Back to index

tetex-bin  3.0
download.c
Go to the documentation of this file.
00001 /*
00002  *   Code to download a font definition at the beginning of a section.
00003  * hacked by SPQR 8.95 to allow for non-partial downloading
00004  *
00005  */
00006 #include "dvips.h" /* The copyright notice in that file is included too! */
00007 #ifndef DOWNLOAD_USING_PDFTEX
00008 #define DOWNLOAD_USING_PDFTEX
00009 #endif
00010 #ifndef DOWNLOAD_USING_PDFTEX
00011 #include "t1part.h"
00012 #endif
00013 #define DVIPS
00014 /*
00015  *   These are the external routines we call.
00016  */
00017 #include "protos.h"
00018 /*
00019  *   These are the external variables we access.
00020  */
00021 extern char *nextstring, *infont ;
00022 extern FILE *bitfile ;
00023 extern fontdesctype *curfnt ;
00024 extern long bytesleft ;
00025 extern long mbytesleft ;
00026 extern quarterword *raster ;
00027 extern quarterword *mraster ;
00028 extern Boolean compressed ;
00029 extern Boolean partialdownload ;
00030 extern double mag ;
00031 extern int actualdpi ;
00032 static unsigned char dummyend[8] = { 252 } ;
00033 extern int prettycolumn ;
00034 extern int quiet ;
00035 extern Boolean disablecomments ;
00036 extern real conv ;
00037 
00038 /*
00039  *   We have a routine that downloads an individual character.
00040  */
00041 static int lastccout ;
00042 void downchar P2C(chardesctype *, c, shalfword, cc)
00043 {
00044    register long i, j ;
00045    register halfword cheight, cwidth ;
00046    register long k ;
00047    register quarterword *p ;
00048    register halfword cmd ;
00049    register shalfword xoff, yoff ;
00050    halfword wwidth = 0 ;
00051    register long len ;
00052    int smallchar ;
00053 
00054    p = c->packptr ;
00055    cmd = *p++ ;
00056    if (cmd & 4) {
00057       if ((cmd & 7) == 7) {
00058          cwidth = getlong(p) ;
00059          cheight = getlong(p + 4) ;
00060          xoff = getlong(p + 8) ;
00061          yoff = getlong(p + 12) ;
00062          p += 16 ;
00063       } else {
00064          cwidth = p[0] * 256 + p[1] ;
00065          cheight = p[2] * 256 + p[3] ;
00066          xoff = p[4] * 256 + p[5] ; /* N.B.: xoff, yoff are signed halfwords */
00067          yoff = p[6] * 256 + p[7] ;
00068          p += 8 ;
00069       }
00070    } else {
00071       cwidth = *p++ ;
00072       cheight = *p++ ;
00073       xoff = *p++ ;
00074       yoff = *p++ ;
00075       if (xoff > 127)
00076          xoff -= 256 ;
00077       if (yoff > 127)
00078          yoff -= 256 ;
00079    }
00080    if (c->flags & BIGCHAR)
00081       smallchar = 0 ;
00082    else
00083       smallchar = 5 ;
00084    if (compressed) {
00085       len = getlong(p) ;
00086       p += 4 ;
00087    } else {
00088       wwidth = (cwidth + 15) / 16 ;
00089       i = 2 * cheight * (long)wwidth ;
00090       if (i <= 0)
00091          i = 2 ;
00092       i += smallchar ;
00093       if (mbytesleft < i) {
00094          if (mbytesleft >= RASTERCHUNK)
00095             (void) free((char *) mraster) ;
00096          if (RASTERCHUNK > i) {
00097             mraster = (quarterword *)mymalloc((integer)RASTERCHUNK) ;
00098             mbytesleft = RASTERCHUNK ;
00099          } else {
00100             k = i + i / 4 ;
00101             mraster = (quarterword *)mymalloc((integer)k) ;
00102             mbytesleft = k ;
00103          }
00104       }
00105       k = i;
00106       while (k > 0)
00107          mraster[--k] = 0 ;
00108       unpack(p, (halfword *)mraster, cwidth, cheight, cmd) ;
00109       p = mraster ;
00110       len = i - smallchar ;
00111    }
00112    if (cheight == 0 || cwidth == 0 || len == 0) {
00113       cwidth = 1 ;
00114       cheight = 1 ;
00115       wwidth = 1 ;
00116       len = 2 ;
00117       if (compressed)
00118          p = dummyend ;  /* CMD(END); see repack.c */
00119       else
00120          mraster[0] = 0 ;
00121    }
00122    if (smallchar) {
00123       p[len] = cwidth ;
00124       p[len + 1] = cheight ;
00125       p[len + 2] = xoff + 128 ;
00126       p[len + 3] = yoff + 128 ;
00127       p[len + 4] = c->pixelwidth ;
00128    } else
00129 /*
00130  *   Now we actually send out the data.
00131  */
00132       specialout('[') ;
00133    if (compressed) {
00134       specialout('<') ;
00135       mhexout(p, len + smallchar) ;
00136       specialout('>') ;
00137    } else {
00138       i = (cwidth + 7) / 8 ;
00139       if (i * cheight > 65520) {
00140          long bc = 0 ;
00141          specialout('<') ;
00142          for (j=0; j<cheight; j++) {
00143             if (bc + i > 65520) {
00144                specialout('>') ;
00145                specialout('<') ;
00146                bc = 0 ;
00147             }
00148             mhexout(p, i) ;
00149             bc += i ;
00150             p += 2*wwidth ;
00151          }
00152          specialout('>') ;
00153       } else {
00154          specialout('<') ;
00155          if (2 * wwidth == i)
00156             mhexout(p, ((long)cheight) * i + smallchar) ;
00157          else {
00158             for (j=0; j<cheight; j++) {
00159                mhexout(p, i) ;
00160                p += 2*wwidth ;
00161             }
00162             if (smallchar)
00163                mhexout(p, (long)smallchar) ;
00164          }
00165          specialout('>') ;
00166       }
00167    }
00168    if (smallchar == 0) {
00169       numout((integer)cwidth) ;
00170       numout((integer)cheight) ;
00171       numout((integer)xoff + 128) ; /* not all these casts needed. */
00172       numout((integer)yoff + 128) ;
00173       numout((integer)(c->pixelwidth)) ;
00174    }
00175    if (lastccout + 1 == cc) {
00176       cmdout("I") ;
00177    } else {
00178       numout((integer)cc) ;
00179       cmdout("D") ;
00180    }
00181    lastccout = cc ;
00182 }
00183 /*
00184  * Output the literal name of the font change command with PostScript index n
00185  */
00186 static char goodnames[] =
00187    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ;
00188 void
00189 makepsname P2C(register char *, s, register int, n)
00190 {
00191    n-- ;
00192    *s++ = 'F' + n / (sizeof(goodnames)-1) ;
00193    *s++ = goodnames[n % (sizeof(goodnames)-1)] ;
00194    *s++ = 0 ;
00195 }
00196 void
00197 lfontout P1C(int, n)
00198 {
00199        char buf[10];
00200         char *b = buf ;
00201         *b++ = '/' ;
00202         makepsname(b, n) ;
00203        cmdout(buf);
00204 }
00205 
00206 /*
00207  *   And the download procedure.
00208  */
00209 void download P2C(charusetype *, p, int, psfont)
00210 {
00211    register int b, i ;
00212    register halfword bit ;
00213    register chardesctype *c ;
00214    int cc, maxcc = -1, numcc ;
00215    double fontscale ;
00216    char name[10] ;
00217    lastccout = -5 ;
00218    name[0] = '/' ;
00219    makepsname(name + 1, psfont) ;
00220    curfnt = p->fd ;
00221    curfnt->psname = psfont ;
00222    if (curfnt->resfont) {
00223       struct resfont *rf = curfnt->resfont ;
00224       int non_empty=0;
00225       for (b=0; b<16; b++)
00226         if(p->bitmap[b] !=0)
00227             non_empty =1;
00228       if(non_empty==0 && curfnt->codewidth==1)
00229         return;
00230       cmdout(name) ;
00231 /* following code re-arranged - Rob Hutchings 1992Apr02 */
00232       c = curfnt->chardesc + 255 ;
00233       cc = 255 ;
00234       numcc = 0 ;
00235       i = 0 ;
00236       for (b=15; b>=0; b--) {
00237          for (bit=1; bit; bit<<=1) {
00238              if (p->bitmap[b] & bit) {
00239                if (i > 0) {
00240                   numout((integer)i) ;
00241                   specialout('[') ;
00242                   i = 0 ;
00243                }
00244                numout((integer)c->pixelwidth) ;
00245                c->flags |= EXISTS ;
00246                numcc++ ;
00247             } else {
00248                i++ ;
00249                c->flags &= ~EXISTS ;
00250             }
00251             c-- ;
00252             cc-- ;
00253          }
00254       }
00255       if (i > 0) {
00256          numout((integer)i) ;
00257          specialout('[') ;
00258       }
00259       specialout ('{') ;
00260       if (rf->specialinstructions)
00261          cmdout(rf->specialinstructions) ;
00262       specialout ('}') ;
00263       numout((integer)numcc) ;
00264       /*
00265        *   This code has been bogus for a long time.  The fix is
00266        *   straightforward.  The input, curfnt->scaledsize, is the
00267        *   desired size of the font in dvi units.  The output is the
00268        *   fontscale, which is the height of the font in output units
00269        *   which are simply pixels.  Thus, all we need to do is multiply
00270        *   by the default generic conv, which properly takes into
00271        *   account magnification, num/den, output resolution, and so on.
00272        *   Sorry this bug has been in here so long.   -tgr
00273        */
00274       fontscale = curfnt->scaledsize * conv ;
00275       (void)sprintf(nextstring, "%g", fontscale) ;
00276       cmdout(nextstring) ;
00277       (void)strcpy(nextstring, "/") ;
00278       (void)strcat(nextstring, rf->PSname) ;
00279       cmdout(nextstring) ;
00280 /* end of changed section - Rob */
00281       cmdout("rf") ;
00282       rf->sent = 1 ;
00283       return ;
00284    }
00285 /*
00286  *   Here we calculate the largest character actually used, and
00287  *   send it as a parameter to df.
00288  */
00289    cc = 0 ;
00290    numcc = 0 ;
00291    for (b=0; b<16; b++) {
00292       for (bit=32768; bit!=0; bit>>=1) {
00293          if (p->bitmap[b] & bit) {
00294             maxcc = cc ;
00295             numcc++ ;
00296          }
00297          cc++ ;
00298       }
00299    }
00300    if (numcc <= 0)
00301       return ;
00302    fontscale = ((double)(curfnt->scaledsize)) / 65536.0 ;
00303    fontscale *= (mag/1000.0) ;
00304    newline() ;
00305    fprintf(bitfile, "%%DVIPSBitmapFont: %s %s %g %d\n", name+1, curfnt->name,
00306                      fontscale, numcc) ;
00307    cmdout(name) ;
00308    numout((integer)numcc) ;
00309    numout((integer)maxcc + 1) ;
00310 /*
00311  *   If we need to scale the font, we say so by using dfs
00312  *   instead of df, and we give it a scale factor.  We also
00313  *   scale the character widths; this is ugly, but scaling
00314  *   fonts is ugly, and this is the best we can probably do.
00315  */
00316    if (curfnt->dpi != curfnt->loadeddpi) {
00317       numout((integer)curfnt->dpi) ;
00318       numout((integer)curfnt->loadeddpi) ;
00319       if (curfnt->alreadyscaled == 0) {
00320          for (b=0, c=curfnt->chardesc; b<256; b++, c++)
00321             c->pixelwidth = (c->pixelwidth * 
00322       (long)curfnt->dpi * 2 + curfnt->loadeddpi) / (2 * curfnt->loadeddpi) ;
00323          curfnt->alreadyscaled = 1 ;
00324       }
00325       cmdout("dfs") ;
00326    } else
00327       cmdout("df") ;
00328    c = curfnt->chardesc ;
00329    cc = 0 ;
00330    for (b=0; b<16; b++) {
00331       for (bit=32768; bit; bit>>=1) {
00332          if (p->bitmap[b] & bit) {
00333             downchar(c, cc) ;
00334             c->flags |= EXISTS ;
00335          } else
00336             c->flags &= ~EXISTS ;
00337          c++ ;
00338          cc++ ;
00339       }
00340    }
00341    cmdout("E") ;
00342    newline() ;
00343    fprintf(bitfile, "%%EndDVIPSBitmapFont\n") ;
00344 }
00345 /*
00346  *   Magic code to deal with PostScript font partial downloading.
00347  *   We track the encodings we've seen so far and keep them in these
00348  *   structures.  We rely on writet1 to load the encodings for us.
00349  */
00350 static struct seenEncodings {
00351    struct seenEncodings *next ;
00352    char *name ;
00353    char **glyphs ;
00354 } *seenEncodings ;
00355 #define MAX_CHAR_CODE 256
00356 /*
00357  *   Load a new encoding and return the array of glyphs as a vector.
00358  *   Linear search.
00359  */
00360 static char **getEncoding(char *encoding) {
00361    struct seenEncodings *p = seenEncodings ;
00362    while (p != 0)
00363       if (strcmp(encoding, p->name) == 0)
00364          break ;
00365       else
00366          p = p->next ;
00367    if (p == 0) {
00368       int i ;
00369       p = (struct seenEncodings *)mymalloc(sizeof(struct seenEncodings)) ;
00370       p->next = seenEncodings ;
00371       seenEncodings = p ;
00372       p->name = xstrdup(encoding) ;
00373       p->glyphs = (char **)mymalloc((MAX_CHAR_CODE+1) * sizeof(char *)) ;
00374       for (i=0; i<MAX_CHAR_CODE; i++)
00375          p->glyphs[i] = ".notdef" ;
00376       load_enc(encoding, p->glyphs) ;
00377    }
00378    return p->glyphs ;
00379 }
00380 /*
00381  *   When partially downloading a type 1 font, sometimes the font uses
00382  *   the built-in encoding (which we don't know at this point) so we want
00383  *   to subset it by character code.  Sometimes the font uses a different
00384  *   encoding, so we want to subset it by glyph.  These routines manage
00385  *   accumulating all the glyph names for a particular font from all
00386  *   the various uses into a single, slash-delimited string for writet1().
00387  *
00388  *   If no glyphs have been added, extraGlyphs is null.  In all cases,
00389  *   the memory allocated for this is in extraGlyphSpace.
00390  */
00391 static char *extraGlyphs = 0 ;
00392 #ifdef DOWNLOAD_USING_PDFTEX
00393 static char *extraGlyphSpace = 0 ;
00394 static int extraGlyphSize = 0 ;
00395 static int glyphSizeUsed = 0 ;
00396 /*
00397  *   We want to make sure we pass in null or "/" but never "".  
00398  */
00399 static void clearExtraGlyphList() {
00400    glyphSizeUsed = 0 ;
00401    extraGlyphs = 0 ;
00402 }
00403 /*
00404  *   Add the glyph name; make sure it hasn't been added already.
00405  *   We do this by adding it, so we can get the // around it,
00406  *   and *then* see if it's already there and if it is un-add it.
00407  */
00408 static void addGlyph(char *glyphName) {
00409    int len = strlen(glyphName) ;
00410    char *startOfAdd = 0 ;
00411    if (len + glyphSizeUsed + 3 > extraGlyphSize) {
00412       extraGlyphSize = 2 * (extraGlyphSize + len + 100) ;
00413       extraGlyphSpace = (char *) xrealloc(extraGlyphSpace, extraGlyphSize) ;
00414    }
00415    extraGlyphs = extraGlyphSpace ;
00416    if (glyphSizeUsed == 0) {
00417       startOfAdd = extraGlyphs + glyphSizeUsed ;
00418       extraGlyphs[glyphSizeUsed++] = '/' ; /* leading / */
00419    } else {
00420       startOfAdd = extraGlyphs + glyphSizeUsed - 1 ;
00421    }
00422    strcpy(extraGlyphs + glyphSizeUsed, glyphName) ;
00423    glyphSizeUsed += len ;
00424    extraGlyphs[glyphSizeUsed++] = '/' ;    /* trailing / */
00425    extraGlyphs[glyphSizeUsed] = 0 ;
00426    if (strstr(extraGlyphs, startOfAdd) != startOfAdd) { /* already there! */
00427       glyphSizeUsed = startOfAdd - extraGlyphs + 1 ; /* kill the second copy */
00428       extraGlyphs[glyphSizeUsed] = 0 ;
00429    }
00430 }
00431 #endif
00432 /*
00433  *   Download a PostScript font, using partial font downloading if
00434  *   necessary.
00435  */
00436 void downpsfont P2C(charusetype *, p, charusetype *, all)
00437 {
00438 #ifdef DOWNLOAD_USING_PDFTEX
00439     static unsigned char grid[256];
00440 #endif
00441     int GridCount ;
00442     register int b;
00443     register halfword bit ;
00444     register chardesctype *c ;
00445     struct resfont *rf ;
00446     int cc;
00447 
00448     curfnt = p->fd ;
00449     rf = curfnt->resfont ;
00450     if (rf == 0 || rf->Fontfile == NULL)
00451        return ;
00452     for (; all->fd; all++)
00453        if (all->fd->resfont &&
00454            strcmp(rf->PSname, all->fd->resfont->PSname) == 0)
00455           break ;
00456     if (all != p)
00457        return ;
00458     if (rf->sent == 2) /* sent as header, from a PS file */
00459        return ;
00460     if (all->fd == 0)
00461        error("! internal error in downpsfont") ;
00462     if (!partialdownload) {
00463         infont = all->fd->resfont->PSname ;
00464        copyfile(all->fd->resfont->Fontfile);
00465         infont = 0 ;
00466        return;
00467     }
00468     for (cc=0; cc<256; cc++)
00469        grid[cc] = 0 ;
00470 #ifdef DOWNLOAD_USING_PDFTEX
00471     clearExtraGlyphList() ;
00472 #endif
00473     for (; all->fd; all++) {
00474         if (all->fd->resfont == 0 ||
00475             strcmp(rf->PSname, all->fd->resfont->PSname))
00476            continue ;
00477         curfnt = all->fd ;
00478 #ifdef DOWNLOAD_USING_PDFTEX
00479         if (curfnt->resfont->Vectfile) {
00480           char **glyphs = getEncoding(curfnt->resfont->Vectfile) ;
00481            c = curfnt->chardesc + 255 ;
00482            cc = 255 ;
00483            for (b=15; b>=0; b--) {
00484                for (bit=1; bit; bit<<=1) {
00485                    if (all->bitmap[b] & bit) {
00486                     addGlyph(glyphs[cc]) ;
00487                    }
00488                    c-- ;
00489                    cc-- ;
00490                }
00491             }
00492         } else {
00493 #endif
00494            c = curfnt->chardesc + 255 ;
00495            cc = 255 ;
00496            for (b=15; b>=0; b--) {
00497                for (bit=1; bit; bit<<=1) {
00498                    if (all->bitmap[b] & bit) {
00499                        grid[cc]=1;
00500                    }
00501                    c-- ;
00502                    cc-- ;
00503                }
00504             }
00505 #ifdef DOWNLOAD_USING_PDFTEX
00506         }
00507 #endif
00508     }
00509 
00510     for (GridCount=0,cc=0; cc<256; cc++) {
00511 /*      tmpgrid[cc]=grid[cc]; */
00512         if(grid[cc] ==1) {
00513             GridCount++;
00514         }
00515     }
00516     if(GridCount!=0 || extraGlyphs) {
00517         if (!quiet) {
00518            if (strlen(rf->Fontfile) + prettycolumn > STDOUTSIZE) {
00519               fprintf(stderr, "\n") ;
00520               prettycolumn = 0 ;
00521            }
00522            (void)fprintf(stderr, "<%s>", rf->Fontfile);
00523           prettycolumn += strlen(rf->Fontfile) + 2 ;
00524        }
00525         newline() ;
00526         if (! disablecomments)
00527            (void)fprintf(bitfile, "%%%%BeginFont: %s\n",  rf->PSname);
00528 #ifdef DOWNLOAD_USING_PDFTEX
00529         if (!t1_subset_2(rf->Fontfile, grid, extraGlyphs))
00530 #else
00531         if(FontPart(bitfile, rf->Fontfile, rf->Vectfile) < 0)
00532 #endif
00533             exit(1);
00534         if (! disablecomments)
00535            (void)fprintf(bitfile, "%%%%EndFont \n");
00536    }
00537 }
00538 
00539 void dopsfont P1C(sectiontype *, fs)
00540 {
00541     charusetype *cu ;
00542 
00543     cu = (charusetype *) (fs + 1) ;
00544 #ifdef DOWNLOAD_USING_PDFTEX
00545     while (cu->fd) {
00546        if (cu->psfused)
00547           cu->fd->psflag = EXISTS ;
00548        downpsfont(cu++, (charusetype *)(fs + 1)) ;
00549     }
00550 #else
00551     line = getmem(BUFSIZ);
00552     tmpline=line;
00553     while (cu->fd) {
00554        if (cu->psfused)
00555           cu->fd->psflag = EXISTS ;
00556        downpsfont(cu++, (charusetype *)(fs + 1)) ;
00557     }
00558     loadbase = ~FLG_LOAD_BASE;
00559     FirstCharB=UnDefineChars(FirstCharB);
00560     free(tmpline);
00561 #endif
00562 }