]> git.sesse.net Git - rdpsrv/blobdiff - Xserver/lib/font/bitmap/pcfwrite.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / font / bitmap / pcfwrite.c
diff --git a/Xserver/lib/font/bitmap/pcfwrite.c b/Xserver/lib/font/bitmap/pcfwrite.c
new file mode 100644 (file)
index 0000000..b6dada7
--- /dev/null
@@ -0,0 +1,487 @@
+/* $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;
+}