1 /* $XConsortium: pcfwrite.c,v 1.6 94/04/17 20:17:16 gildea Exp $ */
5 Copyright (c) 1990, 1994 X Consortium
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:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
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.
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.
34 * Author: Keith Packard, MIT X Consortium
42 /* Write PCF font files */
44 static int current_position;
52 current_position += c;
53 return FontFileWrite(file, b, c);
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);
68 pcfPutINT32(file, format, c)
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);
79 (void) FontFilePutc(c, file);
80 (void) FontFilePutc(c >> 8, file);
81 (void) FontFilePutc(c >> 16, file);
82 return FontFilePutc(c >> 24, file);
87 pcfPutINT16(file, format, c)
91 current_position += 2;
92 if (PCF_BYTE_ORDER(format) == MSBFirst) {
93 (void) FontFilePutc(c >> 8, file);
94 return FontFilePutc(c, file);
96 (void) FontFilePutc(c, file);
97 return FontFilePutc(c >> 8, file);
103 pcfPutINT8(file, format, c)
107 current_position += 1;
108 return FontFilePutc(c, file);
112 pcfWriteTOC(file, table, count)
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);
133 pcfPutCompressedMetric(file, format, metric)
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);
146 pcfPutMetric(file, format, metric)
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);
160 pcfPutBitmap(file, format, pCI)
168 count = BYTES_FOR_GLYPH(pCI, PCF_GLYPH_PAD(format));
169 bits = (unsigned char *) pCI->bits;
170 current_position += count;
172 FontFilePutc(*bits++, file);
176 pcfPutAccel(file, format, pFontInfo)
179 FontInfoPtr pFontInfo;
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);
204 #define Pad(s) (RoundUp(s) - (s))
205 #define RoundUp(s) (((s) + 3) & ~3)
207 #define Compressable(i) (-128 <= (i) && (i) <= 127)
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)
216 #define CanCompressMetrics(min,max) (CanCompressMetric(min) && CanCompressMetric(max))
222 return NameForAtom(a);
225 pcfWriteFont(pFont, file)
229 PCFTableRec tables[32],
238 int prop_string_size;
239 int glyph_string_size;
240 xCharInfo *minbounds,
242 xCharInfo *ink_minbounds,
244 BitmapFontPtr bitmapFont;
247 FontPropPtr offsetProps;
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;
260 minbounds = &pFont->info.minbounds;
261 maxbounds = &pFont->info.maxbounds;
262 ink_minbounds = &pFont->info.ink_minbounds;
263 ink_maxbounds = &pFont->info.ink_maxbounds;
265 offsetProps = (FontPropPtr) xalloc(pFont->info.nprops * sizeof(FontPropRec));
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;
276 offsetProps[i].value = pFont->info.props[i].value;
278 format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan);
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);
295 case PCF_ACCELERATORS:
296 if (bitmapFont->bitmapExtra->info.inkMetrics)
297 table->format = PCF_ACCEL_W_INKBOUNDS | format;
299 table->format = PCF_DEFAULT_FORMAT | format;
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);
309 table->format = PCF_DEFAULT_FORMAT | format;
310 table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
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);
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);
329 table->format = PCF_DEFAULT_FORMAT | format;
330 table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
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);
344 table->format = PCF_DEFAULT_FORMAT | format;
345 table->size = S32 + S32 + bitmapFont->num_chars * S32;
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);
357 case PCF_BDF_ACCELERATORS:
358 if (pFont->info.inkMetrics)
359 table->format = PCF_ACCEL_W_INKBOUNDS | format;
361 table->format = PCF_DEFAULT_FORMAT | format;
367 ntables = table - tables;
369 header_size = S32 + S32 + ntables * (4 * S32);
370 offset = header_size;
371 for (cur_table = 0, table = tables;
373 cur_table++, table++) {
374 table->offset = offset;
375 offset += table->size;
377 current_position = 0;
378 pcfWriteTOC(file, tables, ntables);
379 for (cur_table = 0, table = tables;
381 cur_table++, table++) {
382 if (current_position > table->offset) {
383 printf("can't go backwards... %d > %d\n",
384 current_position, table->offset);
387 while (current_position < table->offset)
388 pcfPutINT8(file, format, '\0');
389 pcfPutLSB32(file, table->format);
390 switch (table->type) {
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);
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);
410 case PCF_ACCELERATORS:
411 pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info);
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);
419 pcfPutINT32(file, format, bitmapFont->num_chars);
420 for (i = 0; i < bitmapFont->num_chars; i++)
421 pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics);
425 pcfPutINT32(file, format, bitmapFont->num_chars);
426 glyph = PCF_GLYPH_PAD(format);
428 for (i = 0; i < bitmapFont->num_chars; i++) {
429 pcfPutINT32(file, format, offset);
430 offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph);
432 for (i = 0; i < GLYPHPADOPTIONS; i++) {
433 pcfPutINT32(file, format,
434 bitmapFont->bitmapExtra->bitmapsSizes[i]);
436 for (i = 0; i < bitmapFont->num_chars; i++)
437 pcfPutBitmap(file, format, &bitmapFont->metrics[i]);
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]);
445 pcfPutINT32(file, format, bitmapFont->num_chars);
446 for (i = 0; i < bitmapFont->num_chars; i++)
447 pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]);
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);
460 pcfPutINT16(file, format, 0xFFFF);
464 pcfPutINT32(file, format, bitmapFont->num_chars);
465 for (i = 0; i < bitmapFont->num_chars; i++)
466 pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]);
468 case PCF_GLYPH_NAMES:
469 pcfPutINT32(file, format, bitmapFont->num_chars);
471 for (i = 0; i < bitmapFont->num_chars; i++) {
472 pcfPutINT32(file, format, offset);
473 offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
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);
481 case PCF_BDF_ACCELERATORS:
482 pcfPutAccel(file, table->format, &pFont->info);