home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / fonts / lib / font / bitmap / pcfwrite.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  14.5 KB  |  477 lines

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