-/* $XConsortium: pcfwrite.c,v 1.6 94/04/17 20:17:16 gildea Exp $ */
-
-/*
-
-Copyright (c) 1990, 1994 X Consortium
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from the X Consortium.
-
-*/
-
-/*
- * Author: Keith Packard, MIT X Consortium
- */
-
-
-#include "fntfilst.h"
-#include "bitmap.h"
-#include "pcf.h"
-
-/* Write PCF font files */
-
-static int current_position;
-
-static int
-pcfWrite(file, b, c)
- FontFilePtr file;
- char *b;
- int c;
-{
- current_position += c;
- return FontFileWrite(file, b, c);
-}
-
-static int
-pcfPutLSB32(file, c)
- FontFilePtr file;
-{
- current_position += 4;
- (void) FontFilePutc(c, file);
- (void) FontFilePutc(c >> 8, file);
- (void) FontFilePutc(c >> 16, file);
- return FontFilePutc(c >> 24, file);
-}
-
-static int
-pcfPutINT32(file, format, c)
- FontFilePtr file;
- CARD32 format;
-{
- current_position += 4;
- if (PCF_BYTE_ORDER(format) == MSBFirst) {
- (void) FontFilePutc(c >> 24, file);
- (void) FontFilePutc(c >> 16, file);
- (void) FontFilePutc(c >> 8, file);
- return FontFilePutc(c, file);
- } else {
- (void) FontFilePutc(c, file);
- (void) FontFilePutc(c >> 8, file);
- (void) FontFilePutc(c >> 16, file);
- return FontFilePutc(c >> 24, file);
- }
-}
-
-static int
-pcfPutINT16(file, format, c)
- FontFilePtr file;
- CARD32 format;
-{
- current_position += 2;
- if (PCF_BYTE_ORDER(format) == MSBFirst) {
- (void) FontFilePutc(c >> 8, file);
- return FontFilePutc(c, file);
- } else {
- (void) FontFilePutc(c, file);
- return FontFilePutc(c >> 8, file);
- }
-}
-
-/*ARGSUSED*/
-static int
-pcfPutINT8(file, format, c)
- FontFilePtr file;
- CARD32 format;
-{
- current_position += 1;
- return FontFilePutc(c, file);
-}
-
-static
-pcfWriteTOC(file, table, count)
- FontFilePtr file;
- PCFTablePtr table;
- int count;
-{
- CARD32 version;
- int i;
-
- version = PCF_FILE_VERSION;
- pcfPutLSB32(file, version);
- pcfPutLSB32(file, count);
- for (i = 0; i < count; i++) {
- pcfPutLSB32(file, table->type);
- pcfPutLSB32(file, table->format);
- pcfPutLSB32(file, table->size);
- pcfPutLSB32(file, table->offset);
- table++;
- }
-}
-
-static
-pcfPutCompressedMetric(file, format, metric)
- FontFilePtr file;
- CARD32 format;
- xCharInfo *metric;
-{
- pcfPutINT8(file, format, metric->leftSideBearing + 0x80);
- pcfPutINT8(file, format, metric->rightSideBearing + 0x80);
- pcfPutINT8(file, format, metric->characterWidth + 0x80);
- pcfPutINT8(file, format, metric->ascent + 0x80);
- pcfPutINT8(file, format, metric->descent + 0x80);
-}
-
-static
-pcfPutMetric(file, format, metric)
- FontFilePtr file;
- CARD32 format;
- xCharInfo *metric;
-{
- pcfPutINT16(file, format, metric->leftSideBearing);
- pcfPutINT16(file, format, metric->rightSideBearing);
- pcfPutINT16(file, format, metric->characterWidth);
- pcfPutINT16(file, format, metric->ascent);
- pcfPutINT16(file, format, metric->descent);
- pcfPutINT16(file, format, metric->attributes);
-}
-
-static
-pcfPutBitmap(file, format, pCI)
- FontFilePtr file;
- CARD32 format;
- CharInfoPtr pCI;
-{
- int count;
- unsigned char *bits;
-
- count = BYTES_FOR_GLYPH(pCI, PCF_GLYPH_PAD(format));
- bits = (unsigned char *) pCI->bits;
- current_position += count;
- while (count--)
- FontFilePutc(*bits++, file);
-}
-
-static
-pcfPutAccel(file, format, pFontInfo)
- FontFilePtr file;
- CARD32 format;
- FontInfoPtr pFontInfo;
-{
- pcfPutINT8(file, format, pFontInfo->noOverlap);
- pcfPutINT8(file, format, pFontInfo->constantMetrics);
- pcfPutINT8(file, format, pFontInfo->terminalFont);
- pcfPutINT8(file, format, pFontInfo->constantWidth);
- pcfPutINT8(file, format, pFontInfo->inkInside);
- pcfPutINT8(file, format, pFontInfo->inkMetrics);
- pcfPutINT8(file, format, pFontInfo->drawDirection);
- pcfPutINT8(file, format, 0);
- pcfPutINT32(file, format, pFontInfo->fontAscent);
- pcfPutINT32(file, format, pFontInfo->fontDescent);
- pcfPutINT32(file, format, pFontInfo->maxOverlap);
- pcfPutMetric(file, format, &pFontInfo->minbounds);
- pcfPutMetric(file, format, &pFontInfo->maxbounds);
- if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
- pcfPutMetric(file, format, &pFontInfo->ink_minbounds);
- pcfPutMetric(file, format, &pFontInfo->ink_maxbounds);
- }
-}
-
-#define S32 4
-#define S16 2
-#define S8 1
-
-#define Pad(s) (RoundUp(s) - (s))
-#define RoundUp(s) (((s) + 3) & ~3)
-
-#define Compressable(i) (-128 <= (i) && (i) <= 127)
-
-#define CanCompressMetric(m) (Compressable((m)->leftSideBearing) && \
- Compressable((m)->rightSideBearing) && \
- Compressable((m)->characterWidth) && \
- Compressable((m)->ascent) && \
- Compressable((m)->descent) && \
- (m)->attributes == 0)
-
-#define CanCompressMetrics(min,max) (CanCompressMetric(min) && CanCompressMetric(max))
-
-static char *
-pcfNameForAtom(a)
- Atom a;
-{
- return NameForAtom(a);
-}
-
-pcfWriteFont(pFont, file)
- FontPtr pFont;
- FontFilePtr file;
-{
- PCFTableRec tables[32],
- *table;
- CARD32 mask,
- bit;
- int ntables;
- int size;
- CARD32 format;
- int i;
- int cur_table;
- int prop_string_size;
- int glyph_string_size;
- xCharInfo *minbounds,
- *maxbounds;
- xCharInfo *ink_minbounds,
- *ink_maxbounds;
- BitmapFontPtr bitmapFont;
- int nencodings;
- int header_size;
- FontPropPtr offsetProps;
- int prop_pad;
- char *atom_name;
- int glyph;
- int offset;
-
- bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
- if (bitmapFont->bitmapExtra) {
- minbounds = &bitmapFont->bitmapExtra->info.minbounds;
- maxbounds = &bitmapFont->bitmapExtra->info.maxbounds;
- ink_minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds;
- ink_maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds;
- } else {
- minbounds = &pFont->info.minbounds;
- maxbounds = &pFont->info.maxbounds;
- ink_minbounds = &pFont->info.ink_minbounds;
- ink_maxbounds = &pFont->info.ink_maxbounds;
- }
- offsetProps = (FontPropPtr) xalloc(pFont->info.nprops * sizeof(FontPropRec));
- if (!offsetProps)
- return AllocError;
- prop_string_size = 0;
- for (i = 0; i < pFont->info.nprops; i++) {
- offsetProps[i].name = prop_string_size;
- prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].name)) + 1;
- if (pFont->info.isStringProp[i]) {
- offsetProps[i].value = prop_string_size;
- prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].value)) + 1;
- } else
- offsetProps[i].value = pFont->info.props[i].value;
- }
- format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan);
- mask = 0xFFFFFFF;
- ntables = 0;
- table = tables;
- while (mask) {
- bit = lowbit(mask);
- mask &= ~bit;
- table->type = bit;
- switch (bit) {
- case PCF_PROPERTIES:
- table->format = PCF_DEFAULT_FORMAT | format;
- size = S32 + S32 + (S32 + S8 + S32) * pFont->info.nprops;
- prop_pad = Pad(size);
- table->size = RoundUp(size) + S32 +
- RoundUp(prop_string_size);
- table++;
- break;
- case PCF_ACCELERATORS:
- if (bitmapFont->bitmapExtra->info.inkMetrics)
- table->format = PCF_ACCEL_W_INKBOUNDS | format;
- else
- table->format = PCF_DEFAULT_FORMAT | format;
- table->size = 100;
- table++;
- break;
- case PCF_METRICS:
- if (CanCompressMetrics(minbounds, maxbounds)) {
- table->format = PCF_COMPRESSED_METRICS | format;
- size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
- table->size = RoundUp(size);
- } else {
- table->format = PCF_DEFAULT_FORMAT | format;
- table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
- }
- table++;
- break;
- case PCF_BITMAPS:
- table->format = PCF_DEFAULT_FORMAT | format;
- size = S32 + S32 + bitmapFont->num_chars * S32 +
- GLYPHPADOPTIONS * S32 +
- bitmapFont->bitmapExtra->bitmapsSizes[PCF_GLYPH_PAD_INDEX(format)];
- table->size = RoundUp(size);
- table++;
- break;
- case PCF_INK_METRICS:
- if (bitmapFont->ink_metrics) {
- if (CanCompressMetrics(ink_minbounds, ink_maxbounds)) {
- table->format = PCF_COMPRESSED_METRICS | format;
- size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
- table->size = RoundUp(size);
- } else {
- table->format = PCF_DEFAULT_FORMAT | format;
- table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
- }
- table++;
- }
- break;
- case PCF_BDF_ENCODINGS:
- table->format = PCF_DEFAULT_FORMAT | format;
- nencodings = (pFont->info.lastRow - pFont->info.firstRow + 1) *
- (pFont->info.lastCol - pFont->info.firstCol + 1);
- size = S32 + 5 * S16 + nencodings * S16;
- table->size = RoundUp(size);
- table++;
- break;
- case PCF_SWIDTHS:
- table->format = PCF_DEFAULT_FORMAT | format;
- table->size = S32 + S32 + bitmapFont->num_chars * S32;
- table++;
- break;
- case PCF_GLYPH_NAMES:
- table->format = PCF_DEFAULT_FORMAT | format;
- glyph_string_size = 0;
- for (i = 0; i < bitmapFont->num_chars; i++)
- glyph_string_size += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
- table->size = S32 + S32 + bitmapFont->num_chars * S32 +
- S32 + RoundUp(glyph_string_size);
- table++;
- break;
- case PCF_BDF_ACCELERATORS:
- if (pFont->info.inkMetrics)
- table->format = PCF_ACCEL_W_INKBOUNDS | format;
- else
- table->format = PCF_DEFAULT_FORMAT | format;
- table->size = 100;
- table++;
- break;
- }
- }
- ntables = table - tables;
- offset = 0;
- header_size = S32 + S32 + ntables * (4 * S32);
- offset = header_size;
- for (cur_table = 0, table = tables;
- cur_table < ntables;
- cur_table++, table++) {
- table->offset = offset;
- offset += table->size;
- }
- current_position = 0;
- pcfWriteTOC(file, tables, ntables);
- for (cur_table = 0, table = tables;
- cur_table < ntables;
- cur_table++, table++) {
- if (current_position > table->offset) {
- printf("can't go backwards... %d > %d\n",
- current_position, table->offset);
- return BadFontName;
- }
- while (current_position < table->offset)
- pcfPutINT8(file, format, '\0');
- pcfPutLSB32(file, table->format);
- switch (table->type) {
- case PCF_PROPERTIES:
- pcfPutINT32(file, format, pFont->info.nprops);
- for (i = 0; i < pFont->info.nprops; i++) {
- pcfPutINT32(file, format, offsetProps[i].name);
- pcfPutINT8(file, format, pFont->info.isStringProp[i]);
- pcfPutINT32(file, format, offsetProps[i].value);
- }
- for (i = 0; i < prop_pad; i++)
- pcfPutINT8(file, format, 0);
- pcfPutINT32(file, format, prop_string_size);
- for (i = 0; i < pFont->info.nprops; i++) {
- atom_name = pcfNameForAtom(pFont->info.props[i].name);
- pcfWrite(file, atom_name, strlen(atom_name) + 1);
- if (pFont->info.isStringProp[i]) {
- atom_name = pcfNameForAtom(pFont->info.props[i].value);
- pcfWrite(file, atom_name, strlen(atom_name) + 1);
- }
- }
- break;
- case PCF_ACCELERATORS:
- pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info);
- break;
- case PCF_METRICS:
- if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
- pcfPutINT16(file, format, bitmapFont->num_chars);
- for (i = 0; i < bitmapFont->num_chars; i++)
- pcfPutCompressedMetric(file, format, &bitmapFont->metrics[i].metrics);
- } else {
- pcfPutINT32(file, format, bitmapFont->num_chars);
- for (i = 0; i < bitmapFont->num_chars; i++)
- pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics);
- }
- break;
- case PCF_BITMAPS:
- pcfPutINT32(file, format, bitmapFont->num_chars);
- glyph = PCF_GLYPH_PAD(format);
- offset = 0;
- for (i = 0; i < bitmapFont->num_chars; i++) {
- pcfPutINT32(file, format, offset);
- offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph);
- }
- for (i = 0; i < GLYPHPADOPTIONS; i++) {
- pcfPutINT32(file, format,
- bitmapFont->bitmapExtra->bitmapsSizes[i]);
- }
- for (i = 0; i < bitmapFont->num_chars; i++)
- pcfPutBitmap(file, format, &bitmapFont->metrics[i]);
- break;
- case PCF_INK_METRICS:
- if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
- pcfPutINT16(file, format, bitmapFont->num_chars);
- for (i = 0; i < bitmapFont->num_chars; i++)
- pcfPutCompressedMetric(file, format, &bitmapFont->ink_metrics[i]);
- } else {
- pcfPutINT32(file, format, bitmapFont->num_chars);
- for (i = 0; i < bitmapFont->num_chars; i++)
- pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]);
- }
- break;
- case PCF_BDF_ENCODINGS:
- pcfPutINT16(file, format, pFont->info.firstCol);
- pcfPutINT16(file, format, pFont->info.lastCol);
- pcfPutINT16(file, format, pFont->info.firstRow);
- pcfPutINT16(file, format, pFont->info.lastRow);
- pcfPutINT16(file, format, pFont->info.defaultCh);
- for (i = 0; i < nencodings; i++) {
- if (bitmapFont->encoding[i])
- pcfPutINT16(file, format, bitmapFont->encoding[i] - bitmapFont->metrics);
- else
- pcfPutINT16(file, format, 0xFFFF);
- }
- break;
- case PCF_SWIDTHS:
- pcfPutINT32(file, format, bitmapFont->num_chars);
- for (i = 0; i < bitmapFont->num_chars; i++)
- pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]);
- break;
- case PCF_GLYPH_NAMES:
- pcfPutINT32(file, format, bitmapFont->num_chars);
- offset = 0;
- for (i = 0; i < bitmapFont->num_chars; i++) {
- pcfPutINT32(file, format, offset);
- offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
- }
- pcfPutINT32(file, format, offset);
- for (i = 0; i < bitmapFont->num_chars; i++) {
- atom_name = pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i]);
- pcfWrite(file, atom_name, strlen(atom_name) + 1);
- }
- break;
- case PCF_BDF_ACCELERATORS:
- pcfPutAccel(file, table->format, &pFont->info);
- break;
- }
- }
- return Successful;
-}