home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / wp_dtp / atap.lha / ATAP / SourceCode / WriteMetricsVector.c < prev   
Text File  |  1992-06-13  |  11KB  |  417 lines

  1. #define    KERNING_AVAILABLE    0x0268
  2. #define    X_WIDTHS_AVAILABLE    0x0068
  3. #define    AMIGA_STANDARD        0x0101
  4. #define    FONT_SPECIFIC        0x0100
  5.  
  6. ULONG WriteMetricsVector(char *afmFilename, int typeWeight)
  7.  
  8. /* This function is the heart of ConvertAFM. It creates what I
  9.    call a "Metrics Vector"; a complete .metric structure with all
  10.    typeface information, character widths, and kerning tables.
  11.  
  12.    It creates a file in T: named by the AFM's typeface name. 
  13.    It contains the complete metrics vector except for the
  14.    typeface style, which you must supply in typeWeight. It
  15.    also returns the length of the file. */
  16.  
  17. {
  18. static    WORD        kerningTables[256][256];
  19. static    char        kerningCheckList[16384];
  20. static    char        currentList[256],*kerningArray,*incomingString,headerCheck[26],encodingScheme[20],intString[4][20],metricFilename[26],typefaceName[68],*intChars;
  21. static    WORD        metricInfo[18],xWidths[256],kerningPointers[256];
  22. static    FILE        *afmFile,*metricFile;
  23. static    int        test,test2,test3,test4,test5,asciiCode,asciiCode2,xWidth,kerningArrayLength,currentOffset;
  24. static    ULONG        vectorLength;
  25. static    UWORD        index,index2;
  26. static    BOOL        goodfit;
  27.  
  28.     for (index=0;index<18;index++)
  29.         metricInfo[index]=0;
  30.     for(index=0;index<68;index++)
  31.         typefaceName[index]=0;
  32.     metricInfo[0]=X_WIDTHS_AVAILABLE;
  33.     for (index=0;index<256;index++)
  34.         xWidths[index]=0;
  35.  
  36.     afmFile=fopen(afmFilename,"r");
  37.  
  38.     if (afmFile==0)
  39.     {
  40.         fclose(afmFile);
  41.         return(0);
  42.     }
  43.  
  44. /* If the AFM file didn't exist, it returns a vectorLength
  45.    of zero. Logical, yes? A non-existant file with zero length? */
  46.  
  47.     headerCheck[0]=0;
  48.     test=-1;
  49.     while(test!=0)
  50.     {
  51.         incomingString=freadline(afmFile);
  52.         sscanf(incomingString,"%s\n",headerCheck);
  53.         test=strcmp(headerCheck,"FontName");
  54.     }
  55.     sscanf(incomingString,"%s %s",headerCheck,typefaceName);
  56.  
  57.     test=-1;
  58.     while(test!=0)
  59.     {
  60.         incomingString=freadline(afmFile);
  61.         sscanf(incomingString,"%s ",headerCheck);
  62.         test=strcmp(headerCheck,"EncodingScheme");
  63.     }
  64.     sscanf(incomingString,"%s %s",headerCheck,encodingScheme);
  65.     test=strcmp(encodingScheme,"FontSpecific");
  66.     test2=strcmp(encodingScheme,"AppleStandard");
  67.     if (test==0 || test2==0)
  68.         metricInfo[6]=FONT_SPECIFIC;
  69.     else
  70.         metricInfo[6]=AMIGA_STANDARD;
  71.     fsetpos(afmFile,0);
  72.  
  73. /* I gotta do this for every parameter I require! Ugh! */
  74.  
  75.     test=-1;
  76.     while(test!=0)
  77.     {
  78.         incomingString=freadline(afmFile);
  79.         sscanf(incomingString,"%s ",headerCheck);
  80.         test=strcmp(headerCheck,"UnderlinePosition");
  81.     }
  82.     sscanf(incomingString,"%s %s",headerCheck,intString[0]);
  83.     metricInfo[11]=atoi(intString[0]);
  84.  
  85.     test=-1;
  86.     while(test!=0)
  87.     {
  88.         incomingString=freadline(afmFile);
  89.         sscanf(incomingString,"%s ",headerCheck);
  90.         test=strcmp(headerCheck,"UnderlineThickness");
  91.     }
  92.     sscanf(incomingString,"%s %s",headerCheck,intString[0]);
  93.     metricInfo[12]=atoi(intString[0]);
  94.  
  95.     test=-1;
  96.     while(test!=0)
  97.     {
  98.         incomingString=freadline(afmFile);
  99.         sscanf(incomingString,"%s ",headerCheck);
  100.         test=strcmp(headerCheck,"FontBBox");
  101.     }
  102.     sscanf(incomingString,"%s %s %s %s %s",headerCheck,intString[0],intString[1],intString[2],intString[3]);
  103.     for (index=0;index<4;index++)
  104.         metricInfo[index+7]=atoi(intString[index]);
  105.  
  106. /* Some typefaces won't have letter-like qualities, like
  107.    cap height, x-height, etc. So, if the very next line is
  108.    "StartCharMetrics", then it creates these values based
  109.    on the Font Bounding Box. */
  110.  
  111.     test=-1;
  112.     incomingString=freadline(afmFile);
  113.     sscanf(incomingString,"%s ",headerCheck);
  114.     test=strcmp(headerCheck,"StartCharMetrics");
  115.  
  116.     if (test!=0)
  117.     {
  118.         test2=-1;
  119.         while(test2!=0)
  120.         {
  121.             sscanf(incomingString,"%s ",headerCheck);
  122.             test2=strcmp(headerCheck,"CapHeight");
  123.         }
  124.         sscanf(incomingString,"%s %s",headerCheck,intString[0]);
  125.         metricInfo[13]=atoi(intString[0]);
  126.     
  127.         test2=-1;
  128.         while(test2==0)
  129.         {
  130.             incomingString=freadline(afmFile);
  131.             sscanf(incomingString,"%s ",headerCheck);
  132.             test2=strcmp(headerCheck,"XHeight");
  133.         }
  134.         sscanf(incomingString,"%s %s",headerCheck,intString[0]);
  135.         metricInfo[14]=atoi(intString[0]);
  136.     
  137.         test2=-1;
  138.         while(test2!=0)
  139.         {
  140.             incomingString=freadline(afmFile);
  141.             sscanf(incomingString,"%s ",headerCheck);
  142.             test2=strcmp(headerCheck,"Descender");
  143.         }
  144.         sscanf(incomingString,"%s %s",headerCheck,intString[0]);
  145.         metricInfo[16]=atoi(intString[0]);
  146.     
  147.         test2=-1;
  148.         while(test2!=0)
  149.         {
  150.             incomingString=freadline(afmFile);
  151.             sscanf(incomingString,"%s ",headerCheck);
  152.             test2=strcmp(headerCheck,"Ascender");
  153.         }
  154.         sscanf(incomingString,"%s %s",headerCheck,intString[0]);
  155.         metricInfo[15]=atoi(intString[0]);
  156.  
  157.         incomingString=freadline(afmFile);
  158.         sscanf(incomingString,"%s %s",headerCheck,intString[0]);
  159.  
  160.     }
  161.     else
  162.     {
  163.         for (index=13;index<17;index++)
  164.             metricInfo[index]=0;
  165.         sscanf(incomingString,"%s %s",headerCheck,intString[0]);
  166.         metricInfo[16]=metricInfo[8];
  167.         for (index=13;index<16;index++)
  168.             metricInfo[index]=metricInfo[8]+metricInfo[10];
  169.     }
  170.  
  171.     metricInfo[17]=typeWeight;
  172.     
  173. /* By now we're on the very first line of x-widths. 
  174.    We start by comparing all the chars to either Amiga Standard
  175.    or Apple Standard encoding and arrange the X-widths in an
  176.    ASCII format. The check arrays #included are used for this.
  177.    If the typeface has Font Specific encoding the ASCII values
  178.    are used directly. */
  179.  
  180.     vectorLength=104;
  181.     if (metricInfo[6]==FONT_SPECIFIC)
  182.     {
  183.         test2=-1;
  184.         incomingString=freadline(afmFile);
  185.         while (test2!=0)
  186.         {
  187.             sscanf(incomingString,"C %s ; WX %s ",intString[0],intString[1]);
  188.             asciiCode=atoi(intString[0]);
  189.             if (asciiCode!=-1)
  190.                 xWidths[asciiCode]=atoi(intString[1]);
  191.             
  192.             incomingString=freadline(afmFile);
  193.             test2=strcmp(incomingString,"EndCharMetrics");
  194.         }
  195.         vectorLength=vectorLength+256*2;
  196.     }
  197.     else
  198.     {
  199.         test2=-1;
  200.         incomingString=freadline(afmFile);
  201.         while (test2!=0)
  202.         {
  203.             sscanf(incomingString,"C %s ; WX %s ; N %s ",intString[0],intString[1],intString[2]);
  204.             index=0;asciiCode=-1;
  205.             while (asciiCode==-1 && index<256)
  206.             {
  207.                 test=strcmp(amigaEncoding[index],intString[2]);
  208.                 if (test==0)
  209.                     asciiCode=index;
  210.                 else
  211.                     index=index+1;
  212.             }
  213.             if (asciiCode!=-1)
  214.                 xWidths[asciiCode]=atoi(intString[1]);
  215.  
  216.             incomingString=freadline(afmFile);
  217.             test2=strcmp(incomingString,"EndCharMetrics");
  218.         }
  219.         vectorLength=vectorLength+256*2;
  220.     }
  221.  
  222. /* If this is any type of standard encoding, I look for kerning
  223.    tables. This means AdobeStandard, AppleStandard, or whatever.
  224.  
  225.    NOTE: Font Specific encoded typefaces CANNOT have kerning
  226.    tables or this program will ignore them. To add kerning to
  227.    a font specific encoded typeface, you'll have to wait for
  228.    my kerning pair editor to be released. 
  229.  
  230.    Anyway, on to kerning pair decyphering. */
  231.  
  232.     test=-1;test2=-1;
  233.     while (test!=0 && test2!=0)
  234.     {
  235.         incomingString=freadline(afmFile);
  236.         test=strcmp(incomingString,"StartKernData");
  237.         test2=strcmp(incomingString,"EndFontMetrics");
  238.     }
  239.     test2=strcmp(encodingScheme,"FontSpecific");
  240.     if (test==0 && test2!=0)
  241.     {
  242.  
  243.         for (index=0;index<256;index++)
  244.             for (index2=0;index2<256;index2++)
  245.                 kerningTables[index][index2]=0;
  246.  
  247.         test3=-1;
  248.         while (test3!=0)
  249.         {
  250.             incomingString=freadline(afmFile);
  251.             sscanf(incomingString,"%s ",headerCheck);
  252.             test3=strcmp(headerCheck,"StartKernPairs");
  253.         }
  254.         test3=-1;
  255.         incomingString=freadline(afmFile);
  256.         test=strcmp(incomingString,"EndKernPairs");
  257.         while (test3!=0)
  258.         {
  259.             sscanf(incomingString,"%s ",headerCheck);
  260.             test4=strcmp(headerCheck,"KPX");
  261.             if (test4==0)
  262.             {
  263.                 sscanf(incomingString,"KPX %s %s %s",intString[0],intString[1],intString[2]);
  264.                 index=0;asciiCode=-1;
  265.                 while (asciiCode==-1 && index<256)
  266.                 {
  267.                     test5=strcmp(amigaEncoding[index],intString[0]);
  268.                     if (test5==0)
  269.                         asciiCode=index;
  270.                     else
  271.                         index=index+1;
  272.                 }
  273.                 index=0;asciiCode2=-1;
  274.                 while (asciiCode2==-1 && index<256)
  275.                 {
  276.                     test5=strcmp(amigaEncoding[index],intString[1]);
  277.                     if (test5==0)
  278.                         asciiCode2=index;
  279.                     else
  280.                         index=index+1;
  281.                 }
  282.                 kerningTables[asciiCode][asciiCode2]=atoi(intString[2]);
  283.             }
  284.             incomingString=freadline(afmFile);
  285.             test3=strcmp(incomingString,"EndKernPairs");
  286.         }
  287.         for (index=0;index<256;index++)
  288.             for (index2=0;index2<256;index2++)
  289.                 if (kerningTables[index][index2]!=0)
  290.                 {
  291.                     kerningPointers[index]=256;
  292.                     index2=256;
  293.                 }
  294.                 else
  295.                     kerningPointers[index]=0;
  296.  
  297. /* Since making a separate function for encoding the kerning
  298.    array doesn't work with DICE (UGH!) I have to include it
  299.    here. */
  300.  
  301.         for (index=0;index<16384;index++)
  302.             kerningCheckList[index]=32;
  303.         /* kerningCheckList nulled to spaces. */
  304.     
  305.         kerningArrayLength=256;
  306.  
  307.         for (index=0;index<256;index++)
  308.         {
  309.             if (kerningPointers[index]!=0)
  310.             {
  311.                 for (index2=0;index2<256;index2++)
  312.                 {
  313.                     if (kerningTables[index][index2]!=0)
  314.                         currentList[index2]=index;
  315.                     else
  316.                         currentList[index2]=32;
  317.                 }
  318.                 /* CurrentList created. */
  319.                 goodfit=TRUE;currentOffset=0;
  320.                 for (index2=0;index2<256;index2++)
  321.                 {
  322.                     if (currentList[index2]!=32 && kerningCheckList[index2]!=32)
  323.                     {
  324.                         goodfit=FALSE;
  325.                         index2=256;
  326.                     }
  327.                 }
  328.                 while (goodfit==FALSE)
  329.                 {
  330.                     currentOffset=currentOffset+1;
  331.                     for (index2=0;index2<256;index2++)
  332.                     {
  333.                         if (currentList[index2]!=32 && kerningCheckList[index2+currentOffset]!=32)
  334.                         {
  335.                             goodfit=FALSE;
  336.                             index2=256;
  337.                         }
  338.                         else
  339.                             goodfit=TRUE;
  340.                     }
  341.                 }
  342.  
  343. /* A good fit was found. Record the offset and insert
  344.    into the check array. */
  345.  
  346.                 for (index2=0;index2<256;index2++)
  347.                     if (currentList[index2]!=32)
  348.                         kerningCheckList[index2+currentOffset]=currentList[index2];
  349.  
  350.                 kerningPointers[index]=kerningPointers[index]+currentOffset;
  351.                 if (kerningArrayLength < currentOffset+256)
  352.                     kerningArrayLength=kerningArrayLength+(currentOffset+256-kerningArrayLength);
  353.             }
  354. /* NEXT! */
  355.         }
  356.         for (index=0;index<256;index++)
  357.             if (kerningPointers[index]!=0)
  358.             {
  359.                 vectorLength=vectorLength+256*4+kerningArrayLength*4;
  360.                 metricInfo[2]=KERNING_AVAILABLE;
  361.                 index=256;
  362.             }
  363.         
  364.     }
  365.  
  366.     fclose(afmFile);
  367.  
  368.     strcpy(metricFilename,"T:");
  369.     strcat(metricFilename,typefaceName);
  370.     metricFile=fopen(metricFilename,"w");
  371.  
  372.     for (index=0;index<68;index++)
  373.         fputc(typefaceName[index],metricFile);
  374.  
  375.     for (index=0;index<18;index++)
  376.     {
  377.         intChars=&metricInfo[index];
  378.         fprintf(metricFile,"%c%c",intChars[0],intChars[1]);
  379.     }
  380.  
  381.     for (index=0;index<256;index++)
  382.     {
  383.         intChars=&xWidths[index];
  384.         fprintf(metricFile,"%c%c",intChars[0],intChars[1]);
  385.     }
  386.  
  387.      if (metricInfo[2]==KERNING_AVAILABLE)
  388.     {
  389.         for (index=0;index<256;index++)
  390.             if (kerningPointers[index]!=0)
  391.             {
  392.                 intChars=&kerningPointers[index];
  393.                 fprintf(metricFile,"%c%c%c%c",intChars[0],intChars[1],0,index);
  394.             }
  395.             else
  396.                 fprintf(metricFile,"%c%c%c%c",0,0,0,0);
  397.  
  398.         for (index=0;index<kerningArrayLength;index++)
  399.             if (kerningCheckList[index]!=32)
  400.             {
  401.                 asciiCode=kerningCheckList[index];
  402.                 asciiCode2=index-kerningPointers[asciiCode]+256;
  403.                 intChars=&kerningTables[asciiCode][asciiCode2];
  404.                 fprintf(metricFile,"%c%c%c%c",intChars[0],intChars[1],0,asciiCode);
  405.             }
  406.             else
  407.                 fprintf(metricFile,"%c%c%c%c",0,0,0,0);
  408.  
  409. /* Cheaky way of writing the kerning table, eh? :-) */
  410.  
  411.     }
  412.  
  413.     fclose(metricFile);
  414.     return(vectorLength);
  415.  
  416. };
  417.