home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 443.lha / fontwo / fontwo.c < prev    next >
C/C++ Source or Header  |  1990-12-02  |  9KB  |  326 lines

  1. /* fontwo.c
  2.  * Double the height or width of an Amiga font
  3.  * (C)1989 Ephraim Cohen
  4.  *
  5.  * Compile (Manx Aztec 3.6):
  6.  *  cc +l fontwo.c
  7.  *  ln fontwo.o -lc32
  8.  */
  9. #include <libraries/diskfont.h>
  10. #include <libraries/dos.h>
  11. #include <stdio.h>
  12. #define REV 33
  13.  
  14. char *note[]= {
  15.     "Usage: option font height [Attributes]",
  16.     "Options:",
  17.     "t    Make a tall font (double the height)",
  18.     "w    Make a wide font (double the width)",
  19.     "The name of the new font ends with 'x'",
  20.     "For example",
  21.     "\tfontwo t Topaz 8",
  22.     "will create the font Fonts:Topaz/16wx",
  23.     "Attributes:",
  24.     "e  Extended", "i  Italic", "b  Bold", "u  Underline",
  25.     "t  Tall Dot", "w  Wide Dot", "p  Proportional",
  26.     0};
  27.  
  28. extern struct TextFont *OpenDiskFont();
  29. extern char    *malloc(),
  30.         *OpenLibrary();
  31.  
  32. char    *GfxBase,
  33.     *DiskfontBase;
  34. char    noroom[]= "Not Enough Memory";
  35.  
  36. char    *fontab;    /* The new font body */
  37. long    attab[20];    /* Relocation information */
  38.  
  39. struct TextAttr        tea;
  40. struct TextFont        *tfp;
  41. struct TextFont        new;
  42. struct DiskFontHeader    dfh;
  43.  
  44. getfont(ta)struct TextAttr *ta;{    /* Get a font with these attributes */
  45.     register struct TextFont *tf;
  46.  
  47.     ta->ta_Flags |= FPF_ROMFONT|FPF_DISKFONT|FPF_DESIGNED;
  48.     if(tf= OpenDiskFont(ta)){
  49.         endfont();
  50.         tfp= tf;
  51.         return TRUE;
  52.     }
  53.     return 0;
  54. }
  55. endfont(){                /* Done with this font */
  56.     if(tfp)CloseFont(tfp);    tfp= 0;
  57. }
  58. char *outname(tf, name)register struct TextFont *tf; char *name;{
  59.     /* Create a name for the new font
  60.      * It is the font height, followed by some letters for
  61.      * the attributes, and followed by 'x' (because it's new)
  62.      */
  63.     static char buf[80], attr[12];
  64.     register char *cp= attr;
  65.  
  66.     if(tf->tf_Style&FSF_EXTENDED)*cp++= 'e';
  67.     if(tf->tf_Style&FSF_ITALIC)*cp++= 'i';
  68.     if(tf->tf_Style&FSF_BOLD)*cp++= 'b';
  69.     if(tf->tf_Style&FSF_UNDERLINED)*cp++= 'u';
  70.     if(tf->tf_Flags&FPF_TALLDOT)*cp++= 't';
  71.     if(tf->tf_Flags&FPF_WIDEDOT)*cp++= 'w';
  72.     if(tf->tf_Flags&FPF_PROPORTIONAL)*cp++= 'p';
  73.     *cp= 0;
  74.     sprintf(buf, "Fonts:%s/%d%sx", name, tf->tf_YSize, attr);
  75.     return buf;
  76. }
  77. getatts(name, hi, cp)register char *cp;{
  78.     /* Setup the TextAttr from the arguments */
  79.     static char buf[64];
  80.  
  81.     strcpy(buf, name); strcat(buf, ".font");
  82.     tea.ta_Name= (STRPTR)buf;
  83.     tea.ta_YSize= hi;
  84.     tea.ta_Style= 0;
  85.     tea.ta_Flags= 0;
  86.     if(cp)while(*cp)switch(toupper(*cp++)){
  87.     case 'E':    tea.ta_Style |= FSF_EXTENDED; break;
  88.     case 'I':    tea.ta_Style |= FSF_ITALIC; break;
  89.     case 'B':    tea.ta_Style |= FSF_BOLD; break;
  90.     case 'U':    tea.ta_Style |= FSF_UNDERLINED; break;
  91.     case 'T':    tea.ta_Flags |= FPF_TALLDOT; break;
  92.     case 'W':    tea.ta_Flags |= FPF_WIDEDOT; break;
  93.     case 'P':    tea.ta_Flags |= FPF_PROPORTIONAL; break;
  94.     }
  95. }
  96. char *
  97. opelib(name)char *name;{    /* Open a library--complain if it's absent */
  98.     register char *lib;
  99.  
  100.     aver(lib= OpenLibrary(name,REV), name);
  101.     return lib;
  102. }
  103. openlibs(){            /* Get these libraries */
  104.     GfxBase=    opelib("graphics.library");
  105.     DiskfontBase=     opelib("diskfont.library");
  106. }
  107. main(ac,av)register char **av;{
  108.     BPTR fd;        /* File pointer */
  109.     register size,        /* size of fontab */
  110.         fun;        /* Function (Taller or Wider) */
  111.  
  112.     if(ac<3){
  113. err:        for(av= note; *av; ++av)
  114.             printf("%s\n", *av);
  115.         exit(5);
  116.     }
  117.     getatts(av[2], atoi(av[3]), ac>4? av[4]:0);
  118.     fun= toupper(av[1][0]);
  119.  
  120.     /* Must be Taller or Wider */
  121.     if(fun!='T' && fun!='W')goto err;
  122.  
  123.     openlibs();                /* Get a font */
  124.     getfont(&tea);
  125.     aver(tfp, "No such font/size");
  126.  
  127.     if(fun=='T')taller(tfp);        /* Make a taller version */
  128.     else wider(tfp);            /* or a wider version */
  129.  
  130.     aver(size= makefont(&new), noroom);    /* >>> */
  131.  
  132.     fd= Open(outname(&new, av[2]), MODE_NEWFILE);    /* Write it out */
  133.     aver(fd, "Cannot create the new font");
  134.     aver(writehunx(fd, fontab, size), "Write failed");
  135.     Close(fd);
  136.  
  137.     aver(0,0);                    /* All done */
  138. }
  139. aver(bool, msg)char *msg;{    /* Quit cleanly if bool is false */
  140.     if(bool)return;
  141.     if(msg)printf("?%s\n", msg);
  142.  
  143.     endfont();
  144.     if(GfxBase)CloseLibrary(GfxBase);
  145.     if(DiskfontBase)CloseLibrary(DiskfontBase);
  146.     exit(msg? 5:0);
  147. }
  148. taller(tf)register struct TextFont *tf;{    /* Double the height */
  149.     register char *sp, *dp;
  150.     register x,y;
  151.  
  152.     new= *tf;                /* Copy the original */
  153.     new.tf_YSize *= 2;            /* Double height */
  154.     new.tf_Baseline *= 2;
  155.  
  156.     if(new.tf_Flags&FPF_TALLDOT)        /* It's a wider font now */
  157.         new.tf_Flags &= ~FPF_TALLDOT;
  158.     else    new.tf_Flags |= FPF_WIDEDOT;
  159.     
  160.     aver(dp= (char *)malloc(new.tf_YSize*new.tf_Modulo),noroom);
  161.  
  162.     new.tf_CharData= (APTR)dp;        /* Copy the character data */
  163.     sp= (char *)(tf->tf_CharData);
  164.     for(y= 0; y<tf->tf_YSize; y++){        /* For each scanline:    */
  165.         for(x= 0; x<tf->tf_Modulo; x++)    /*  Copy it once    */
  166.             *dp++= *sp++;
  167.         sp -= tf->tf_Modulo;
  168.         for(x= 0; x<tf->tf_Modulo; x++)    /*  and copy it again    */
  169.             *dp++= *sp++;
  170.     }
  171. }
  172. APTR duexshort(wp, n)register unsigned short *wp;{
  173.     /* Copy and double all the values in a table of unsigned shorts */
  174.     register unsigned short *dp, *dp0;
  175.  
  176.     aver(dp0= dp= (unsigned short *)malloc(n*sizeof(short)), noroom);
  177.     do
  178.         *dp++= (*wp++) << 1;
  179.     while(--n);
  180.     return (APTR)dp0;
  181. }
  182. wider(tf)register struct TextFont *tf;{
  183.     unsigned short widtab[256];
  184.     register unsigned char *cp;
  185.     register unsigned short *wp;
  186.     register x,y;
  187.  
  188.     new= *tf;                /* Copy the original */
  189.     new.tf_Modulo *= 2;
  190.     new.tf_XSize *= 2;
  191.  
  192.     if(new.tf_Flags&FPF_WIDEDOT)        /* It's a taller font now */
  193.         new.tf_Flags &= ~FPF_WIDEDOT;
  194.     else    new.tf_Flags |= FPF_TALLDOT;
  195.  
  196.     for(x= 0; x<256; x++){        /* Make the widening table: */
  197.         widtab[x]= 0;        /* (Look up a byte, get a bbyyttee) */
  198.         for(y= 0; y<8; y++)
  199.             if(x&(1<<y))
  200.                 widtab[x] |= 3 << (y+y);
  201.     }
  202.  
  203.     /* space for the new character data */
  204.     wp= (unsigned short *)malloc(new.tf_YSize*new.tf_Modulo);
  205.     aver(wp ,noroom);
  206.  
  207.     new.tf_CharData= (APTR)wp;        /* Copy and widen: */
  208.     cp= (unsigned char *)(tf->tf_CharData);
  209.     for(y= 0; y<tf->tf_YSize; y++)        /* For each (long) scanline */
  210.         for(x= 0; x<tf->tf_Modulo; x++)
  211.             *wp++= widtab[*cp++];    /* Widen chars to shorts */
  212.  
  213.     y= tf->tf_HiChar + 2 - tf->tf_LoChar;    /* Number of chars in font */
  214.  
  215.     /* Widen and copy the other tables */
  216.     new.tf_CharLoc= duexshort(tf->tf_CharLoc, y+y);
  217.     if(tf->tf_CharSpace)
  218.         new.tf_CharSpace= duexshort(tf->tf_CharSpace, y);
  219.     if(tf->tf_CharKern)
  220.         new.tf_CharKern= duexshort(tf->tf_CharKern, y);
  221. }
  222. addr(at, cp)long *at; char *cp;{
  223.     /* Add a relocation datum, in hackish imitation of an assembler */
  224.     /* When loaded, the contents of at is the address of cp        */
  225.  
  226.     *at= cp-fontab;            /* Location gets offset to data */
  227.     cp= (char *)at;
  228.     attab[attab[1]+3]= cp-fontab;    /* Offset to location        */
  229.     ++attab[1];            /* Count of relocated stuff    */
  230. }
  231. char *
  232. bcopy(dp, sp, n)register char *dp, *sp;{
  233.     /* Copy and return past end of copy */
  234.     do
  235.         *dp++= *sp++;
  236.     while(--n);
  237.     return dp;
  238. }
  239. makefont(tf)register struct TextFont *tf;{
  240.     /* Put together the pieces for a font */
  241.  
  242.     static char rts[]= {0x70, 0xff, 0x4e, 0x75};    /* rts instruction */
  243.     register struct DiskFontHeader *dfh;
  244.     register char *cp, *name;
  245.     register n, size;
  246.  
  247.     /* This is the relocation hunk--start it empty */
  248.     attab[0]= 0x3EC; attab[1]= 0; attab[2]= 0;
  249.  
  250.     /* How long is the font?  */
  251.     n= tf->tf_HiChar + 2 - tf->tf_LoChar;
  252.     size= 4 + sizeof(*dfh) + tf->tf_Modulo*tf->tf_YSize + 4*n;
  253.     if(tf->tf_CharSpace)size+= sizeof(short)*n;
  254.     if(tf->tf_CharKern)size+= sizeof(short)*n;
  255.  
  256.     fontab= (char *)malloc(size);    /* Get and clear the font space */
  257.     if(!fontab)return 0;
  258.     cp= fontab+size;
  259.     do
  260.         *--cp= 0;
  261.     while(cp>fontab);
  262.  
  263.     /* Start with 'return 0' (fonts look just like executables) */
  264.     bcopy(fontab, rts, 4);
  265.  
  266.     /* Next comes this structure: */
  267.     dfh= (struct DiskFontHeader *)(&fontab[4]);
  268.     dfh->dfh_DF.ln_Type= NT_FONT;
  269.     addr(&dfh->dfh_DF.ln_Name, dfh->dfh_Name);
  270.     dfh->dfh_FileID= DFH_ID;
  271.     dfh->dfh_Revision= 1;
  272.     dfh->dfh_Segment= 0;
  273.     strncpy(dfh->dfh_Name,tf->tf_Message.mn_Node.ln_Name,MAXFONTNAME);
  274.  
  275.     dfh->dfh_TF= *tf;
  276.     dfh->dfh_TF.tf_Message.mn_Node.ln_Succ= 0;
  277.     dfh->dfh_TF.tf_Message.mn_Node.ln_Pred= 0;
  278.     dfh->dfh_TF.tf_Message.mn_Node.ln_Type= NT_FONT;
  279.     addr(&dfh->dfh_TF.tf_Message.mn_Node.ln_Name, dfh->dfh_Name);
  280.     dfh->dfh_TF.tf_Message.mn_ReplyPort= 0;
  281.     dfh->dfh_TF.tf_Accessors= 0;
  282.  
  283.     /* Now comes font data--copy it in */
  284.     cp= fontab + sizeof(*dfh) + sizeof(long);
  285.  
  286.     addr(&dfh->dfh_TF.tf_CharData, cp);
  287.     cp= bcopy(cp, tf->tf_CharData, tf->tf_Modulo*tf->tf_YSize);
  288.  
  289.     addr(&dfh->dfh_TF.tf_CharLoc, cp);
  290.     cp= bcopy(cp, tf->tf_CharLoc, n*2*sizeof(short));
  291.  
  292.     if(tf->tf_CharSpace){
  293.         addr(&dfh->dfh_TF.tf_CharSpace, cp);
  294.         cp= bcopy(cp, tf->tf_CharSpace, n*sizeof(short));
  295.     }
  296.     if(tf->tf_CharKern){
  297.         addr(&dfh->dfh_TF.tf_CharKern, cp);
  298.         cp= bcopy(cp, tf->tf_CharKern, n*sizeof(short));
  299.     }
  300.     /* Now set the size of all this stuff */
  301.     dfh->dfh_TF.tf_Message.mn_Length= cp - ((char *)(&dfh->dfh_TF));
  302.  
  303.     return size;
  304. }
  305. writehunx(fd, cp, size)BPTR fd; char *cp;{
  306.     /* Write the font hunks */
  307.     static long hunkstat[]= {    /* Pre-canned program header */
  308.     0x000003F3, 0x00000000, 0x00000001, 0x00000000,
  309.     0x00000000, 0x000000FE, 0x000003E9, 0x000000FE};
  310.  
  311.         size= (size+3) >>2;
  312.     hunkstat[5]= size;    /* Put sizes in the header */
  313.     hunkstat[7]= size;    /* (now we pretend we're a linker) */
  314.  
  315.     /* Write the header */
  316.     if(Write(fd, hunkstat, sizeof(hunkstat))<0)return 0;
  317.  
  318.     /* Font body as a code hunk */
  319.     if(Write(fd, cp, size<<2)<0)return 0;
  320.  
  321.     /* Relocation hunk */
  322.     attab[attab[1]+3]= 0;
  323.     attab[attab[1]+4]= 0x3F2;
  324.     if(Write(fd, attab, (attab[1]+5)<<2)<0)return 0;
  325. }
  326.