Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione 3.1 patch 650 git-svn-id: svn://10.65.10.50/trunk@14148 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			784 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			784 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*---------------------------------------------------------------------------*
 | |
|  |              PDFlib - A library for generating PDF on the fly             |
 | |
|  +---------------------------------------------------------------------------+
 | |
|  | Copyright (c) 1997-2005 Thomas Merz and PDFlib GmbH. All rights reserved. |
 | |
|  +---------------------------------------------------------------------------+
 | |
|  |                                                                           |
 | |
|  |    This software is subject to the PDFlib license. It is NOT in the       |
 | |
|  |    public domain. Extended versions and commercial licenses are           |
 | |
|  |    available, please check http://www.pdflib.com.                         |
 | |
|  |                                                                           |
 | |
|  *---------------------------------------------------------------------------*/
 | |
| 
 | |
| /* $Id: p_afm.c,v 1.2 2006-07-11 13:10:33 alex Exp $
 | |
|  *
 | |
|  * PDFlib AFM parsing routines
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include "p_intern.h"
 | |
| #include "p_font.h"
 | |
| 
 | |
| #define AFM_LINEBUF       4096
 | |
| 
 | |
| #define AFM_SEPARATORS    "\f\n\r\t\v ,:;"
 | |
| 
 | |
| #define AFM_MINNUMGLYPHS  5
 | |
| 
 | |
| /* The values of each of these enumerated items correspond to an entry in the
 | |
|  * table of strings defined below. Therefore, if you add a new string as
 | |
|  * new keyword into the keyStrings table, you must also add a corresponding
 | |
|  * pdf_afmkey AND it MUST be in the same position!
 | |
|  *
 | |
|  * IMPORTANT: since the sorting algorithm is a binary search, the strings of
 | |
|  * keywords must be placed in lexicographical order, below. [Therefore, the
 | |
|  * enumerated items are not necessarily in lexicographical order, depending
 | |
|  * on the name chosen. BUT, they must be placed in the same position as the
 | |
|  * corresponding key string.] The NOPE shall remain in the last position,
 | |
|  * since it does not correspond to any key string.
 | |
|  */
 | |
| 
 | |
| #ifndef PDFLIB_EBCDIC
 | |
| typedef enum
 | |
| {
 | |
|     ASCENDER,
 | |
|     CHARBBOX,
 | |
|     CODE,
 | |
|     COMPCHAR,
 | |
|     CODEHEX,
 | |
|     CAPHEIGHT,
 | |
|     CHARWIDTH,
 | |
|     CHARACTERSET,
 | |
|     CHARACTERS,
 | |
|     COMMENT,
 | |
|     DESCENDER,
 | |
|     ENCODINGSCHEME,
 | |
|     ENDCHARMETRICS,
 | |
|     ENDCOMPOSITES,
 | |
|     ENDDIRECTION,
 | |
|     ENDFONTMETRICS,
 | |
|     ENDKERNDATA,
 | |
|     ENDKERNPAIRS,
 | |
|     ENDKERNPAIRS0,
 | |
|     ENDKERNPAIRS1,
 | |
|     ENDMASTERFONTMETRICS,
 | |
|     ENDTRACKKERN,
 | |
|     ESCCHAR,
 | |
|     FAMILYNAME,
 | |
|     FONTBBOX,
 | |
|     FONTNAME,
 | |
|     FULLNAME,
 | |
|     ISBASEFONT,
 | |
|     ISCIDFONT,
 | |
|     ISFIXEDPITCH,
 | |
|     ISFIXEDV,
 | |
|     ITALICANGLE,
 | |
|     KERNPAIR,
 | |
|     KERNPAIRHAMT,
 | |
|     KERNPAIRXAMT,
 | |
|     KERNPAIRYAMT,
 | |
|     LIGATURE,
 | |
|     MAPPINGSCHEME,
 | |
|     METRICSSETS,
 | |
|     CHARNAME,
 | |
|     NOTICE,
 | |
|     COMPCHARPIECE,
 | |
|     STARTCHARMETRICS,
 | |
|     STARTCOMPFONTMETRICS,
 | |
|     STARTCOMPOSITES,
 | |
|     STARTDIRECTION,
 | |
|     STARTFONTMETRICS,
 | |
|     STARTKERNDATA,
 | |
|     STARTKERNPAIRS,
 | |
|     STARTKERNPAIRS0,
 | |
|     STARTKERNPAIRS1,
 | |
|     STARTMASTERFONTMETRICS,
 | |
|     STARTTRACKKERN,
 | |
|     STDHW,
 | |
|     STDVW,
 | |
|     TRACKKERN,
 | |
|     UNDERLINEPOSITION,
 | |
|     UNDERLINETHICKNESS,
 | |
|     VVECTOR,
 | |
|     VERSION,
 | |
|     XYWIDTH,
 | |
|     XY0WIDTH,
 | |
|     X0WIDTH,
 | |
|     Y0WIDTH,
 | |
|     XY1WIDTH,
 | |
|     X1WIDTH,
 | |
|     Y1WIDTH,
 | |
|     XWIDTH,
 | |
|     YWIDTH,
 | |
|     WEIGHT,
 | |
|     XHEIGHT,
 | |
|     NOPE
 | |
| }
 | |
| pdf_afmkey;
 | |
| 
 | |
| /* keywords for the system:
 | |
|  * This a table of all of the current strings that are vaild AFM keys.
 | |
|  * Each entry can be referenced by the appropriate pdf_afmkey value (an
 | |
|  * enumerated data type defined above). If you add a new keyword here,
 | |
|  * a corresponding pdf_afmkey MUST be added to the enumerated data type
 | |
|  * defined above, AND it MUST be added in the same position as the
 | |
|  * string is in this table.
 | |
|  *
 | |
|  * IMPORTANT: since the sorting algorithm is a binary search, the keywords
 | |
|  * must be placed in lexicographical order. And, NULL should remain at the
 | |
|  * end.
 | |
|  */
 | |
| 
 | |
| static const char *keyStrings[] =
 | |
| {
 | |
|     "Ascender",
 | |
|     "B",
 | |
|     "C",
 | |
|     "CC",
 | |
|     "CH",
 | |
|     "CapHeight",
 | |
|     "CharWidth",
 | |
|     "CharacterSet",
 | |
|     "Characters",
 | |
|     "Comment",
 | |
|     "Descender",
 | |
|     "EncodingScheme",
 | |
|     "EndCharMetrics",
 | |
|     "EndComposites",
 | |
|     "EndDirection",
 | |
|     "EndFontMetrics",
 | |
|     "EndKernData",
 | |
|     "EndKernPairs",
 | |
|     "EndKernPairs0",
 | |
|     "EndKernPairs1",
 | |
|     "EndMasterFontMetrics",
 | |
|     "EndTrackKern",
 | |
|     "EscChar",
 | |
|     "FamilyName",
 | |
|     "FontBBox",
 | |
|     "FontName",
 | |
|     "FullName",
 | |
|     "IsBaseFont",
 | |
|     "IsCIDFont",
 | |
|     "IsFixedPitch",
 | |
|     "IsFixedV",
 | |
|     "ItalicAngle",
 | |
|     "KP",
 | |
|     "KPH",
 | |
|     "KPX",
 | |
|     "KPY",
 | |
|     "L",
 | |
|     "MappingScheme",
 | |
|     "MetricsSets",
 | |
|     "N",
 | |
|     "Notice",
 | |
|     "PCC",
 | |
|     "StartCharMetrics",
 | |
|     "StartCompFontMetrics",
 | |
|     "StartComposites",
 | |
|     "StartDirection",
 | |
|     "StartFontMetrics",
 | |
|     "StartKernData",
 | |
|     "StartKernPairs",
 | |
|     "StartKernPairs0",
 | |
|     "StartKernPairs1",
 | |
|     "StartMasterFontMetrics",
 | |
|     "StartTrackKern",
 | |
|     "StdHW",
 | |
|     "StdVW",
 | |
|     "TrackKern",
 | |
|     "UnderlinePosition",
 | |
|     "UnderlineThickness",
 | |
|     "VVector",
 | |
|     "Version",
 | |
|     "W",
 | |
|     "W0",
 | |
|     "W0X",
 | |
|     "W0Y",
 | |
|     "W1",
 | |
|     "W1X",
 | |
|     "W1Y",
 | |
|     "WX",
 | |
|     "WY",
 | |
|     "Weight",
 | |
|     "XHeight"
 | |
| };
 | |
| 
 | |
| #else   /* !PDFLIB_EBCDIC */
 | |
| #endif  /* PDFLIB_EBCDIC */
 | |
| 
 | |
| static pdc_bool
 | |
| pdf_parse_afm(
 | |
|     PDF *p,
 | |
|     pdc_file *fp,
 | |
|     pdc_font *font,
 | |
|     const char *fontname,
 | |
|     const char *filename)
 | |
| {
 | |
|     static const char fn[] = "pdf_parse_afm";
 | |
|     const char *afmtype = NULL;
 | |
|     char **wordlist, *keyword, *arg1;
 | |
|     char line[AFM_LINEBUF];
 | |
|     int i, cmp, lo, hi, nwords, nglyphs = 0, nline = 0;
 | |
|     int tablen = ((sizeof keyStrings) / (sizeof (char *)));
 | |
|     pdc_sint32 iz;
 | |
|     double dz;
 | |
|     pdc_scalar charwidth = -1;
 | |
|     pdf_afmkey keynumber;
 | |
|     pdc_glyphwidth *glw;
 | |
|     pdc_bool toskip = pdc_false;
 | |
|     pdc_bool is_zadbfont = !strcmp(fontname, "ZapfDingbats");
 | |
| 
 | |
| 
 | |
|     /* all new glyph names of AGL 2.0 are missing */
 | |
|     font->missingglyphs = 0xFFFFFFFF;
 | |
| 
 | |
|     /* read loop. because of Mac files we use pdc_fgetline */
 | |
|     while (pdc_fgetline(line, AFM_LINEBUF, fp) != NULL)
 | |
|     {
 | |
|         /* split line */
 | |
|         nline++;
 | |
|         nwords = pdc_split_stringlist(p->pdc, line, AFM_SEPARATORS, &wordlist);
 | |
|         if (!nwords) continue;
 | |
|         keyword = wordlist[0];
 | |
| 
 | |
|         /* find keynumber */
 | |
|         lo = 0;
 | |
|         hi = tablen;
 | |
|         keynumber = NOPE;
 | |
|         while (lo < hi)
 | |
|         {
 | |
|             i = (lo + hi) / 2;
 | |
|             cmp = strcmp(keyword, keyStrings[i]);
 | |
| 
 | |
|             if (cmp == 0)
 | |
|             {
 | |
|                 keynumber = (pdf_afmkey) i;
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             if (cmp < 0)
 | |
|                 hi = i;
 | |
|             else
 | |
|                 lo = i + 1;
 | |
|         }
 | |
| 
 | |
|         /* unkown key */
 | |
|         if (keynumber == NOPE)
 | |
|         {
 | |
|             if (font->verbose == pdc_true)
 | |
|                 pdc_warning(p->pdc, PDF_E_T1_AFMBADKEY, keyword, filename, 0,0);
 | |
| 
 | |
|             goto PDF_PARSECONTD;
 | |
|         }
 | |
|         if (keynumber == ENDDIRECTION)
 | |
|             toskip = pdc_false;
 | |
| 
 | |
|         if (nwords == 1 || toskip == pdc_true)
 | |
|             goto PDF_PARSECONTD;
 | |
| 
 | |
|         /* key switch */
 | |
|         arg1 = wordlist[1];
 | |
|         switch (keynumber)
 | |
|         {
 | |
|             case STARTDIRECTION:
 | |
|             if (pdc_str2integer(arg1, 0, &iz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             if (iz)
 | |
|                 toskip = pdc_true;
 | |
|             break;
 | |
| 
 | |
|             case STARTCOMPFONTMETRICS:
 | |
|             afmtype = "ACFM";
 | |
|             goto PDF_SYNTAXERROR;
 | |
| 
 | |
|             case STARTMASTERFONTMETRICS:
 | |
|             afmtype = "AMFM";
 | |
|             goto PDF_SYNTAXERROR;
 | |
| 
 | |
|             case ISCIDFONT:
 | |
|             afmtype = "CID font";
 | |
|             if (!strcmp(arg1, "true"))
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             break;
 | |
| 
 | |
|             case FONTNAME:
 | |
|             font->name = pdc_strdup(p->pdc, arg1);
 | |
|             pdc_trace_protocol(p->pdc, 1, trc_font,
 | |
|                 "\tPostScript fontname: \"%s\"\n", font->name);
 | |
|             break;
 | |
| 
 | |
|             /* Recognize Multiple Master fonts by last part of name */
 | |
|             case FAMILYNAME:
 | |
|             if (!strcmp(wordlist[nwords-1], "MM"))
 | |
|                 font->type = pdc_MMType1;
 | |
|             break;
 | |
| 
 | |
|             /* Default: FontSpecific */
 | |
|             case ENCODINGSCHEME:
 | |
|             if (!pdc_stricmp(arg1, "StandardEncoding") ||
 | |
|                 !pdc_stricmp(arg1, "AdobeStandardEncoding"))
 | |
|                 font->isstdlatin = pdc_true ;
 | |
|             break;
 | |
| 
 | |
|             case STDHW:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->StdHW = (int) dz;
 | |
|             break;
 | |
| 
 | |
|             case STDVW:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->StdVW = (int) dz;
 | |
|             break;
 | |
| 
 | |
|             /* If we don't know StdVW we guess it from the font weight */
 | |
|             case WEIGHT:
 | |
|             if (font->StdVW == 0)
 | |
|             {
 | |
|                 if (!pdc_stricmp(arg1, "Light"))
 | |
|                     font->StdVW = PDF_STEMV_LIGHT;
 | |
|                 else if (!pdc_stricmp(arg1, "Medium"))
 | |
|                     font->StdVW = PDF_STEMV_MEDIUM;
 | |
|                 else if (!pdc_stricmp(arg1, "Semi") ||
 | |
|                          !pdc_stricmp(arg1, "SemiBold"))
 | |
|                     font->StdVW = PDF_STEMV_SEMIBOLD;
 | |
|                 else if (!pdc_stricmp(arg1, "Bold"))
 | |
|                     font->StdVW = PDF_STEMV_BOLD;
 | |
|                 else if (!pdc_stricmp(arg1, "Extra") ||
 | |
|                          !pdc_stricmp(arg1, "ExtraBold"))
 | |
|                     font->StdVW = PDF_STEMV_EXTRABOLD;
 | |
|                 else if (!pdc_stricmp(arg1, "Black"))
 | |
|                     font->StdVW = PDF_STEMV_BLACK;
 | |
|                 else
 | |
|                     font->StdVW = PDF_STEMV_NORMAL;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|             case ISFIXEDPITCH:
 | |
|             if (!pdc_stricmp(arg1, "false"))
 | |
|                 font->isFixedPitch = pdc_false;
 | |
|             else
 | |
|                 font->isFixedPitch = pdc_true;
 | |
|             break;
 | |
| 
 | |
|             /* New AFM 4.1 keyword "CharWidth" implies fixed pitch */
 | |
|             case CHARWIDTH:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             charwidth = dz;
 | |
|             font->isFixedPitch = pdc_true;
 | |
|             break;
 | |
| 
 | |
|             case ITALICANGLE:
 | |
|             {
 | |
|                 if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                     goto PDF_SYNTAXERROR;
 | |
|                 font->italicAngle = dz;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|             case UNDERLINEPOSITION:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->underlinePosition = (int) dz;
 | |
|             break;
 | |
| 
 | |
|             case UNDERLINETHICKNESS:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->underlineThickness = (int) dz;
 | |
|             break;
 | |
| 
 | |
|             case FONTBBOX:
 | |
|             {
 | |
|                 if (nwords != 5)
 | |
|                     goto PDF_SYNTAXERROR;
 | |
|                 for (i = 1; i < nwords; i++)
 | |
|                 {
 | |
|                     if (pdc_str2double(wordlist[i], &dz) != pdc_true)
 | |
|                         goto PDF_SYNTAXERROR;
 | |
|                     if (i == 1)
 | |
|                         font->llx = dz;
 | |
|                     else if (i == 2)
 | |
|                         font->lly = dz;
 | |
|                     else if (i == 3)
 | |
|                         font->urx = dz;
 | |
|                     else if (i == 4)
 | |
|                         font->ury = dz;
 | |
|                 }
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|             case CAPHEIGHT:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->capHeight = (int) dz;
 | |
|             break;
 | |
| 
 | |
|             case XHEIGHT:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->xHeight = (int) dz;
 | |
|             break;
 | |
| 
 | |
|             case DESCENDER:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->descender = (int) dz;
 | |
|             break;
 | |
| 
 | |
|             case ASCENDER:
 | |
|             if (pdc_str2double(arg1, &dz) != pdc_true)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->ascender = (int) dz;
 | |
|             break;
 | |
| 
 | |
|             /* Character widths */
 | |
| 
 | |
|             case STARTCHARMETRICS:
 | |
|             if (pdc_str2integer(arg1, PDC_INT_UNSIGNED, (pdc_sint32 *) &nglyphs)
 | |
|                 != pdc_true || nglyphs <= 0)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             font->glw = (pdc_glyphwidth *) pdc_calloc(p->pdc,
 | |
|                             (size_t) nglyphs * sizeof(pdc_glyphwidth), fn);
 | |
|             break;
 | |
| 
 | |
|             /* Character code */
 | |
|             case CODE:
 | |
|             case CODEHEX:
 | |
|             if (!nglyphs || !font->glw)
 | |
|                 goto PDF_SYNTAXERROR;
 | |
|             if (font->numOfGlyphs >= nglyphs)
 | |
|             {
 | |
|                 nglyphs++;
 | |
|                 font->glw = (pdc_glyphwidth *) pdc_realloc(p->pdc, font->glw,
 | |
|                                 (size_t) nglyphs * sizeof(pdc_glyphwidth), fn);
 | |
|             }
 | |
|             glw = &font->glw[font->numOfGlyphs];
 | |
|             if (keynumber == CODE)
 | |
|             {
 | |
|                 if (pdc_str2integer(arg1, 0, &iz) != pdc_true)
 | |
|                     goto PDF_SYNTAXERROR;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if (pdc_str2integer(arg1, PDC_INT_HEXADEC, &iz) != pdc_true)
 | |
|                     goto PDF_SYNTAXERROR;
 | |
|             }
 | |
|             glw->code = (pdc_short) iz;
 | |
|             glw->unicode = 0;
 | |
|             glw->width = (pdc_ushort)
 | |
|                 (font->monospace ? font->monospace : charwidth);
 | |
|             font->numOfGlyphs++;
 | |
| 
 | |
|             /* Character width and name */
 | |
|             for (i = 2; i < nwords; i++)
 | |
|             {
 | |
|                 if (!strcmp(wordlist[i], "WX") ||
 | |
|                     !strcmp(wordlist[i], "W0X") ||
 | |
|                     !strcmp(wordlist[i], "W"))
 | |
|                 {
 | |
|                     i++;
 | |
|                     if (i == nwords)
 | |
|                         goto PDF_SYNTAXERROR;
 | |
|                     if (pdc_str2double(wordlist[i], &dz) != pdc_true)
 | |
|                         goto PDF_SYNTAXERROR;
 | |
|                     glw->width = (pdc_ushort)
 | |
|                          (font->monospace ? font->monospace : dz);
 | |
|                 }
 | |
| 
 | |
|                 if (!strcmp(wordlist[i], "N"))
 | |
|                 {
 | |
|                     i++;
 | |
|                     if (i == nwords)
 | |
|                         goto PDF_SYNTAXERROR;
 | |
|                     glw->unicode = is_zadbfont ?
 | |
|                                      (pdc_ushort) pdc_zadb2unicode(wordlist[i]):
 | |
|                                       pdc_insert_glyphname(p->pdc, wordlist[i]);
 | |
|                     pdc_delete_missingglyph_bit(glw->unicode,
 | |
|                                                 &font->missingglyphs);
 | |
| 
 | |
|                     pdc_trace_protocol(p->pdc, 2, trc_font,
 | |
|                         "\t\tGlyph%4d: Code=%3d  U+%04X  Width=%4d  \"%s\"\n",
 | |
|                         font->numOfGlyphs, glw->code, glw->unicode,
 | |
|                         glw->width, wordlist[i]);
 | |
|                 }
 | |
|             }
 | |
|             break;
 | |
| 
 | |
| 
 | |
|             default:
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         PDF_PARSECONTD:
 | |
|         pdc_cleanup_stringlist(p->pdc, wordlist);
 | |
|         wordlist = NULL;
 | |
| 
 | |
|         if (keynumber == ENDFONTMETRICS)
 | |
|             break;
 | |
|     }
 | |
| 
 | |
|     /* necessary font struct members */
 | |
|     if (font->name == NULL || font->glw == NULL)
 | |
|         goto PDF_SYNTAXERROR;
 | |
| 
 | |
|     pdf_font_set_missvalues(p, font);
 | |
| 
 | |
|     pdc_fclose(fp);
 | |
|     return pdc_true;
 | |
| 
 | |
|     PDF_SYNTAXERROR:
 | |
|     pdc_fclose(fp);
 | |
|     pdc_cleanup_stringlist(p->pdc, wordlist);
 | |
| 
 | |
|     if (afmtype)
 | |
|         pdc_set_errmsg(p->pdc, PDF_E_T1_UNSUPP_FORMAT, afmtype, 0, 0, 0);
 | |
|     else
 | |
|         pdc_set_errmsg(p->pdc, PDC_E_IO_ILLSYNTAX, "AFM ", filename,
 | |
|                        pdc_errprintf(p->pdc, "%d", nline), 0);
 | |
| 
 | |
|     if (font->verbose == pdc_true)
 | |
|         pdc_error(p->pdc, -1, 0, 0, 0, 0);
 | |
| 
 | |
|     return pdc_false;
 | |
| }
 | |
| 
 | |
| pdc_bool
 | |
| pdf_process_metrics_data(
 | |
|     PDF *p,
 | |
|     pdc_font *font,
 | |
|     const char *fontname)
 | |
| {
 | |
|     static const char fn[] = "pdf_process_metrics_data";
 | |
|     int *widths;
 | |
|     pdc_ushort uv;
 | |
|     pdc_encoding enc = font->encoding;
 | |
|     pdc_encodingvector *ev = NULL;
 | |
|     int foundChars = 0, tofree = 0, i, k;
 | |
| 
 | |
|     /* Unallowed encoding */
 | |
|     if (enc == pdc_cid || enc < pdc_builtin) {
 | |
| 
 | |
| 	pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC,
 | |
| 	    fontname, pdf_get_encoding_name(p, enc, font), 0, 0);
 | |
| 
 | |
|         if (font->verbose == pdc_true)
 | |
| 	    pdc_error(p->pdc, -1, 0, 0, 0, 0);
 | |
| 
 | |
|         return pdc_false;
 | |
|     }
 | |
| 
 | |
|     /* Determine the default character width (width of space character) */
 | |
|     if (font->monospace)
 | |
|     {
 | |
|         font->defWidth = font->monospace;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         font->defWidth = PDF_DEFAULT_WIDTH;
 | |
|         for (i = 0; i < font->numOfGlyphs; i++)
 | |
|         {
 | |
|             if (font->glw[i].unicode == PDF_DEFAULT_GLYPH)
 | |
|             {
 | |
|                 font->defWidth = (int) font->glw[i].width;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* builtin font */
 | |
|     if (font->isstdlatin == pdc_false && enc != pdc_builtin &&
 | |
|         !strcmp(font->encapiname, "auto"))
 | |
|     {
 | |
|         enc = pdc_builtin;
 | |
|         font->encoding = enc;
 | |
|     }
 | |
| 
 | |
|     /* optimizing PDF output */
 | |
|     if (enc == pdc_ebcdic || enc == pdc_ebcdic_37)
 | |
|         font->towinansi = pdc_winansi;
 | |
| 
 | |
|     /*
 | |
|      * Generate character width according to the chosen encoding
 | |
|      */
 | |
| 
 | |
|     {
 | |
|         font->code2GID = (pdc_ushort *) pdc_calloc(p->pdc,
 | |
|                                    font->numOfCodes  * sizeof (pdc_ushort), fn);
 | |
|         font->widths = (int *) pdc_calloc(p->pdc,
 | |
|                                    font->numOfCodes * sizeof(int), fn);
 | |
|         widths = font->widths;
 | |
| 
 | |
|         /* Given encoding */
 | |
|         if (enc >= 0 && enc < p->encodings_number)
 | |
|         {
 | |
|             ev = pdf_get_encoding_vector(p, enc);
 | |
|             for (k = 0; k < font->numOfCodes; k++)
 | |
|             {
 | |
|                 uv = ev->codes[k];
 | |
|                 widths[k] = font->defWidth;
 | |
|                 if (uv == 0x0000)
 | |
|                     continue;
 | |
| 
 | |
|                 uv = pdc_get_alter_glyphname(uv, font->missingglyphs, NULL);
 | |
|                 if (uv)
 | |
|                 {
 | |
|                     for (i = 0; i < font->numOfGlyphs; i++)
 | |
|                     {
 | |
|                         if (font->glw[i].unicode == uv)
 | |
|                         {
 | |
|                             widths[k] = font->glw[i].width;
 | |
|                             font->code2GID[k] = 1;
 | |
|                             foundChars++;
 | |
|                             break;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             /* No characters found and lex Symbolii */
 | |
|             if (foundChars < AFM_MINNUMGLYPHS ||
 | |
|                 (!strcmp(fontname, "Symbol") && enc == pdc_winansi))
 | |
|             {
 | |
|                 if (font->isstdlatin == pdc_true)
 | |
|                 {
 | |
|                     pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC,
 | |
|                         fontname, pdf_get_encoding_name(p, enc, font),
 | |
|                         0, 0);
 | |
| 
 | |
|                     if (font->verbose)
 | |
|                         pdc_error(p->pdc, -1, 0, 0, 0, 0);
 | |
| 
 | |
|                     return pdc_false;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     /* We enforce builtin encoding */
 | |
|                     if (font->verbose && strcmp(font->encapiname, "auto"))
 | |
|                         pdc_warning(p->pdc, PDF_E_FONT_FORCEENC,
 | |
|                             pdf_get_encoding_name(p, pdc_builtin, font),
 | |
|                             pdf_get_encoding_name(p, enc, font), fontname,
 | |
|                             0);
 | |
|                     enc = pdc_builtin;
 | |
|                     font->encoding = enc;
 | |
|                     font->towinansi = pdc_invalidenc;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /* built-in encoding */
 | |
|         if (enc == pdc_builtin)
 | |
|         {
 | |
|             if (font->glw == NULL)
 | |
|             {
 | |
|                 pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC,
 | |
|                     fontname, pdf_get_encoding_name(p, enc, font), 0, 0);
 | |
| 
 | |
|                 if (font->verbose)
 | |
|                     pdc_error(p->pdc, -1, 0, 0, 0, 0);
 | |
| 
 | |
|                 return pdc_false;
 | |
|             }
 | |
| 
 | |
|             /* temporary encoding */
 | |
|             ev = (pdc_encodingvector *)
 | |
|                      pdc_malloc(p->pdc, sizeof(pdc_encodingvector), fn);
 | |
|             pdc_init_encoding(p->pdc, ev, "");
 | |
|             tofree = 1;
 | |
|             for (i = 0; i < font->numOfCodes; i++)
 | |
|             {
 | |
|                 widths[i] = font->defWidth;
 | |
|                 ev->codes[i] = PDF_DEFAULT_GLYPH;
 | |
|             }
 | |
|             for (i = 0; i < font->numOfGlyphs; i++)
 | |
|             {
 | |
|                 pdc_short code = font->glw[i].code;
 | |
| 
 | |
|                 if (code >= 0 && code < font->numOfCodes)
 | |
|                 {
 | |
|                     widths[code] = font->glw[i].width;
 | |
|                     ev->codes[code] = font->glw[i].unicode;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if (tofree) pdc_cleanup_encoding(p->pdc, ev);
 | |
| 
 | |
|     if (font->glw != NULL)
 | |
|     {
 | |
|         pdc_free(p->pdc, font->glw);
 | |
|         font->glw = NULL;
 | |
|     }
 | |
| 
 | |
|     return pdc_true;
 | |
| }
 | |
| 
 | |
| pdc_bool
 | |
| pdf_get_metrics_afm(
 | |
|     PDF *p,
 | |
|     pdc_font *font,
 | |
|     const char *fontname,
 | |
|     pdc_encoding enc,
 | |
|     const char *filename)
 | |
| {
 | |
|     char fullname[PDC_FILENAMELEN];
 | |
|     pdc_file *afmfile;
 | |
| 
 | |
|     /* open AFM file */
 | |
|     if ((afmfile = pdf_fopen_name(p, filename, fullname, "AFM ", 0)) == NULL)
 | |
|     {
 | |
| 	if (font->verbose_open)
 | |
| 	    pdc_error(p->pdc, -1, 0, 0, 0, 0);
 | |
| 
 | |
|         return pdc_undef;
 | |
|     }
 | |
| 
 | |
|     pdc_trace_protocol(p->pdc, 1, trc_font,
 | |
|         "\tLoading AFM metric fontfile \"%s\":\n", fullname);
 | |
| 
 | |
|     /* parse AFM file */
 | |
|     if (pdf_parse_afm(p, afmfile, font, fontname, fullname) == pdc_false)
 | |
|         return pdc_false;
 | |
| 
 | |
|     /* process metric data */
 | |
|     font->encoding = enc;
 | |
|     if (pdf_process_metrics_data(p, font, fontname) == pdc_false)
 | |
|         return pdc_false;
 | |
| 
 | |
|     if (!pdf_make_fontflag(p, font))
 | |
|         return pdc_false;
 | |
| 
 | |
|     return pdc_true;
 | |
| }
 | |
| 
 | |
| pdc_bool
 | |
| pdf_get_core_metrics_afm(
 | |
|     PDF *p,
 | |
|     pdc_font *font,
 | |
|     pdc_core_metric *metric,
 | |
|     const char *fontname,
 | |
|     const char *filename)
 | |
| {
 | |
|     pdc_file *afmfile;
 | |
| 
 | |
|     /* open AFM file */
 | |
|     if ((afmfile = pdf_fopen(p, filename, "AFM ", 0)) == NULL)
 | |
| 	pdc_error(p->pdc, -1, 0, 0, 0, 0);
 | |
| 
 | |
|     /* parse AFM file */
 | |
|     if (pdf_parse_afm(p, afmfile, font, fontname, filename) == pdc_false)
 | |
|         return pdc_false;
 | |
| 
 | |
|     /* process metric data */
 | |
|     font->encoding = pdc_invalidenc;
 | |
|     pdc_fill_core_metric(p->pdc, font, metric);
 | |
| 
 | |
|     return pdc_true;
 | |
| }
 | |
| 
 |