Scale the OUTLINETEXTMETRIC's bounding box with the font size.
[wine] / dlls / wineps / afm2c.c
1 /*******************************************************************************
2  *
3  *  Function to write WINEPS AFM data structures as C
4  *
5  *  Copyright 2001 Ian Pilcher
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * NOTES:
22  *
23  *  PSDRV_AFM2C(AFM *afm) writes the AFM data structure addressed by afm (and
24  *  its subsidiary objects) as a C file which can which can then be built in to
25  *  the driver.  It creates the file in the current directory with a name of
26  *  the form {FontName}.c, where {FontName} is the PostScript font name with
27  *  hyphens replaced by underscores.
28  *
29  *  To use this function, do the following:
30  *
31  *      *  Edit dlls/wineps/Makefile (or dlls/wineps/Makefile.in) and add
32  *         afm2c.c as a source file.
33  *
34  *      *  Edit dlls/wineps/afm.c and uncomment the call to PSDRV_AFM2C in
35  *         PSDRV_DumpFontList() (or wherever it gets moved).  The resulting
36  *         compiler warning can be safely ignored.
37  *
38  *  IMPORTANT:  For this to work, all glyph names in the AFM data being
39  *      written *MUST* already be present in PSDRV_AGLGlyphNames in agl.c.
40  *      See mkagl.c in this directory for information on how to generate
41  *      updated glyph name information.  Note, however, that if the glyph
42  *      name information in agl.c is regenerated, *ALL* AFM data must also
43  *      be recreated.
44  *
45  */
46
47 #include <string.h>
48 #include <stdio.h>
49 #include <math.h>
50
51 #include "wine/debug.h"
52 #include "psdrv.h"
53
54 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
55
56 inline static void cursorto(FILE *of, int np, int cp)
57 {
58     int ntp = np & 0xfffffff8;
59     int ctp = cp & 0xfffffff8;
60
61     while (ctp < ntp)
62     {
63         fputc('\t', of);
64         ctp += 8;
65         cp = ctp;
66     }
67
68     while (cp < np)
69     {
70         fputc(' ', of);
71         ++cp;
72     }
73 }
74
75 static void writeHeader(FILE *of, const AFM *afm, const char *buffer)
76 {
77     int i;
78
79     fputc('/', of);
80     for (i = 1; i < 80; ++i)
81         fputc('*', of);
82     fprintf(of, "\n"
83                 " *\n"
84                 " *\tFont metric data for %s\n"
85                 " *\n"
86                 " *\tCopyright 2001 Ian Pilcher\n"
87                 " *\n"
88                 " *\n"
89                 " *\tSee dlls/wineps/data/COPYRIGHTS for font copyright "
90                         "information.\n"
91                 " *\n"
92                 " */\n"
93                 "\n"
94                 "#include \"psdrv.h\"\n"
95                 "#include \"data/agl.h\"\n", afm->FullName);
96 }
97
98 static void writeMetrics(FILE *of, const AFM *afm, const char *buffer)
99 {
100     int i;
101
102     fputs("\n\n/*\n *  Glyph metrics\n */\n\n", of);
103
104     fprintf(of, "static const AFMMETRICS metrics[%i] =\n{\n",
105             afm->NumofMetrics);
106
107     for (i = 0; i < afm->NumofMetrics - 1; ++i)
108     {
109         fprintf(of, "    { %3i, 0x%.4lx, %4g, GN_%s },\n", afm->Metrics[i].C,
110                 afm->Metrics[i].UV, afm->Metrics[i].WX, afm->Metrics[i].N->sz);
111     }
112
113     fprintf(of, "    { %3i, 0x%.4lx, %4g, GN_%s }\n};\n", afm->Metrics[i].C,
114             afm->Metrics[i].UV, afm->Metrics[i].WX, afm->Metrics[i].N->sz);
115 }
116
117 static void writeAFM(FILE *of, const AFM *afm, const char *buffer)
118 {
119     fputs("\n\n/*\n *  Font metrics\n */\n\n", of);
120
121     fprintf(of, "const AFM PSDRV_%s =\n{\n", buffer);
122     cursorto(of, 44, fprintf(of, "    \"%s\",", afm->FontName));
123     fputs("/* FontName */\n", of);
124     cursorto(of, 44, fprintf(of, "    \"%s\",", afm->FullName));
125     fputs("/* FullName */\n", of);
126     cursorto(of, 44, fprintf(of, "    \"%s\",", afm->FamilyName));
127     fputs("/* FamilyName */\n", of);
128     cursorto(of, 44, fprintf(of, "    \"%s\",", afm->EncodingScheme));
129     fputs("/* EncodingScheme */\n", of);
130     cursorto(of, 44, fprintf(of, "    %s,",
131             (afm->Weight > 550) ? "FW_BOLD" : "FW_NORMAL"));
132     fputs("/* Weight */\n", of);
133     cursorto(of, 44, fprintf(of, "    %g,", afm->ItalicAngle));
134     fputs("/* ItalicAngle */\n", of);
135     cursorto(of, 44, fprintf(of, "    %s,",
136             afm->IsFixedPitch ? "TRUE" : "FALSE"));
137     fputs("/* IsFixedPitch */\n", of);
138     cursorto(of, 44, fprintf(of, "    %g,", afm->UnderlinePosition));
139     fputs("/* UnderlinePosition */\n", of);
140     cursorto(of, 44, fprintf(of, "    %g,", afm->UnderlineThickness));
141     fputs("/* UnderlineThickness */\n", of);
142     cursorto(of, 44, fprintf(of, "    { %g, %g, %g, %g },", afm->FontBBox.llx,
143             afm->FontBBox.lly, afm->FontBBox.urx, afm->FontBBox.ury));
144     fputs("/* FontBBox */\n", of);
145     cursorto(of, 44, fprintf(of, "    %g,", afm->Ascender));
146     fputs("/* Ascender */\n", of);
147     cursorto(of, 44, fprintf(of, "    %g,", afm->Descender));
148     fputs("/* Descender */\n", of);
149     fputs("    {\n", of);
150     cursorto(of, 44, 7 + fprintf(of, "\t%u,",
151             (unsigned int)(afm->WinMetrics.usUnitsPerEm)));
152     fputs("/* WinMetrics.usUnitsPerEm */\n", of);
153     cursorto(of, 44, 7 + fprintf(of, "\t%i,",
154             (int)(afm->WinMetrics.sAscender)));
155     fputs("/* WinMetrics.sAscender */\n", of);
156     cursorto(of, 44, 7 + fprintf(of, "\t%i,",
157             (int)(afm->WinMetrics.sDescender)));
158     fputs("/* WinMetrics.sDescender */\n", of);
159     cursorto(of, 44, 7 + fprintf(of, "\t%i,",
160             (int)(afm->WinMetrics.sLineGap)));
161     fputs("/* WinMetrics.sLineGap */\n", of);
162     cursorto(of, 44, 7 + fprintf(of, "\t%i,",
163             (int)(afm->WinMetrics.sAvgCharWidth)));
164     fputs("/* WinMetrics.sAvgCharWidth */\n", of);
165     cursorto(of, 44, 7 + fprintf(of, "\t%i,",
166             (int)(afm->WinMetrics.sTypoAscender)));
167     fputs("/* WinMetrics.sTypoAscender */\n", of);
168     cursorto(of, 44, 7 + fprintf(of, "\t%i,",
169             (int)(afm->WinMetrics.sTypoDescender)));
170     fputs("/* WinMetrics.sTypoDescender */\n", of);
171     cursorto(of, 44, 7 + fprintf(of, "\t%i,",
172             (int)(afm->WinMetrics.sTypoLineGap)));
173     fputs("/* WinMetrics.sTypoLineGap */\n", of);
174     cursorto(of, 44, 7 + fprintf(of, "\t%u,",
175             (unsigned int)(afm->WinMetrics.usWinAscent)));
176     fputs("/* WinMetrics.usWinAscent */\n", of);
177     cursorto(of, 44, 7 + fprintf(of, "\t%u",
178             (unsigned int)(afm->WinMetrics.usWinDescent)));
179     fputs("/* WinMetrics.usWinDescent */\n",of);
180     fputs("    },\n", of);
181     cursorto(of, 44, fprintf(of, "    %i,", afm->NumofMetrics));
182     fputs("/* NumofMetrics */\n", of);
183     fputs("    metrics\t\t\t\t    /* Metrics */\n};\n", of);
184 }
185
186 void PSDRV_AFM2C(const AFM *afm)
187 {
188     char    buffer[256];
189     FILE    *of;
190     int     i;
191
192     strncpy(buffer, afm->FontName, sizeof(buffer) - 3);
193     buffer[sizeof(buffer) - 3] = '\0';
194
195     for (i = 0; i < strlen(buffer); ++i)
196         if (buffer[i] == '-')
197             buffer[i] = '_';
198
199     buffer[i] = '.';  buffer[i + 1] = 'c';  buffer[i + 2] = '\0';
200
201     MESSAGE("writing '%s'\n", buffer);
202
203     of = fopen(buffer, "w");
204     if (of == NULL)
205     {
206         ERR("error opening '%s' for writing\n", buffer);
207         return;
208     }
209
210     buffer[i] = '\0';
211
212     writeHeader(of, afm, buffer);
213     writeMetrics(of, afm, buffer);
214     writeAFM(of, afm, buffer);
215
216     fclose(of);
217 }