PCFFont.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:19k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: PCFFont.c++,v 1.5 2008/04/26 22:34:28 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1994-1996 Sam Leffler
  4.  * Copyright (c) 1994-1996 Silicon Graphics, Inc.
  5.  * HylaFAX is a trademark of Silicon Graphics
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26. /*
  27.  * Read and render a PCF font.  This code is VERY distantly
  28.  * related to the X11R5 code found in the file pcfread.c (the
  29.  * original copyright is at the bottom of this file).
  30.  *
  31.  * This code is specifically written to handle just enough
  32.  * of the format to image text for outgoing facsimile.
  33.  */
  34. #include <unistd.h>
  35. #include <stdlib.h>
  36. #include "PCFFont.h"
  37. #include "tiffio.h"
  38. #define LSBFirst 0
  39. #define MSBFirst 1
  40. struct PCFTableRec { // on-disk table of contents
  41.     u_long type;
  42.     u_long format;
  43.     u_long size;
  44.     u_long offset;
  45. };
  46. struct charInfo {
  47.     short lsb, rsb; // left+right side bearing from file
  48.     short ascent, descent;// ascent+descent from file
  49.     u_short cw; // character width from file
  50.     u_char* bits; // pointer to glyph bitmap
  51. };
  52. #define PCF_FILE_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1)
  53. #define PCF_FORMAT_MASK 0xffffff00
  54. #define PCF_DEFAULT_FORMAT 0x00000000
  55. #define PCF_COMPRESSED_METRICS 0x00000100
  56. #define PCF_ACCEL_W_INKBOUNDS 0x00000100
  57. #define PCF_METRICS (1<<2) // font metric information
  58. #define PCF_BITMAPS (1<<3) // glyph bitmaps
  59. #define PCF_BDF_ENCODINGS (1<<5) // BDF-based encoding
  60. #define PCF_BDF_ACCELERATORS (1<<8) // BDF-derived accelerator information
  61. #define PCF_GLYPH_PAD_MASK (3<<0)
  62. #define PCF_BYTE_MASK (1<<2)
  63. #define PCF_BIT_MASK (1<<3)
  64. #define PCF_SCAN_UNIT_MASK (3<<4)
  65. #define CONFIG_BIT MSBFirst // required bit order
  66. #define CONFIG_BYTE MSBFirst // required byte order
  67. #define CONFIG_GLYPH 2 // glyphs must be word-aligned
  68. #define CONFIG_GLYPH_IX 1 // index for word-aligned glyphs
  69. inline bool PCFFont::isFormat(u_long f) const
  70.     { return ((format&PCF_FORMAT_MASK) == f); }
  71. inline u_int PCFFont::byteOrder() const
  72.     { return ((format&PCF_BYTE_MASK) ? MSBFirst : LSBFirst); }
  73. inline u_int PCFFont::bitOrder() const
  74.     { return ((format&PCF_BIT_MASK) ? MSBFirst : LSBFirst); }
  75. inline u_int PCFFont::glyphPadIndex() const
  76.     { return ((format) & PCF_GLYPH_PAD_MASK); }
  77. inline u_int PCFFont::glyphPad() const
  78.     { return (1<<glyphPadIndex()); }
  79. inline u_int PCFFont::scanUnit() const
  80.     { return (1<<((format) & PCF_SCAN_UNIT_MASK)); }
  81. PCFFont::PCFFont()
  82. {
  83.     file = NULL;
  84.     filename = NULL;
  85.     encoding = NULL;
  86.     bitmaps = NULL;
  87.     metrics = NULL;
  88.     toc = NULL;
  89.     cdef = NULL;
  90.     { union { int32 i; char c[4]; } u; u.i = 1; isBigEndian = u.c[0] == 0; }
  91. }
  92. PCFFont::~PCFFont()
  93. {
  94.     cleanup();
  95. }
  96. void
  97. PCFFont::cleanup()
  98. {
  99.     if (file != NULL)
  100. fclose(file), file = NULL;
  101.     ready = false;
  102.     delete toc, toc = NULL;
  103.     delete encoding, encoding = NULL;
  104.     delete bitmaps, bitmaps = NULL;
  105.     delete metrics, metrics = NULL;
  106.     cdef = NULL;
  107. }
  108. /*
  109.  * Read only the useful bits from a PCF font file:
  110.  * font metrics, font bitmaps, font encoding, and
  111.  * some of the accelerator info.
  112.  */
  113. bool
  114. PCFFont::read(const char* name)
  115. {
  116.     cleanup();
  117.     filename = name; // for error diagnostics
  118.     file = fopen(filename, "r");
  119.     if (file == NULL) {
  120. error("Can not open file");
  121. return (false);
  122.     }
  123.     if (!readTOC())
  124. return (false);
  125.     if (seekToTable(PCF_METRICS)) {
  126. format = getLSB32();
  127. if (isFormat(PCF_DEFAULT_FORMAT))
  128.     numGlyphs = getINT32();
  129. else if (isFormat(PCF_COMPRESSED_METRICS))
  130.     numGlyphs = getINT16();
  131. else {
  132.     error("Bad font metric format 0x%lx", format);
  133.     return (false);
  134. }
  135. metrics = new charInfo[numGlyphs];
  136. if (!metrics) {
  137.     error("No space for font metric information");
  138.     return (false);
  139. }
  140. for (u_int i = 0; i < numGlyphs; i++) {
  141.     if (isFormat(PCF_DEFAULT_FORMAT))
  142. getMetric(metrics[i]);
  143.     else
  144. getCompressedMetric(metrics[i]);
  145. }
  146.     } else {
  147. error("Can not seek to font metric information");
  148. return (false);
  149.     }
  150.     if (seekToTable(PCF_BITMAPS)) {
  151. format = getLSB32();
  152. if (!isFormat(PCF_DEFAULT_FORMAT)) {
  153.     error("Bad bitmap data format 0x%lx", format);
  154.     return (false);
  155. }
  156. u_long nbitmaps = getINT32();
  157. u_long* offsets = new u_long[nbitmaps];
  158. if (!offsets) {
  159.     error("No space for bitmap offsets array");
  160.     return (false);
  161. }
  162. for (u_int i = 0; i < nbitmaps; i++)
  163.     offsets[i] = getINT32();
  164. u_long bitmapSizes[4];
  165. bitmapSizes[0] = getINT32();
  166. bitmapSizes[1] = getINT32();
  167. bitmapSizes[2] = getINT32();
  168. bitmapSizes[3] = getINT32();
  169. u_long sizebitmaps = bitmapSizes[glyphPadIndex()];
  170. bitmaps = new u_char[sizebitmaps];
  171. if (!bitmaps) {
  172.     error("No space for bitmap data array");
  173.     delete offsets;
  174.     return (false);
  175. }
  176. if (fread(bitmaps, (u_int) sizebitmaps, 1, file) != 1) {
  177.     error("Error reading bitmap data");
  178.     delete offsets;
  179.     return (false);
  180. }
  181. if (bitOrder() != CONFIG_BIT)
  182.     TIFFReverseBits(bitmaps, sizebitmaps);
  183. if (byteOrder() != bitOrder()) {
  184.     switch (scanUnit()) {
  185.     case 2:
  186. TIFFSwabArrayOfShort((uint16*) bitmaps, sizebitmaps/2);
  187. break;
  188.     case 4:
  189. TIFFSwabArrayOfLong((uint32*) bitmaps, sizebitmaps/4);
  190. break;
  191.     default:
  192. error("Unknown scan unit format %dn", scanUnit());
  193. break;
  194.     }
  195. }
  196. if (!isBigEndian) // NB: rasterizer requires BE byte order
  197.     TIFFSwabArrayOfShort((u_short*) bitmaps, sizebitmaps/2);
  198. if (glyphPad() != CONFIG_GLYPH) {
  199.     u_long sizepadbitmaps = bitmapSizes[CONFIG_GLYPH_IX];
  200.     u_char* padbitmaps = new u_char[sizepadbitmaps];
  201.     if (!padbitmaps) {
  202. error("No space for padded bitmap data array");
  203. delete offsets;
  204. return (false);
  205.     }
  206.     int newoff = 0;
  207.     for (u_int i = 0; i < nbitmaps; i++) {
  208. off_t old = offsets[i];
  209. offsets[i] = newoff;
  210. const charInfo& metric = metrics[i];
  211. newoff += repadBitmap(bitmaps + old, padbitmaps + newoff,
  212.   glyphPad(), CONFIG_GLYPH,
  213.   metric.rsb - metric.lsb,
  214.   metric.ascent + metric.descent);
  215.     }
  216.     delete bitmaps;
  217.     bitmaps = padbitmaps;
  218. }
  219. for (u_int j = 0; j < nbitmaps; j++) {
  220.     metrics[j].bits = bitmaps + offsets[j];
  221.     if ((unsigned long) metrics[j].bits & 1) {
  222. error("Internal error, bitmap data not word-aligned");
  223. delete offsets;
  224. return (false);
  225.     }
  226. }
  227. delete offsets;
  228.     } else {
  229. error("Can not seek to bitmap data");
  230. return (false);
  231.     }
  232.     if (seekToTable(PCF_BDF_ENCODINGS)) {
  233. format = getLSB32();
  234. if (!isFormat(PCF_DEFAULT_FORMAT)) {
  235.     error("Bad encodings format 0x%lx", format);
  236.     return (false);
  237. }
  238. firstCol = getINT16();
  239. lastCol = getINT16();
  240. firstRow = getINT16();
  241. lastRow = getINT16();
  242. u_short defaultCh = getINT16();
  243. u_int nencoding = (lastCol-firstCol+1) * (lastRow-firstRow+1);
  244. encoding = new charInfo*[nencoding];
  245. if (!encoding) {
  246.     error("No space for character encoding vector");
  247.     return (false);
  248. }
  249. for (u_int i = 0; i < nencoding; i++) {
  250.     int encodingOffset = getINT16();
  251.     encoding[i] = (encodingOffset == 0xffff) ?
  252. 0 : metrics + encodingOffset;
  253. }
  254. if (defaultCh != (u_short)-1) {
  255.     int r = defaultCh >> 8;
  256.     int c = defaultCh & 0xff;
  257.     if (firstRow <= r && r <= lastRow && firstCol <= c && c <= lastCol) {
  258. int cols = lastCol - firstCol + 1;
  259. r = r - firstRow;
  260. c = c - firstCol;
  261. cdef = encoding[r * cols + c];
  262.     }
  263. }
  264.     } else {
  265. error("Can not seek to encoding data");
  266. return (false);
  267.     }
  268.     if (seekToTable(PCF_BDF_ACCELERATORS)) {
  269. format = getLSB32();
  270. if (!isFormat(PCF_DEFAULT_FORMAT) &&
  271.     !isFormat(PCF_ACCEL_W_INKBOUNDS)) {
  272.     error("Bad BDF accelerator format 0x%lx", format);
  273.     return (false);
  274. }
  275. fseek(file, 8, SEEK_CUR); // skip a bunch of junk
  276. fontAscent = (short) getINT32();
  277. fontDescent = (short) getINT32();
  278. // more stuff...
  279.     } else {
  280. error("Can not seek to BDF accelerator information");
  281. return (false);
  282.     }
  283.     fclose(file), file = NULL;
  284.     filename = NULL;
  285.     return (ready = true);
  286. }
  287. u_long
  288. PCFFont::getLSB32()
  289. {
  290.     u_long c = getc(file);
  291.     c |= getc(file) << 8;
  292.     c |= getc(file) << 16;
  293.     c |= getc(file) << 24;
  294.     return (c);
  295. }
  296. u_long
  297. PCFFont::getINT32()
  298. {
  299.     u_long c;
  300.     if (byteOrder() == MSBFirst) {
  301. c = getc(file) << 24;
  302. c |= getc(file) << 16;
  303. c |= getc(file) << 8;
  304. c |= getc(file);
  305.     } else {
  306. c = getc(file);
  307. c |= getc(file) << 8;
  308. c |= getc(file) << 16;
  309. c |= getc(file) << 24;
  310.     }
  311.     return (c);
  312. }
  313. int
  314. PCFFont::getINT16()
  315. {
  316.     int c;
  317.     if (byteOrder() == MSBFirst) {
  318. c = getc(file) << 8;
  319. c |= getc(file);
  320.     } else {
  321. c = getc(file);
  322. c |= getc(file) << 8;
  323.     }
  324.     return (c);
  325. }
  326. int PCFFont::getINT8() { return getc(file); }
  327. /*
  328.  * PCF supports two formats for metrics, both the regular
  329.  * jumbo size, and 'lite' metrics, which are useful
  330.  * for most fonts which have even vaguely reasonable
  331.  * metrics
  332.  */
  333. void
  334. PCFFont::getMetric(charInfo& metric)
  335. {
  336.     metric.lsb = getINT16();
  337.     metric.rsb = getINT16();
  338.     metric.cw = getINT16();
  339.     metric.ascent = getINT16();
  340.     metric.descent = getINT16();
  341.     (void) getINT16(); // attributes
  342. }
  343. void
  344. PCFFont::getCompressedMetric(charInfo& metric)
  345. {
  346.     metric.lsb = getINT8() - 0x80;
  347.     metric.rsb = getINT8() - 0x80;
  348.     metric.cw = getINT8() - 0x80;
  349.     metric.ascent = getINT8() - 0x80;
  350.     metric.descent = getINT8() - 0x80;
  351. }
  352. /*
  353.  * Position to the begining of the specified table.
  354.  */
  355. bool
  356. PCFFont::seekToTable(u_long type)
  357. {
  358.     for (u_int i = 0; i < tocSize; i++)
  359. if (toc[i].type == type) {
  360.     if (fseek(file, toc[i].offset, SEEK_SET) == -1) {
  361. error("Can not seek; fseek failed");
  362. return (false);
  363.     }
  364.     format = toc[i].format;
  365.     return (true);
  366. }
  367.     error("Can not seek; no such entry in the TOC");
  368.     return (false);
  369. }
  370. /*
  371.  * Read the table-of-contents for the font file.
  372.  */
  373. bool
  374. PCFFont::readTOC()
  375. {
  376.     u_long version = getLSB32();
  377.     if (version != PCF_FILE_VERSION) {
  378. error("Cannot read TOC; bad version number %lu", version);
  379. return (false);
  380.     }
  381.     tocSize = getLSB32();
  382.     toc = new PCFTableRec[tocSize];
  383.     if (!toc) {
  384. error("Cannot read TOC; no space for %lu records", tocSize);
  385. return (false);
  386.     }
  387.     for (u_int i = 0; i < tocSize; i++) {
  388. toc[i].type = getLSB32();
  389. toc[i].format = getLSB32();
  390. toc[i].size = getLSB32();
  391. toc[i].offset = getLSB32();
  392.     }
  393.     return (true);
  394. }
  395. int
  396. PCFFont::repadBitmap(u_char* src, u_char* dst, u_long spad, u_long dpad, int w, int h)
  397. {
  398.     int srcWidthBytes;
  399.     switch (spad) {
  400.     case 1: srcWidthBytes = (w+7)>>3; break;
  401.     case 2: srcWidthBytes = ((w+15)>>4)<<1; break;
  402.     case 4: srcWidthBytes = ((w+31)>>5)<<2; break;
  403.     case 8: srcWidthBytes = ((w+63)>>6)<<3; break;
  404.     default: return 0;
  405.     }
  406.     int dstWidthBytes;
  407.     switch (dpad) {
  408.     case 1: dstWidthBytes = (w+7)>>3; break;
  409.     case 2: dstWidthBytes = ((w+15)>>4)<<1; break;
  410.     case 4: dstWidthBytes = ((w+31)>>5)<<2; break;
  411.     case 8: dstWidthBytes = ((w+63)>>6)<<3; break;
  412.     default: return 0;
  413.     }
  414.     w = srcWidthBytes;
  415.     if (w > dstWidthBytes)
  416. w = dstWidthBytes;
  417.     for (int row = 0; row < h; row++) {
  418. int col;
  419. for (col = 0; col < w; col++)
  420.     *dst++ = *src++;
  421. while (col < dstWidthBytes) {
  422.     *dst++ = '';
  423.     col++;
  424. }
  425. src += srcWidthBytes - w;
  426.     }
  427.     return (dstWidthBytes * h);
  428. }
  429. u_int
  430. PCFFont::charWidth(u_int c) const
  431. {
  432.     if (ready) {
  433. charInfo* ci = (firstCol <= c && c <= lastCol) ?
  434.     encoding[c - firstCol] : cdef;
  435. return (ci ? ci->cw : 0);
  436.     } else
  437. return (0);
  438. }
  439. void
  440. PCFFont::strWidth(const char* text, u_int &sw, u_int& sh) const
  441. {
  442.     sh = fontHeight();
  443.     sw = 0;
  444.     if (ready) {
  445. for (const char* cp = text; *cp; cp++) {
  446.     u_int g = *cp;
  447.     charInfo* ci = (firstCol <= g && g <= lastCol) ?
  448. encoding[g - firstCol] : cdef;
  449.     if (ci)
  450. sw += ci->cw;
  451. }
  452.     }
  453. }
  454. /* merge Left/Right bits from a word in a glyph bitmap */
  455. #define MERGEL(r,g,dx,dm) 
  456.     (r) = ((r) &~ (dm)) | (((g)>>dx) & (dm))
  457. #define MERGER(r,g,dx,dm) 
  458.     (r) = ((r) &~ (dm)) | (((g)<<(dx)) & (dm))
  459. /*
  460.  * Image text into a raster.  The raster origin (0,0) is assumed to
  461.  * be in the upper left.  Text is imaged from top-to-bottom and
  462.  * left-to-right.  The height of the rendered text is returned.
  463.  */
  464. u_int
  465. PCFFont::imageText(const char* text, bool isutf8,
  466.     u_short* raster, u_int w, u_int h,
  467.     u_int lm, u_int rm, u_int tm, u_int bm) const
  468. {
  469.     if (!ready)
  470. return (0);
  471.     u_int rowwords = howmany(w,16);
  472.     u_int y = tm + fontAscent;
  473.     u_int x = lm;
  474.     /*
  475.      * The rasterize assumes words have a big-endian
  476.      * byte order.  For now (rather than fix it) we
  477.      * byte swap the data coming in and going out.
  478.      */
  479.     if (!isBigEndian) // XXX
  480. TIFFSwabArrayOfShort((u_short*) raster, h*rowwords);
  481.     const char* cp = text;
  482.     for (; *cp; cp++) {
  483. u_int g = (u_int)*cp;
  484. if (isutf8 && (g >= 0xC0)) { // first byte in a multibyte character
  485.     /*
  486.      * We probably could use mbstowcs and not perform
  487.      * the UTF-8 decoding ourselves; however, this saves
  488.      * us from needing to use #ifdef __STDC_ISO_10646__
  489.      * and thus able to support UTF-8 on systems where
  490.      * it is not.
  491.      */
  492.     u_short morebytes = 0;
  493.     if ((g & 0x20) == 0) {
  494. morebytes = 1;
  495. g &= 0x1F;
  496.     } else if ((g & 0x10) == 0) {
  497. morebytes = 2;
  498. g &= 0xF;
  499.     } else if ((g & 0x8) == 0) {
  500. morebytes = 3;
  501. g &= 0x7;
  502.     } else if ((g & 0x4) == 0) {
  503. morebytes = 4;
  504. g &= 0x3;
  505.     } else if ((g & 0x2) == 0) {
  506. morebytes = 5;
  507. g &= 0x1;
  508.     }
  509.     for (cp++; morebytes && *cp; morebytes--, cp++) {
  510. g <<= 6;
  511. g += (*cp & 0x3F);
  512.     }
  513.     cp--; // back up one
  514. }
  515. int l = g >> 8;
  516. int c = g & 0xff;
  517. charInfo* ci = (firstRow <= l && l <= lastRow && firstCol <= c && c <= lastCol) ?
  518.     encoding[g - firstCol] : cdef;
  519. if (!ci)
  520.     continue;
  521. if (x + ci->cw > w - rm) { // no space on line, move down
  522.     if (y+fontHeight() >= h-bm)
  523. break; // raster completely full
  524.     y += fontHeight();
  525.     x = lm;
  526. }
  527. /*
  528.  * Blit glyph bitmap into raster.  The work done here is
  529.  * not designed for speed.  We break the work into two cases;
  530.  * where the destination location in the raster is word-aligned
  531.  * and where it's not word-aligned.  Glyph bitmaps are assumed
  532.  * to be word-padded and to have the bits ``left adjusted''
  533.  * within words.  Note that we handle glyphs that are at
  534.  * most 47 bits wide; this should be sufficient for our needs.
  535.  */
  536. u_short cw = ci->rsb - ci->lsb; // bitmap glyph width
  537. u_short cwords = cw>>4; // full words in glyph
  538. if (cwords > 2) // skip too wide glyph
  539.     continue;
  540. int cx = x + ci->lsb; // left edge of glyph
  541. int ch = ci->ascent + ci->descent; // glyph height
  542. u_short* rp = raster + (y-ci->ascent)*rowwords + (cx>>4);
  543. u_short* gp = (u_short*) ci->bits;
  544. u_short dx0 = cx&15; // raster word offset
  545. u_short rowdelta = rowwords - cwords; // raster row adjust factor
  546. u_short cbits = cw&15; // partial glyph word
  547. if (dx0 != 0) { // hard case, raster unaligned
  548.     u_short dm0 = 0xffff>>dx0;
  549.     u_short dx1 = 16-dx0;
  550.     u_short dm1 = ~dm0;
  551.     u_short dm2, dm3;
  552.     if (cbits > dx1) { // spills into 2nd word
  553. dm2 = dm0;
  554. dm3 = ~((1<<dx1)-1);
  555.     } else { // fits entirely into 1st word
  556. dm2 = dm0 &~ ((1<<(dx1-cbits))-1);
  557. dm3 = 0;
  558.     }
  559.     for (short r = 0; r < ch; r++) {
  560. switch (cwords) { // merge complete glyph words
  561. case 2: MERGEL(rp[0], gp[0], dx0, dm0);
  562. MERGER(rp[1], gp[0], dx1, dm1);
  563. rp++, gp++;
  564. case 1: MERGEL(rp[0], gp[0], dx0, dm0);
  565. MERGER(rp[1], gp[0], dx1, dm1);
  566. rp++, gp++;
  567. }
  568. if (cbits) {
  569.     MERGEL(rp[0], gp[0], dx0, dm2);
  570.     MERGER(rp[1], gp[0], dx1, dm3);
  571.     gp++;
  572. }
  573. rp += rowdelta;
  574.     }
  575. } else { // raster word-aligned
  576.     u_short dm = 0xffff<<(16-cbits);
  577.     for (short r = 0; r < ch; r++) {
  578. switch (cwords) {
  579. case 2: *rp++ = *gp++;
  580. case 1: *rp++ = *gp++;
  581. }
  582. if (cbits)
  583.     MERGEL(*rp, *gp++, 0, dm);
  584. rp += rowdelta;
  585.     }
  586. }
  587. x += ci->cw;
  588.     }
  589.     if (!isBigEndian) // XXX
  590. TIFFSwabArrayOfShort((u_short*) raster, h*rowwords);
  591.     return (y+fontDescent+bm);
  592. }
  593. #undef MERGEL
  594. #undef MERGER
  595. #include <ctype.h>
  596. void
  597. PCFFont::print(FILE* fd) const
  598. {
  599.     if (ready) {
  600. fprintf(fd, "Font Ascent: %d Descent: %dn", fontAscent, fontDescent);
  601. fprintf(fd, "FirstCol: %u LastCol: %un", firstCol, lastCol);
  602. fprintf(fd, "%lu glyphs:n", numGlyphs);
  603. for (u_int c = firstCol; c <= lastCol; c++) {
  604.     charInfo* ci = encoding[c - firstCol];
  605.     if (!ci)
  606. continue;
  607.     if (isprint(c))
  608. fprintf(fd,
  609.     "'%c': lsb %2d rsb %2d cw %2d ascent %2d descent %dn",
  610.     c, ci->lsb, ci->rsb, ci->cw, ci->ascent, ci->descent);
  611.     else
  612. fprintf(fd,
  613.     "%3d: lsb %2d rsb %2d cw %2d ascent %2d descent %dn",
  614.     c, ci->lsb, ci->rsb, ci->cw, ci->ascent, ci->descent);
  615. }
  616.     }
  617. }
  618. #include "Str.h"
  619. extern void vlogError(const char* fmt, va_list ap);
  620. void
  621. PCFFont::error(const char* fmt0 ...)
  622. {
  623.     va_list ap;
  624.     va_start(ap, fmt0);
  625.     fxStr fmt = fxStr::format("PCFFont: %s: %s",
  626. filename ? filename : "<unknown file>", fmt0);
  627.     vlogError(fmt, ap);
  628.     va_end(ap);
  629. }
  630. /*
  631.  * $XConsortium: pcfread.c,v 1.10 92/05/12 18:07:47 gildea Exp $
  632.  *
  633.  * Copyright 1990 Massachusetts Institute of Technology
  634.  *
  635.  * Permission to use, copy, modify, distribute, and sell this software and its
  636.  * documentation for any purpose is hereby granted without fee, provided that
  637.  * the above copyright notice appear in all copies and that both that
  638.  * copyright notice and this permission notice appear in supporting
  639.  * documentation, and that the name of M.I.T. not be used in advertising or
  640.  * publicity pertaining to distribution of the software without specific,
  641.  * written prior permission.  M.I.T. makes no representations about the
  642.  * suitability of this software for any purpose.  It is provided "as is"
  643.  * without express or implied warranty.
  644.  *
  645.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  646.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  647.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  648.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  649.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  650.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  651.  *
  652.  * Author:  Keith Packard, MIT X Consortium
  653.  */