home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / g / gs241j11.zip / ZKFPCF.C < prev    next >
C/C++ Source or Header  |  1992-07-01  |  23KB  |  929 lines

  1. /*
  2.  * zkfpcf.c --- Kanji font operator for X11R5 PCF format file
  3.  *
  4.  * Copyright (C) 1991 Norio Katayama.
  5.  * Sep. 10, 1991 Programmed by N.Katayama (katayama@nacsis.ac.jp)
  6.  */
  7.  
  8. #include "memory_.h"
  9. #include "ghost.h"
  10. #include "oper.h"
  11. #include "errors.h"
  12. #include "gsmatrix.h"
  13. #include "state.h"
  14. #include "store.h"
  15.  
  16. #define B_X_CL    500    /* horizontal center in BuildChar */
  17. #define B_Y_CL    400    /* vertical center in BuildChar */
  18.  
  19. /* Imported procedures */
  20.  
  21. extern int kf_is_vchar(P1(int));
  22. extern int kf_vmatrix(P5(int, floatp, floatp, gs_rect *, gs_matrix *));
  23. extern int gs_imagebbox(P6(int width, int height, int bool, 
  24.                gs_matrix *pmat, byte *image, gs_rect *));
  25.  
  26. /* Forward declaration */
  27.  
  28. private int pcfimage(P9(char *, int, int *, int *, byte *, int,
  29.             gs_matrix *, floatp *, floatp *));
  30.  
  31. /*
  32.  * zkfpcf
  33.  */
  34.  
  35. int
  36. zkfpcf(register os_ptr op)
  37. {
  38.     char *buffer;
  39.     int code, len, width, height, length;
  40.     int jis_code, wmode;
  41.     byte *bitmap;
  42.     floatp w0x, w0y;
  43.     gs_matrix *pmat, vmat, imat;
  44.     gs_rect bbox;
  45.  
  46.     check_type(op[-4], t_integer);        /* JIS Code */
  47.     check_type(op[-3], t_integer);        /* WMode */
  48.     if((code = write_matrix(op - 2)) < 0)    /* ImageMatrix */
  49.         return code;
  50.     check_type(op[-1], t_string);        /* ImageString */
  51.     check_type(op[0], t_string);        /* FileName */
  52.  
  53.     len = r_size(op);
  54.     if((buffer = gs_malloc(len + 1, 1, "zkfpcf")) == 0)
  55.         return e_VMerror;
  56.     memcpy(buffer, (char *)op->value.bytes, len);
  57.     buffer[len] = 0;
  58.  
  59.     jis_code = op[-4].value.intval;
  60.     wmode = op[-3].value.intval;
  61.  
  62.     bitmap = op[-1].value.bytes;
  63.     length = r_size(op - 1);
  64.     pmat = (gs_matrix *)op[-2].value.refs;
  65.  
  66.     if((code = pcfimage(buffer, jis_code, 
  67.                 &width, &height, bitmap, length,
  68.                 pmat, &w0x, &w0y)) < 0)
  69.         return code;
  70.  
  71.     if((code = gs_imagebbox(width, height, 1, pmat, bitmap, &bbox)) < 0)
  72.         return code;
  73.  
  74.     if(wmode && kf_is_vchar(jis_code)) {
  75.         kf_vmatrix(jis_code,
  76.                (floatp)B_X_CL, (floatp)B_Y_CL, &bbox, &vmat);
  77.         gs_matrix_invert(&vmat, &imat);
  78.         gs_matrix_multiply(&imat, pmat, pmat);
  79.     }
  80.  
  81.     /* Push results */
  82.     /* w0x w0y llx lly urx ury width height bool matrix bitmap */
  83.     push(6);
  84.     make_real(op - 10, w0x);
  85.     make_real(op - 9, w0y);
  86.     make_real(op - 8, bbox.p.x);
  87.     make_real(op - 7, bbox.p.y);
  88.     make_real(op - 6, bbox.q.x);
  89.     make_real(op - 5, bbox.q.y);
  90.     make_int(op - 4, width);
  91.     make_int(op - 3, height);
  92.     make_bool(op - 2 , 1);
  93.     make_tasv(op - 1, t_array, a_all, 6, refs, (ref *)pmat);
  94.     make_tasv(op, t_string, a_all, length, bytes, bitmap);
  95.     gs_free(buffer, len + 1, 1, "zkfpcf");
  96.     return 0;
  97. }
  98.  
  99. /* -------- Initialization procedure -------- */
  100.  
  101. op_def zkfpcf_op_defs[] = {
  102.     {"5kfpcf", zkfpcf},
  103.     op_def_end(0)
  104. };
  105.  
  106. /*--------- The part below is written with reference to pcfread.c  -------*/
  107. /*------------- which is included in MIT X11R5 distribution. -------------*/
  108.  
  109. /*
  110.  * $XConsortium: pcfread.c,v 1.7 91/07/22 22:58:57 keith Exp $
  111.  *
  112.  * Copyright 1990 Massachusetts Institute of Technology
  113.  *
  114.  * Permission to use, copy, modify, distribute, and sell this software and its
  115.  * documentation for any purpose is hereby granted without fee, provided that
  116.  * the above copyright notice appear in all copies and that both that
  117.  * copyright notice and this permission notice appear in supporting
  118.  * documentation, and that the name of M.I.T. not be used in advertising or
  119.  * publicity pertaining to distribution of the software without specific,
  120.  * written prior permission.  M.I.T. makes no representations about the
  121.  * suitability of this software for any purpose.  It is provided "as is"
  122.  * without express or implied warranty.
  123.  *
  124.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  125.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  126.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  127.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  128.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  129.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  130.  *
  131.  * Author:  Keith Packard, MIT X Consortium
  132.  */
  133.  
  134. /* X11 headers */
  135.  
  136. #undef min    /* min and max are defined in X11/misc.h */
  137. #undef max
  138. #undef private    /* private is used as a variable name in fontstruct.h */
  139. #define name _name    /* circumvent the conflict between type and ident */
  140.  
  141. #ifdef BSD4_2    /* circumvent the conflict between Xfuncs.h and memory_.h */
  142. #define bcopy _bcopy
  143. #define bzero _bzero
  144. #include <X11/Xfuncs.h>
  145. #undef bcopy
  146. #undef bzero
  147. #endif
  148.  
  149. #include <X11/X.h>
  150. #include <X11/Xproto.h>
  151. #include "servermd.h"
  152. #include "fontmisc.h"
  153. #include "fontstruct.h"
  154. #include "pcf.h"
  155.  
  156. #ifdef NOPRIVATE
  157. #define private /* */
  158. #else
  159. #define private static
  160. #endif
  161.  
  162. /* Temporary Font Information */
  163.  
  164. typedef struct TempFontRec {
  165.     PCFTablePtr tables;
  166.     int ntables;
  167.     FontInfoPtr pFI;
  168.     CharInfoPtr pCI;
  169.     CharInfoPtr *encoding;
  170.     CARD32 bitmap_format;
  171.     char *strings;
  172.     int pixel_size;
  173. } TempFont, *TempFontPtr;
  174.  
  175. #define ReallyNonExistent(pci) \
  176.   ((((pci)->metrics.leftSideBearing + \
  177.      (pci)->metrics.rightSideBearing) == 0) && \
  178.    (((pci)->metrics.ascent + (pci)->metrics.descent) == 0))
  179.  
  180. private CARD32
  181. pcfGetLSB32(FILE *fp)
  182. {
  183.     unsigned char buffer[4];
  184.     CARD32 c;
  185.  
  186.     fread(buffer, 1, 4, fp);
  187.     c = (unsigned long)buffer[0];
  188.     c |= (unsigned long)buffer[1] << 8;
  189.     c |= (unsigned long)buffer[2] << 16;
  190.     c |= (unsigned long)buffer[3] << 24;
  191.     return c;
  192. }
  193.  
  194. private long
  195. pcfGetINT32(FILE *fp, CARD32 format)
  196. {
  197.     unsigned char buffer[4];
  198.     long c;
  199.  
  200.     fread(buffer, 1, 4, fp);
  201.  
  202.     if(PCF_BYTE_ORDER(format) == MSBFirst) {
  203.         c = (unsigned long)buffer[0] << 24;
  204.         c |= (unsigned long)buffer[1] << 16;
  205.         c |= (unsigned long)buffer[2] << 8;
  206.         c |= (unsigned long)buffer[3];
  207.     }
  208.     else {
  209.         c = (unsigned long)buffer[0];
  210.         c |= (unsigned long)buffer[1] << 8;
  211.         c |= (unsigned long)buffer[2] << 16;
  212.         c |= (unsigned long)buffer[3] << 24;
  213.     }
  214.     return c;
  215. }
  216.  
  217. private int
  218. pcfGetINT16(FILE *fp, CARD32 format)
  219. {
  220.     unsigned char buffer[2];
  221.     int c;
  222.  
  223.     fread(buffer, 1, 2, fp);
  224.  
  225.     if(PCF_BYTE_ORDER(format) == MSBFirst) {
  226.         c = (unsigned int)buffer[0] << 8;
  227.         c |= (unsigned int)buffer[1];
  228.     }
  229.     else {
  230.         c = (unsigned int)buffer[0];
  231.         c |= (unsigned int)buffer[1] << 8;
  232.     }
  233.     return c;
  234. }
  235.  
  236. #define pcfGetINT8(fp, format)    fgetc(fp)
  237.  
  238. private void
  239. BitOrderInvert(unsigned char *ptr, int length)
  240. {
  241.     int i, j, k;
  242.     unsigned char c;
  243.  
  244.     for(i=0; i<length; i++, ptr++) {
  245.         c = 0;
  246.         for(j=0, k=7; j < 8; j++, k--)
  247.             c |= ((*ptr >> j) & 1) << k;
  248.         *ptr = c;
  249.     }
  250. }
  251.  
  252. private void
  253. TwoByteSwap(unsigned char *ptr, int length)
  254. {
  255.     int i;
  256.     unsigned char c;
  257.  
  258.     for(i=0; i<length; i += 2) {
  259.         c = ptr[i];
  260.         ptr[i] = ptr[i+1];
  261.         ptr[i+1] = c;
  262.     }
  263. }
  264.  
  265. private void
  266. FourByteSwap(unsigned char *ptr, int length)
  267. {
  268.     int i;
  269.     unsigned char c;
  270.  
  271.     for(i=0; i<length; i += 4) {
  272.         c = ptr[i];
  273.         ptr[i] = ptr[i+3];
  274.         ptr[i+3] = c;
  275.         c = ptr[i+1];
  276.         ptr[i+1] = ptr[i+2];
  277.         ptr[i+2] = c;
  278.     }
  279. }
  280.  
  281. private int
  282. pcfReadTOC(FILE *fp, PCFTablePtr *ptables, int *pcount)
  283. {
  284.     CARD32    version;
  285.     PCFTablePtr tables;
  286.     int count;
  287.     int i;
  288.  
  289.     version = pcfGetLSB32(fp);
  290.     if(version != PCF_FILE_VERSION)
  291.         return e_undefinedfilename;
  292.     count = pcfGetLSB32(fp);
  293.     if((tables = (PCFTablePtr)malloc(count * sizeof(PCFTableRec))) == 0)
  294.         return e_VMerror;
  295.  
  296.     for(i=0; i<count; i++) {
  297.         tables[i].type = pcfGetLSB32(fp);
  298.         tables[i].format = pcfGetLSB32(fp);
  299.         tables[i].size = pcfGetLSB32(fp);
  300.         tables[i].offset = pcfGetLSB32(fp);
  301.     }
  302.     *ptables = tables;
  303.     *pcount = count;
  304.     return 0;
  305. }
  306.  
  307. private int
  308. pcfGetMetric(FILE *fp, CARD32 format, xCharInfo *metric)
  309. {
  310.     metric->leftSideBearing = pcfGetINT16(fp, format);
  311.     metric->rightSideBearing = pcfGetINT16(fp, format);
  312.     metric->characterWidth = pcfGetINT16(fp, format);
  313.     metric->ascent = pcfGetINT16(fp, format);
  314.     metric->descent = pcfGetINT16(fp, format);
  315.     metric->attributes = pcfGetINT16(fp, format);
  316. }
  317.  
  318. private int
  319. pcfGetCompressedMetric(FILE *fp, CARD32 format, xCharInfo *metric)
  320. {
  321.     metric->leftSideBearing = pcfGetINT8(fp, format) - 0x80;
  322.     metric->rightSideBearing = pcfGetINT8(fp, format) - 0x80;
  323.     metric->characterWidth = pcfGetINT8(fp, format) - 0x80;
  324.     metric->ascent = pcfGetINT8(fp, format) - 0x80;
  325.     metric->descent = pcfGetINT8(fp, format) - 0x80;
  326.     metric->attributes = 0;
  327. }
  328.  
  329. private int
  330. pcfSeekToType(FILE *fp, PCFTablePtr tables, int ntables, CARD32 type, 
  331.           CARD32 *pformat, CARD32 *psize)
  332. {
  333.     int i;
  334.  
  335.     for(i=0; i<ntables; i++) {
  336.         if(tables[i].type == type) {
  337.             fseek(fp, tables[i].offset, 0);
  338.             *psize = tables[i].size;
  339.             *pformat = tables[i].format;
  340.             return 1;
  341.         }
  342.     }
  343.     return 0;
  344. }
  345.  
  346. private int
  347. pcfHasType(PCFTablePtr tables, int ntables, CARD32 type)
  348. {
  349.     int         i;
  350.  
  351.     for (i = 0; i < ntables; i++)
  352.     if (tables[i].type == type)
  353.         return 1;
  354.     return 0;
  355. }
  356.  
  357. private int
  358. pcfGetProperties(FILE *fp, PCFTablePtr tables, int ntables, 
  359.          FontInfoPtr pFontInfo, char **strings_return)
  360. {
  361.     FontPropPtr props;
  362.     int nprops;
  363.     char *isStringProp;
  364.     CARD32 format, size;
  365.     int i, string_size;
  366.     char *strings;
  367.  
  368.     /* font properties */
  369.  
  370.     if(!pcfSeekToType(fp, tables, ntables, PCF_PROPERTIES, &format, &size))
  371.         return e_undefinedfilename;
  372.     format = pcfGetLSB32(fp);
  373.     if(!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
  374.         return e_undefinedfilename;
  375.     nprops = pcfGetINT32(fp, format);
  376.     if((props = (FontPropPtr)malloc(nprops * sizeof(FontPropRec))) == 0)
  377.         return e_VMerror;
  378.     if((isStringProp = (char *)malloc(nprops * sizeof(char))) == 0)
  379.         return e_VMerror;
  380.     for(i=0; i<nprops; i++) {
  381.         props[i].name = pcfGetINT32(fp, format);
  382.         isStringProp[i] = pcfGetINT8(fp, format);
  383.         props[i].value = pcfGetINT32(fp, format);
  384.     }
  385.     /* pad the property array */
  386.     /*
  387.      * clever here - nprops is the same as the number of odd-units read, as
  388.      * only isStringProp are odd length
  389.      */
  390.     if (nprops & 3)    {
  391.         i = 4 - (nprops & 3);
  392.         fseek(fp, i, 1);
  393.     }
  394.     string_size = pcfGetINT32(fp, format);
  395.     if((strings = (char *)malloc(string_size)) == 0)
  396.         return e_VMerror;
  397.     fread(strings, 1, string_size, fp);
  398.  
  399.     pFontInfo->isStringProp = isStringProp;
  400.     pFontInfo->props = props;
  401.     pFontInfo->nprops = nprops;
  402.     *strings_return = strings;
  403.  
  404.     return 0;
  405. }
  406.  
  407. private int
  408. pcfGetAccel(FontInfoPtr pFontInfo, FILE *fp, 
  409.         PCFTablePtr tables, int ntables, CARD32 type)
  410. {
  411.     CARD32      format;
  412.     CARD32    size;
  413.  
  414.     if (!pcfSeekToType(fp, tables, ntables, type, &format, &size))
  415.         return e_undefinedfilename;
  416.     format = pcfGetLSB32(fp);
  417.     if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
  418.     !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) 
  419.         return e_undefinedfilename;
  420.     pFontInfo->noOverlap = pcfGetINT8(fp, format);
  421.     pFontInfo->constantMetrics = pcfGetINT8(fp, format);
  422.     pFontInfo->terminalFont = pcfGetINT8(fp, format);
  423.     pFontInfo->constantWidth = pcfGetINT8(fp, format);
  424.     pFontInfo->inkInside = pcfGetINT8(fp, format);
  425.     pFontInfo->inkMetrics = pcfGetINT8(fp, format);
  426.     pFontInfo->drawDirection = pcfGetINT8(fp, format);
  427.     pFontInfo->anamorphic = FALSE;
  428.      /* natural alignment */ pcfGetINT8(fp, format);
  429.     pFontInfo->fontAscent = pcfGetINT32(fp, format);
  430.     pFontInfo->fontDescent = pcfGetINT32(fp, format);
  431.     pFontInfo->maxOverlap = pcfGetINT32(fp, format);
  432.     pcfGetMetric(fp, format, &pFontInfo->minbounds);
  433.     pcfGetMetric(fp, format, &pFontInfo->maxbounds);
  434.     if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
  435.     pcfGetMetric(fp, format, &pFontInfo->ink_minbounds);
  436.     pcfGetMetric(fp, format, &pFontInfo->ink_maxbounds);
  437.     } else {
  438.     pFontInfo->ink_minbounds = pFontInfo->minbounds;
  439.     pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
  440.     }
  441.     return 0;
  442. }
  443.  
  444. private int
  445. GetTempFont(char *file, FILE **pfp, TempFont **ptf)
  446. {
  447.     int i;
  448.     int nencoding, nmetrics, nbitmaps, sizebitmaps;
  449.     CARD32 format, size, bitmapSizes[GLYPHPADOPTIONS];
  450.     int hasBDFAccelerators;
  451.     long offset;
  452.     FILE *fp;
  453.     TempFont *tf;
  454.  
  455.     if((fp = fopen(file, "r")) == NULL)
  456.         return e_undefinedfilename;
  457.  
  458.     if((tf = (TempFont *)malloc(sizeof(TempFont))) == 0) {
  459.         fclose(fp);
  460.         return e_VMerror;
  461.     }
  462.  
  463.     if((tf->pFI = (FontInfoPtr)malloc(sizeof(FontInfoRec))) == 0) {
  464.         fclose(fp);
  465.         return e_VMerror;
  466.     }
  467.  
  468.     if(pcfReadTOC(fp, &tf->tables, &tf->ntables) < 0) {
  469.         fclose(fp);
  470.         return e_undefinedfilename;
  471.     }
  472.  
  473.     /* properties */
  474.  
  475.     if(pcfGetProperties(fp, tf->tables, tf->ntables, 
  476.             tf->pFI, &tf->strings) < 0) {
  477.         fclose(fp);
  478.         return e_undefinedfilename;
  479.     }
  480.  
  481.     /* Use the old accelerators if no BDF accelerators are in the file */
  482.  
  483.     hasBDFAccelerators = 
  484.         pcfHasType(tf->tables, tf->ntables, PCF_BDF_ACCELERATORS);
  485.     if (!hasBDFAccelerators) {
  486.         if(pcfGetAccel(tf->pFI, fp, 
  487.                tf->tables, tf->ntables, PCF_ACCELERATORS) < 0) {
  488.             fclose(fp);
  489.             return e_undefinedfilename;
  490.         }
  491.     }
  492.  
  493.     /* metrics */
  494.  
  495.     if(!pcfSeekToType(fp, tf->tables, tf->ntables,
  496.               PCF_METRICS, &format, &size)) {
  497.         fclose(fp);
  498.         return e_undefinedfilename;
  499.     }
  500.     format = pcfGetLSB32(fp);
  501.     if(!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
  502.        !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
  503.         fclose(fp);
  504.         return e_undefinedfilename;
  505.     }
  506.     if(PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
  507.         nmetrics = pcfGetINT32(fp, format);
  508.     else
  509.         nmetrics = pcfGetINT16(fp, format);
  510.     if((tf->pCI = (CharInfoPtr)malloc(nmetrics * sizeof(CharInfoRec))) == 0) {
  511.         fclose(fp);
  512.         return e_undefinedfilename;
  513.     }
  514.     for(i=0; i<nmetrics; i++) {
  515.         if(PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
  516.             pcfGetMetric(fp, format, &tf->pCI[i].metrics);
  517.         else
  518.             pcfGetCompressedMetric(fp, format, &tf->pCI[i].metrics);
  519.     }
  520.     
  521.     /* encoding */
  522.  
  523.     if(pcfSeekToType(fp, tf->tables, tf->ntables, 
  524.              PCF_BDF_ENCODINGS, &format, &size) < 0) {
  525.         fclose(fp);
  526.         return e_undefinedfilename;
  527.     }
  528.  
  529.     format = pcfGetLSB32(fp);
  530.     if(!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
  531.         fclose(fp);
  532.         return e_undefinedfilename;
  533.     }
  534.  
  535.     tf->pFI->firstCol = pcfGetINT16(fp, format);
  536.     tf->pFI->lastCol = pcfGetINT16(fp, format);
  537.     tf->pFI->firstRow = pcfGetINT16(fp, format);
  538.     tf->pFI->lastRow = pcfGetINT16(fp, format);
  539.     tf->pFI->defaultCh = pcfGetINT16(fp, format);
  540.  
  541.     nencoding = (tf->pFI->lastCol - tf->pFI->firstCol + 1) *
  542.         (tf->pFI->lastRow - tf->pFI->firstRow + 1);
  543.  
  544.     if((tf->encoding = (CharInfoPtr *)
  545.     calloc(nencoding, sizeof(CharInfoPtr))) == 0) {
  546.         fclose(fp);
  547.         return e_VMerror;
  548.     }
  549.  
  550.     tf->pFI->allExist = TRUE;
  551.     for(i=0; i<nencoding; i++) {
  552.         if((offset = pcfGetINT16(fp, format)) == 0xFFFF) {
  553.             tf->pFI->allExist = FALSE;
  554.             tf->encoding[i] = 0;
  555.         }
  556.         else
  557.             tf->encoding[i] = tf->pCI + offset;
  558.     }
  559.  
  560.     /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
  561.  
  562.     if(hasBDFAccelerators) {
  563.         if(pcfGetAccel(tf->pFI, fp, tf->tables, tf->ntables, 
  564.                PCF_BDF_ACCELERATORS) < 0) {
  565.             fclose(fp);
  566.             return e_undefinedfilename;
  567.         }
  568.     }
  569.  
  570.     /* bitmaps */
  571.  
  572.     if(!pcfSeekToType(fp, tf->tables, tf->ntables, 
  573.               PCF_BITMAPS, &format, &size) < 0) {
  574.         fclose(fp);
  575.         return e_undefinedfilename;
  576.     }
  577.     format = tf->bitmap_format = pcfGetLSB32(fp);
  578.     if(!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
  579.         fclose(fp);
  580.         return e_undefinedfilename;
  581.     }
  582.  
  583.     nbitmaps = pcfGetINT32(fp, format);
  584.     if(nbitmaps != nmetrics) {
  585.         fclose(fp);
  586.         return e_undefinedfilename;
  587.     }
  588.  
  589.     for(i=0; i<nbitmaps; i++)
  590.         tf->pCI[i].bits = (char *)pcfGetINT32(fp, format);
  591.         
  592.     for(i=0; i<GLYPHPADOPTIONS; i++)
  593.         bitmapSizes[i] = pcfGetINT32(fp, format);
  594.     sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)];
  595.  
  596.     offset = ftell(fp);
  597.     for(i=0; i<nbitmaps; i++)
  598.         tf->pCI[i].bits += offset;
  599.  
  600.     /* Retrieve properties */
  601.  
  602.     tf->pixel_size = tf->pFI->fontAscent + tf->pFI->fontDescent;
  603.  
  604.     for(i = 0; i< tf->pFI->nprops; i++) {
  605.  
  606.         FontPropPtr pFP = tf->pFI->props;
  607.         char *prop_name  = tf->strings + pFP[i].name;
  608.         int   prop_value = pFP[i].value;
  609.  
  610.         if(strcmp(prop_name, "PIXEL_SIZE") == 0)
  611.             tf->pixel_size = prop_value;
  612.     }
  613.  
  614.     if(tf->pixel_size == 0)
  615.         return e_undefinedfilename;
  616.  
  617.     /**********************************************
  618.      * NOTICE: BDF style accelerators are ignored *
  619.      **********************************************/
  620.  
  621.     *pfp = fp;
  622.     *ptf = tf;
  623.     return 0;
  624. }
  625.  
  626. private int
  627. code2num(TempFont *tf, unsigned int code)
  628. {
  629.     int row, col, ncols;
  630.     FontInfoPtr pFI = tf->pFI;
  631.  
  632.     if((row = (code >> 8)) < pFI->firstRow ||
  633.        row > pFI->lastRow)
  634.         return -1;
  635.     if((col = (code & 0x00ff)) < pFI->firstCol ||
  636.        col > pFI->lastCol)
  637.         return -1;
  638.     ncols = pFI->lastCol - pFI->firstCol + 1;
  639.     return (row - pFI->firstRow) * ncols + col - pFI->firstCol;
  640. }
  641.  
  642. private int
  643. GetPCFBitmap(FILE *fp, TempFont *tf, unsigned int char_code, 
  644.          int *width, int *height, byte *bmap, int length, 
  645.          int *pixel_size, int *font_ascent, int *font_descent,
  646.          int *wx, int *wy, int *llx, int *lly, int *urx, int *ury)
  647. {
  648.     int ht, wd, gbp, wid, bytes, glyphbytes;
  649.     int i, j, count;
  650.     unsigned char *bitmap, *ptr;
  651.     int charnum;
  652.     CharInfoPtr pCI;
  653.  
  654.     if((charnum = code2num(tf, char_code)) == -1) {
  655.         if((charnum = code2num(tf, tf->pFI->defaultCh)) == -1)
  656.             return e_rangecheck;
  657.     }
  658.     else {
  659.         if(tf->encoding[charnum] == 0 || 
  660.            ReallyNonExistent(tf->encoding[charnum])) {
  661.             if((charnum = code2num(tf, tf->pFI->defaultCh)) == -1)
  662.                 return e_rangecheck;
  663.         }
  664.     }
  665.  
  666.     if((pCI = tf->encoding[charnum]) == 0) {
  667.         /* If the CharInfo does not exist, return blank character. */
  668.         *pixel_size = tf->pixel_size;
  669.         *font_ascent = tf->pFI->fontAscent;
  670.         *font_descent = tf->pFI->fontDescent;
  671.            *width = 0;
  672.         *height = 0;
  673.         length = 0;
  674.         *wx = tf->pFI->maxbounds.characterWidth;
  675.         *wy = 0;
  676.         *llx = tf->pFI->maxbounds.leftSideBearing;
  677.         *lly = - tf->pFI->maxbounds.descent;
  678.         *urx = tf->pFI->maxbounds.rightSideBearing;
  679.         *ury = tf->pFI->maxbounds.ascent;
  680.         return 0;
  681.     }
  682.  
  683.     ht = pCI->metrics.descent + pCI->metrics.ascent;
  684.     wd = pCI->metrics.rightSideBearing - pCI->metrics.leftSideBearing;
  685.     gbp = BYTES_PER_ROW(wd, PCF_GLYPH_PAD(tf->bitmap_format));
  686.     wid = ((wd / 8) + ((wd % 8) ? 1 : 0));
  687.     bytes = ht * wid;
  688.     glyphbytes = gbp * ht;
  689.  
  690.     if(bytes > length)
  691.         return e_rangecheck;
  692.  
  693.     /* Read Glyph */
  694.     
  695.     if((bitmap = ptr = (unsigned char *)
  696.         gs_malloc(glyphbytes, 1, "GetPCFBitmap(bitmap)")) == 0)
  697.         return e_VMerror;
  698.  
  699.     if(fseek(fp, (long)pCI->bits, 0) < 0)
  700.         return e_ioerror;
  701.  
  702.     if(fread(bitmap, 1, glyphbytes, fp) != glyphbytes)
  703.         return e_ioerror;
  704.  
  705.     if (PCF_BIT_ORDER(tf->bitmap_format) != MSBFirst)
  706.         BitOrderInvert(ptr, glyphbytes);
  707.     if (PCF_BYTE_ORDER(tf->bitmap_format) !=
  708.         PCF_BIT_ORDER(tf->bitmap_format)) {
  709.         switch(PCF_SCAN_UNIT(tf->bitmap_format)) {
  710.         case 2:
  711.             TwoByteSwap(ptr, glyphbytes);
  712.             break;
  713.         case 4:
  714.             FourByteSwap(ptr, glyphbytes);
  715.             break;
  716.         }
  717.     }
  718.         
  719.     count = 0;
  720.     for (i = 0; i < ht; i++) {
  721.         for (j = 0; j < wid; j++)
  722.             bmap[count++] = *ptr++;
  723.         ptr += (gbp - wid);
  724.     }
  725.  
  726.     gs_free((char *)bitmap, glyphbytes, 1, "GetPCFBitmap(bitmap)");
  727.  
  728.     /* Set Metrics Information */
  729.     
  730.     *pixel_size = tf->pixel_size;
  731.     *font_ascent = tf->pFI->fontAscent;
  732.     *font_descent = tf->pFI->fontDescent;
  733.     *width = wd;
  734.     *height = ht;
  735.     *wx = pCI->metrics.characterWidth;
  736.     *wy = 0;
  737.     *llx = pCI->metrics.leftSideBearing;
  738.     *lly = - pCI->metrics.descent;
  739.     *urx = pCI->metrics.rightSideBearing;
  740.     *ury = pCI->metrics.ascent;
  741.     return 0;
  742. }
  743.  
  744. /*--------------------------- end of pcfread --------------------------*/
  745.  
  746. /*
  747.  * Hash Index Routines
  748.  */
  749.  
  750. typedef struct index_item_s {
  751.     struct index_item_s *next;
  752.     char *str;
  753.     FILE *fp;
  754.     TempFont *tf;
  755. } index_item;
  756. private index_item *hash_index[256];
  757.  
  758. /* Hash function */
  759. private int
  760. hash(unsigned char *str)
  761. {
  762.         unsigned char hash;
  763.         for(hash = 0; *str != 0; str++)
  764.                 hash ^= *str;
  765.         return hash;
  766. }
  767.  
  768. /* store */
  769. private int
  770. store(char *str, FILE *fp, TempFont *tf)
  771. {
  772.     int key = hash((unsigned char *)str);
  773.     index_item *item;
  774.     if((item = (index_item *)malloc(sizeof(index_item))) == 0)
  775.         return e_VMerror;
  776.     if((item->str = (char *)malloc(strlen(str) + 1)) == 0)
  777.         return e_VMerror;
  778.     strcpy(item->str, str);
  779.     item->next = hash_index[key];
  780.     item->fp = fp;
  781.     item->tf = tf;
  782.     hash_index[key] = item;
  783.     return 0;
  784. }
  785.  
  786. /* search */
  787. private int
  788. search(char *str, FILE **fp, TempFont **tf)
  789. {
  790.     int key = hash((unsigned char *)str);
  791.     index_item *item;
  792.     item = hash_index[key];
  793.     while(item != 0) {
  794.         if(strcmp(item->str, str) == 0) {
  795.             *fp = item->fp;
  796.             *tf = item->tf;
  797.             return 1;
  798.         }
  799.         item = item->next;
  800.     }
  801.     return 0;
  802. }
  803.  
  804. /*
  805.  * Open PCF Font File
  806.  */
  807.  
  808. private int
  809. OpenPCFFont(char *file, FILE **pfp, TempFont **ptf)
  810. {
  811.     int code;
  812.  
  813.     if(search(file, pfp, ptf))
  814.         return 0;
  815.     else {
  816.         if((code = GetTempFont(file, pfp, ptf)) < 0)
  817.             return code;
  818.         if((code = store(file, *pfp, *ptf)) < 0)
  819.             return code;
  820.         return 0;
  821.     }
  822. }
  823.  
  824. /*
  825.  * Kanji Code Conversion
  826.  */
  827.  
  828. private unsigned int
  829. jis2euc(unsigned int jis_code)
  830. {
  831.     return jis_code | 0x8080;
  832. }
  833.  
  834. private unsigned int
  835. jis2sjis(unsigned int jis_code)
  836. {
  837.     unsigned int j1, j2, s1, s2;
  838.  
  839.     j1 = jis_code >> 8;
  840.     j2 = jis_code & 0xff;
  841.  
  842.     if(j1 < 0x5f)
  843.         s1 = (j1 - 0x21) / 2 + 0x81;
  844.     else
  845.         s1 = (j1 - 0x5f) / 2 + 0xe0;
  846.  
  847.     if(j1 & 1) {
  848.         if(j2 < 0x60)
  849.             s2 = j2 + 0x1f;
  850.         else
  851.             s2 = j2 + 0x20;
  852.     }
  853.     else
  854.         s2 = j2 + 0x7e;
  855.  
  856.     return (s1 << 8 + s2);
  857. }
  858.  
  859. private unsigned int
  860. jis2cc(TempFont *tf, unsigned int jis_code)
  861. {
  862.     int num;
  863.  
  864.     if(((num = code2num(tf, 0x3021)) >= 0) && (tf->encoding[num] != 0)) {
  865.         /* suppose that the encoding is JIS */
  866.         return jis_code;
  867.     }
  868.  
  869.     if(((num = code2num(tf, 0xB0A1)) >= 0) && (tf->encoding[num] != 0)) {
  870.         /* suppose that the encoding is EUC */
  871.         return jis2euc(jis_code);
  872.     }
  873.  
  874.     if(((num = code2num(tf, 0x889F)) >= 0) && (tf->encoding[num] != 0)) {
  875.         /* suppose that the encoding is SJIS */
  876.         return jis2sjis(jis_code);
  877.     }
  878.  
  879.     return jis_code;
  880. }
  881.  
  882. /*
  883.  * Retrieve Font Image
  884.  */
  885.  
  886. private int
  887. pcfimage(char *file, int jis_code, 
  888.      int *width, int *height, byte *bitmap, int length,
  889.      gs_matrix *pmat, floatp *wx, floatp *wy)
  890. {
  891.     int code, pixel_size, font_ascent, font_descent;
  892.     int w_x, w_y, ll_x, ll_y, ur_x, ur_y;
  893.     unsigned int char_code;
  894.     floatp dx, dy, scale;
  895.     gs_matrix smat, tmat;
  896.     FILE *fp;
  897.     TempFont *tf;
  898.  
  899.     if((code = OpenPCFFont(file, &fp, &tf)) < 0)
  900.         return code;
  901.  
  902.     char_code = jis2cc(tf, jis_code);
  903.  
  904.     if((code = GetPCFBitmap(fp, tf, char_code,
  905.                 width, height, bitmap, length,
  906.                 &pixel_size, &font_ascent, &font_descent,
  907.                 &w_x, &w_y, &ll_x, &ll_y, &ur_x, &ur_y)) < 0)
  908.         return code;
  909.  
  910.     /* Transform Image */
  911.  
  912.     gs_make_identity(pmat);
  913.  
  914.     scale = (floatp)B_Y_CL * 2.0 / (floatp)font_ascent;
  915.     gs_make_scaling(1.0 / scale, -1.0 / scale, &smat);
  916.  
  917.     dx = (floatp)pixel_size / 2.0 - (floatp)B_X_CL / scale;
  918.     dy = (floatp)font_ascent;
  919.     gs_make_translation(dx, dy, &tmat);
  920.  
  921.     gs_matrix_multiply(pmat, &smat, pmat);
  922.     gs_matrix_multiply(pmat, &tmat, pmat);
  923.  
  924.     *wx = (floatp)B_X_CL * 2.0;
  925.     *wy = 0;
  926.  
  927.     return 0;
  928. }
  929.