]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/bitmap/pcfwrite.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / font / bitmap / pcfwrite.c
1 /* $XConsortium: pcfwrite.c,v 1.6 94/04/17 20:17:16 gildea Exp $ */
2
3 /*
4
5 Copyright (c) 1990, 1994  X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
30
31 */
32
33 /*
34  * Author:  Keith Packard, MIT X Consortium
35  */
36
37
38 #include "fntfilst.h"
39 #include "bitmap.h"
40 #include "pcf.h"
41
42 /* Write PCF font files */
43
44 static int  current_position;
45
46 static int
47 pcfWrite(file, b, c)
48     FontFilePtr file;
49     char       *b;
50     int         c;
51 {
52     current_position += c;
53     return FontFileWrite(file, b, c);
54 }
55
56 static int
57 pcfPutLSB32(file, c)
58     FontFilePtr file;
59 {
60     current_position += 4;
61     (void) FontFilePutc(c, file);
62     (void) FontFilePutc(c >> 8, file);
63     (void) FontFilePutc(c >> 16, file);
64     return FontFilePutc(c >> 24, file);
65 }
66
67 static int
68 pcfPutINT32(file, format, c)
69     FontFilePtr file;
70     CARD32      format;
71 {
72     current_position += 4;
73     if (PCF_BYTE_ORDER(format) == MSBFirst) {
74         (void) FontFilePutc(c >> 24, file);
75         (void) FontFilePutc(c >> 16, file);
76         (void) FontFilePutc(c >> 8, file);
77         return FontFilePutc(c, file);
78     } else {
79         (void) FontFilePutc(c, file);
80         (void) FontFilePutc(c >> 8, file);
81         (void) FontFilePutc(c >> 16, file);
82         return FontFilePutc(c >> 24, file);
83     }
84 }
85
86 static int
87 pcfPutINT16(file, format, c)
88     FontFilePtr file;
89     CARD32      format;
90 {
91     current_position += 2;
92     if (PCF_BYTE_ORDER(format) == MSBFirst) {
93         (void) FontFilePutc(c >> 8, file);
94         return FontFilePutc(c, file);
95     } else {
96         (void) FontFilePutc(c, file);
97         return FontFilePutc(c >> 8, file);
98     }
99 }
100
101 /*ARGSUSED*/
102 static int
103 pcfPutINT8(file, format, c)
104     FontFilePtr file;
105     CARD32      format;
106 {
107     current_position += 1;
108     return FontFilePutc(c, file);
109 }
110
111 static
112 pcfWriteTOC(file, table, count)
113     FontFilePtr file;
114     PCFTablePtr table;
115     int         count;
116 {
117     CARD32      version;
118     int         i;
119
120     version = PCF_FILE_VERSION;
121     pcfPutLSB32(file, version);
122     pcfPutLSB32(file, count);
123     for (i = 0; i < count; i++) {
124         pcfPutLSB32(file, table->type);
125         pcfPutLSB32(file, table->format);
126         pcfPutLSB32(file, table->size);
127         pcfPutLSB32(file, table->offset);
128         table++;
129     }
130 }
131
132 static
133 pcfPutCompressedMetric(file, format, metric)
134     FontFilePtr file;
135     CARD32      format;
136     xCharInfo  *metric;
137 {
138     pcfPutINT8(file, format, metric->leftSideBearing + 0x80);
139     pcfPutINT8(file, format, metric->rightSideBearing + 0x80);
140     pcfPutINT8(file, format, metric->characterWidth + 0x80);
141     pcfPutINT8(file, format, metric->ascent + 0x80);
142     pcfPutINT8(file, format, metric->descent + 0x80);
143 }
144
145 static
146 pcfPutMetric(file, format, metric)
147     FontFilePtr file;
148     CARD32      format;
149     xCharInfo  *metric;
150 {
151     pcfPutINT16(file, format, metric->leftSideBearing);
152     pcfPutINT16(file, format, metric->rightSideBearing);
153     pcfPutINT16(file, format, metric->characterWidth);
154     pcfPutINT16(file, format, metric->ascent);
155     pcfPutINT16(file, format, metric->descent);
156     pcfPutINT16(file, format, metric->attributes);
157 }
158
159 static
160 pcfPutBitmap(file, format, pCI)
161     FontFilePtr file;
162     CARD32      format;
163     CharInfoPtr pCI;
164 {
165     int         count;
166     unsigned char *bits;
167
168     count = BYTES_FOR_GLYPH(pCI, PCF_GLYPH_PAD(format));
169     bits = (unsigned char *) pCI->bits;
170     current_position += count;
171     while (count--)
172         FontFilePutc(*bits++, file);
173 }
174
175 static
176 pcfPutAccel(file, format, pFontInfo)
177     FontFilePtr file;
178     CARD32      format;
179     FontInfoPtr pFontInfo;
180 {
181     pcfPutINT8(file, format, pFontInfo->noOverlap);
182     pcfPutINT8(file, format, pFontInfo->constantMetrics);
183     pcfPutINT8(file, format, pFontInfo->terminalFont);
184     pcfPutINT8(file, format, pFontInfo->constantWidth);
185     pcfPutINT8(file, format, pFontInfo->inkInside);
186     pcfPutINT8(file, format, pFontInfo->inkMetrics);
187     pcfPutINT8(file, format, pFontInfo->drawDirection);
188     pcfPutINT8(file, format, 0);
189     pcfPutINT32(file, format, pFontInfo->fontAscent);
190     pcfPutINT32(file, format, pFontInfo->fontDescent);
191     pcfPutINT32(file, format, pFontInfo->maxOverlap);
192     pcfPutMetric(file, format, &pFontInfo->minbounds);
193     pcfPutMetric(file, format, &pFontInfo->maxbounds);
194     if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
195         pcfPutMetric(file, format, &pFontInfo->ink_minbounds);
196         pcfPutMetric(file, format, &pFontInfo->ink_maxbounds);
197     }
198 }
199
200 #define S32 4
201 #define S16 2
202 #define S8 1
203
204 #define Pad(s)      (RoundUp(s) - (s))
205 #define RoundUp(s)  (((s) + 3) & ~3)
206
207 #define Compressable(i) (-128 <= (i) && (i) <= 127)
208
209 #define CanCompressMetric(m)    (Compressable((m)->leftSideBearing) && \
210                                  Compressable((m)->rightSideBearing) && \
211                                  Compressable((m)->characterWidth) && \
212                                  Compressable((m)->ascent) && \
213                                  Compressable((m)->descent) && \
214                                  (m)->attributes == 0)
215
216 #define CanCompressMetrics(min,max) (CanCompressMetric(min) && CanCompressMetric(max))
217
218 static char *
219 pcfNameForAtom(a)
220     Atom        a;
221 {
222     return NameForAtom(a);
223 }
224
225 pcfWriteFont(pFont, file)
226     FontPtr     pFont;
227     FontFilePtr file;
228 {
229     PCFTableRec tables[32],
230                *table;
231     CARD32      mask,
232                 bit;
233     int         ntables;
234     int         size;
235     CARD32      format;
236     int         i;
237     int         cur_table;
238     int         prop_string_size;
239     int         glyph_string_size;
240     xCharInfo  *minbounds,
241                *maxbounds;
242     xCharInfo  *ink_minbounds,
243                *ink_maxbounds;
244     BitmapFontPtr  bitmapFont;
245     int         nencodings;
246     int         header_size;
247     FontPropPtr offsetProps;
248     int         prop_pad;
249     char       *atom_name;
250     int         glyph;
251     int         offset;
252
253     bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
254     if (bitmapFont->bitmapExtra) {
255         minbounds = &bitmapFont->bitmapExtra->info.minbounds;
256         maxbounds = &bitmapFont->bitmapExtra->info.maxbounds;
257         ink_minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds;
258         ink_maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds;
259     } else {
260         minbounds = &pFont->info.minbounds;
261         maxbounds = &pFont->info.maxbounds;
262         ink_minbounds = &pFont->info.ink_minbounds;
263         ink_maxbounds = &pFont->info.ink_maxbounds;
264     }
265     offsetProps = (FontPropPtr) xalloc(pFont->info.nprops * sizeof(FontPropRec));
266     if (!offsetProps)
267         return AllocError;
268     prop_string_size = 0;
269     for (i = 0; i < pFont->info.nprops; i++) {
270         offsetProps[i].name = prop_string_size;
271         prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].name)) + 1;
272         if (pFont->info.isStringProp[i]) {
273             offsetProps[i].value = prop_string_size;
274             prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].value)) + 1;
275         } else
276             offsetProps[i].value = pFont->info.props[i].value;
277     }
278     format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan);
279     mask = 0xFFFFFFF;
280     ntables = 0;
281     table = tables;
282     while (mask) {
283         bit = lowbit(mask);
284         mask &= ~bit;
285         table->type = bit;
286         switch (bit) {
287         case PCF_PROPERTIES:
288             table->format = PCF_DEFAULT_FORMAT | format;
289             size = S32 + S32 + (S32 + S8 + S32) * pFont->info.nprops;
290             prop_pad = Pad(size);
291             table->size = RoundUp(size) + S32 +
292                 RoundUp(prop_string_size);
293             table++;
294             break;
295         case PCF_ACCELERATORS:
296             if (bitmapFont->bitmapExtra->info.inkMetrics)
297                 table->format = PCF_ACCEL_W_INKBOUNDS | format;
298             else
299                 table->format = PCF_DEFAULT_FORMAT | format;
300             table->size = 100;
301             table++;
302             break;
303         case PCF_METRICS:
304             if (CanCompressMetrics(minbounds, maxbounds)) {
305                 table->format = PCF_COMPRESSED_METRICS | format;
306                 size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
307                 table->size = RoundUp(size);
308             } else {
309                 table->format = PCF_DEFAULT_FORMAT | format;
310                 table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
311             }
312             table++;
313             break;
314         case PCF_BITMAPS:
315             table->format = PCF_DEFAULT_FORMAT | format;
316             size = S32 + S32 + bitmapFont->num_chars * S32 +
317                 GLYPHPADOPTIONS * S32 +
318                 bitmapFont->bitmapExtra->bitmapsSizes[PCF_GLYPH_PAD_INDEX(format)];
319             table->size = RoundUp(size);
320             table++;
321             break;
322         case PCF_INK_METRICS:
323             if (bitmapFont->ink_metrics) {
324                 if (CanCompressMetrics(ink_minbounds, ink_maxbounds)) {
325                     table->format = PCF_COMPRESSED_METRICS | format;
326                     size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
327                     table->size = RoundUp(size);
328                 } else {
329                     table->format = PCF_DEFAULT_FORMAT | format;
330                     table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
331                 }
332                 table++;
333             }
334             break;
335         case PCF_BDF_ENCODINGS:
336             table->format = PCF_DEFAULT_FORMAT | format;
337             nencodings = (pFont->info.lastRow - pFont->info.firstRow + 1) *
338                 (pFont->info.lastCol - pFont->info.firstCol + 1);
339             size = S32 + 5 * S16 + nencodings * S16;
340             table->size = RoundUp(size);
341             table++;
342             break;
343         case PCF_SWIDTHS:
344             table->format = PCF_DEFAULT_FORMAT | format;
345             table->size = S32 + S32 + bitmapFont->num_chars * S32;
346             table++;
347             break;
348         case PCF_GLYPH_NAMES:
349             table->format = PCF_DEFAULT_FORMAT | format;
350             glyph_string_size = 0;
351             for (i = 0; i < bitmapFont->num_chars; i++)
352                 glyph_string_size += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
353             table->size = S32 + S32 + bitmapFont->num_chars * S32 +
354                 S32 + RoundUp(glyph_string_size);
355             table++;
356             break;
357         case PCF_BDF_ACCELERATORS:
358             if (pFont->info.inkMetrics)
359                 table->format = PCF_ACCEL_W_INKBOUNDS | format;
360             else
361                 table->format = PCF_DEFAULT_FORMAT | format;
362             table->size = 100;
363             table++;
364             break;
365         }
366     }
367     ntables = table - tables;
368     offset = 0;
369     header_size = S32 + S32 + ntables * (4 * S32);
370     offset = header_size;
371     for (cur_table = 0, table = tables;
372             cur_table < ntables;
373             cur_table++, table++) {
374         table->offset = offset;
375         offset += table->size;
376     }
377     current_position = 0;
378     pcfWriteTOC(file, tables, ntables);
379     for (cur_table = 0, table = tables;
380             cur_table < ntables;
381             cur_table++, table++) {
382         if (current_position > table->offset) {
383             printf("can't go backwards... %d > %d\n",
384                    current_position, table->offset);
385             return BadFontName;
386         }
387         while (current_position < table->offset)
388             pcfPutINT8(file, format, '\0');
389         pcfPutLSB32(file, table->format);
390         switch (table->type) {
391         case PCF_PROPERTIES:
392             pcfPutINT32(file, format, pFont->info.nprops);
393             for (i = 0; i < pFont->info.nprops; i++) {
394                 pcfPutINT32(file, format, offsetProps[i].name);
395                 pcfPutINT8(file, format, pFont->info.isStringProp[i]);
396                 pcfPutINT32(file, format, offsetProps[i].value);
397             }
398             for (i = 0; i < prop_pad; i++)
399                 pcfPutINT8(file, format, 0);
400             pcfPutINT32(file, format, prop_string_size);
401             for (i = 0; i < pFont->info.nprops; i++) {
402                 atom_name = pcfNameForAtom(pFont->info.props[i].name);
403                 pcfWrite(file, atom_name, strlen(atom_name) + 1);
404                 if (pFont->info.isStringProp[i]) {
405                     atom_name = pcfNameForAtom(pFont->info.props[i].value);
406                     pcfWrite(file, atom_name, strlen(atom_name) + 1);
407                 }
408             }
409             break;
410         case PCF_ACCELERATORS:
411             pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info);
412             break;
413         case PCF_METRICS:
414             if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
415                 pcfPutINT16(file, format, bitmapFont->num_chars);
416                 for (i = 0; i < bitmapFont->num_chars; i++)
417                     pcfPutCompressedMetric(file, format, &bitmapFont->metrics[i].metrics);
418             } else {
419                 pcfPutINT32(file, format, bitmapFont->num_chars);
420                 for (i = 0; i < bitmapFont->num_chars; i++)
421                     pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics);
422             }
423             break;
424         case PCF_BITMAPS:
425             pcfPutINT32(file, format, bitmapFont->num_chars);
426             glyph = PCF_GLYPH_PAD(format);
427             offset = 0;
428             for (i = 0; i < bitmapFont->num_chars; i++) {
429                 pcfPutINT32(file, format, offset);
430                 offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph);
431             }
432             for (i = 0; i < GLYPHPADOPTIONS; i++) {
433                 pcfPutINT32(file, format,
434                             bitmapFont->bitmapExtra->bitmapsSizes[i]);
435             }
436             for (i = 0; i < bitmapFont->num_chars; i++)
437                 pcfPutBitmap(file, format, &bitmapFont->metrics[i]);
438             break;
439         case PCF_INK_METRICS:
440             if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
441                 pcfPutINT16(file, format, bitmapFont->num_chars);
442                 for (i = 0; i < bitmapFont->num_chars; i++)
443                     pcfPutCompressedMetric(file, format, &bitmapFont->ink_metrics[i]);
444             } else {
445                 pcfPutINT32(file, format, bitmapFont->num_chars);
446                 for (i = 0; i < bitmapFont->num_chars; i++)
447                     pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]);
448             }
449             break;
450         case PCF_BDF_ENCODINGS:
451             pcfPutINT16(file, format, pFont->info.firstCol);
452             pcfPutINT16(file, format, pFont->info.lastCol);
453             pcfPutINT16(file, format, pFont->info.firstRow);
454             pcfPutINT16(file, format, pFont->info.lastRow);
455             pcfPutINT16(file, format, pFont->info.defaultCh);
456             for (i = 0; i < nencodings; i++) {
457                 if (bitmapFont->encoding[i])
458                     pcfPutINT16(file, format, bitmapFont->encoding[i] - bitmapFont->metrics);
459                 else
460                     pcfPutINT16(file, format, 0xFFFF);
461             }
462             break;
463         case PCF_SWIDTHS:
464             pcfPutINT32(file, format, bitmapFont->num_chars);
465             for (i = 0; i < bitmapFont->num_chars; i++)
466                 pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]);
467             break;
468         case PCF_GLYPH_NAMES:
469             pcfPutINT32(file, format, bitmapFont->num_chars);
470             offset = 0;
471             for (i = 0; i < bitmapFont->num_chars; i++) {
472                 pcfPutINT32(file, format, offset);
473                 offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
474             }
475             pcfPutINT32(file, format, offset);
476             for (i = 0; i < bitmapFont->num_chars; i++) {
477                 atom_name = pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i]);
478                 pcfWrite(file, atom_name, strlen(atom_name) + 1);
479             }
480             break;
481         case PCF_BDF_ACCELERATORS:
482             pcfPutAccel(file, table->format, &pFont->info);
483             break;
484         }
485     }
486     return Successful;
487 }