Main Page   Modules   Alphabetical List   Compound List   File List   Compound Members   File Members  

t1mac.c

00001 /*  $Id: t1mac.c,v 1.3 2000/11/30 02:25:10 dbryson Exp $ */
00002 
00003 /*
00004 **  Description:
00005 **  
00006 **    This file is part of libps
00007 **
00008 **
00009 **  Contact:
00010 **
00011 **      Mail:
00012 **
00013 **        Technology Associates, Inc.
00014 **        LIBPS Project
00015 **        1455 Deming Way #11
00016 **        Sparks, NV  89431
00017 **        USA
00018 **
00019 **      Email:
00020 **
00021 **        libps@techass.com
00022 **
00023 **      See our website at:
00024 **
00025 **        libps.sourceforge.net
00026 **
00027 */
00028 
00029 /* t1mac
00030  *
00031  * This program converts Type 1 fonts in PFA or PFB format into Macintosh Type
00032  * 1 fonts stored in MacBinary (I or II), AppleSingle, AppleDouble, BinHex, or
00033  * raw resource fork format.
00034  *
00035  * Copyright (c) 2000 by Eddie Kohler, all rights reserved.
00036  *
00037  * Permission is hereby granted to use, modify, and distribute this program
00038  * for any purpose provided this copyright notice and the one below remain
00039  * intact. */
00040 
00041 /* Note: this is ANSI C. */
00042 
00043 #ifdef HAVE_CONFIG_H
00044 # include <config.h>
00045 #endif
00046 #if defined(_MSDOS) || defined(_WIN32)
00047 # include <fcntl.h>
00048 # include <io.h>
00049 #endif
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052 #include <string.h>
00053 #include <ctype.h>
00054 #include <limits.h>
00055 #include <stdarg.h>
00056 #include <errno.h>
00057 #include <time.h>
00058 #include "clp.h"
00059 #include "t1lib.h"
00060 
00061 /* int32 must be at least 32-bit */
00062 #if INT_MAX >= 0x7FFFFFFFUL
00063 typedef int int32;
00064 typedef unsigned int uint32;
00065 #else
00066 typedef long int32;
00067 typedef unsigned long uint32;
00068 #endif
00069 
00070 typedef unsigned char byte;
00071 
00072 void fatal_error(const char *message, ...);
00073 void error(const char *message, ...);
00074 
00075 /* resource fork layout */
00076 #define RFORK_HEADERLEN 256
00077 #define RFORK_MAP_RESERVEDLEN 22
00078 #define RFORK_MAP_HEADERLEN 28
00079 #define RFORK_RTYPE_LEN 8
00080 #define RFORK_RSRC_LEN 12
00081 
00082 /* Macintosh times are # seconds since 1/1/1904, not 1/1/1970 */
00083 #define MAC_TIME_DELTA 2082844800
00084 
00085 /* POST resource information */
00086 #define POST_ASCII 1
00087 #define POST_BINARY 2
00088 #define POST_END 5
00089 
00090 /* Adobe font file information */
00091 #define T1_FILETYPE 0x4C57464E  /* LWFN */
00092 #define T1_FILECREATOR 0x54315554 /* T1UT */
00093 #define T1_FINDERFLAGS 33       /* Bundle + Inited */
00094 
00095 #define MAX_RSRC_LEN 2048
00096 static byte buf[MAX_RSRC_LEN];
00097 static int bufpos;
00098 static int blocktyp;
00099 
00100 static char *font_name;
00101 
00102 /* information about the resources being built */
00103 typedef struct Rsrc {
00104   int32 type;
00105   int id;
00106   int attrs;
00107   int data_offset;
00108   uint32 data_len;
00109   int next_in_type;
00110   int next_type;
00111 } Rsrc;
00112 static Rsrc *rsrc = 0;
00113 static int nrsrc = 0;
00114 static int rsrc_cap = 0;
00115 static int cur_post_id = 0;
00116 
00117 /* output resource fork */
00118 static FILE *rfork_f = 0;
00119 
00120 /* ICN# data */
00121 static const unsigned char icon_bw_data[] = {
00122 0,0,0,0,255,255,255,255,128,0,0,1,128,0,0,1,128,0,0,1,
00123 128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,1,128,0,0,33,
00124 128,0,0,97,128,0,0,225,128,0,1,225,128,0,3,225,128,0,7,225,
00125 128,0,15,225,128,0,31,225,128,0,55,225,159,128,103,249,144,128,199,9,
00126 240,129,135,15,0,131,7,0,0,134,7,0,15,140,7,240,8,31,255,240,
00127 8,63,255,240,8,96,7,240,8,192,7,240,9,192,15,240,11,224,31,240,
00128 15,240,63,240,15,255,255,240,0,0,0,0,255,255,255,255,255,255,255,255,
00129 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
00130 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
00131 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
00132 255,255,255,255,240,255,255,15,240,255,255,15,0,255,255,0,0,255,255,0,
00133 15,255,255,240,15,255,255,240,15,255,255,240,15,255,255,240,15,255,255,240,
00134 15,255,255,240,15,255,255,240,15,255,255,240,15,255,255,240,};
00135 
00136 static const unsigned char small_icon_bw_data[] = {
00137 255,255,128,1,128,1,128,1,128,5,128,13,128,29,128,61,128,125,184,253,
00138 201,179,59,60,39,252,44,60,60,124,63,252,255,255,255,255,255,255,255,255,
00139 255,255,255,255,255,255,255,255,255,255,255,255,207,243,63,252,63,252,63,252,
00140 63,252,63,252,};
00141 
00142 static const unsigned char icon_8_data[] = {
00143 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00144 0,0,0,0,0,0,0,0,0,0,0,0,92,92,92,92,92,92,92,92,
00145 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00146 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00147 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,105,92,92,92,92,
00148 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00149 92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,
00150 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,105,
00151 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00152 92,92,92,92,92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92,
00153 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00154 92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00155 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,105,92,92,92,92,
00156 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00157 92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,
00158 92,92,92,92,92,92,92,92,92,92,92,92,92,92,5,92,92,92,92,105,
00159 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00160 92,92,92,92,92,5,5,92,92,92,92,105,92,92,92,92,92,92,92,92,
00161 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,5,5,5,92,
00162 92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00163 92,92,92,92,92,92,92,5,5,5,5,92,92,92,92,105,92,92,92,92,
00164 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,5,5,
00165 5,5,5,92,92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,
00166 92,92,92,92,92,92,92,92,92,5,5,5,5,5,5,92,92,92,92,105,
00167 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00168 5,5,5,5,5,5,5,92,92,92,92,105,92,92,92,92,92,92,92,92,
00169 92,92,92,92,92,92,92,92,92,92,92,5,5,5,5,5,5,5,5,92,
00170 92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00171 92,92,5,5,92,5,5,5,5,5,5,92,92,92,92,105,92,92,92,105,
00172 105,105,105,105,92,92,92,92,92,92,92,92,92,5,5,92,92,5,5,105,
00173 105,105,105,105,92,92,92,105,92,92,92,105,0,0,0,0,92,92,92,92,
00174 92,92,92,92,5,5,92,92,92,5,5,105,0,0,0,0,92,92,92,105,
00175 105,105,105,105,0,0,0,0,92,92,92,92,92,92,92,5,5,92,92,92,
00176 92,5,5,105,0,0,0,0,105,105,105,105,0,0,0,0,0,0,0,0,
00177 92,92,92,92,92,92,5,5,92,92,92,92,92,5,5,105,0,0,0,0,
00178 0,0,0,0,0,0,0,0,0,0,0,0,92,92,92,92,92,5,5,92,
00179 92,92,92,92,92,5,5,105,0,0,0,0,0,0,0,0,0,0,0,0,
00180 92,92,92,92,92,92,92,92,5,5,92,92,92,92,92,92,92,5,5,5,
00181 5,5,5,92,0,0,0,0,0,0,0,0,92,92,92,92,92,92,92,5,
00182 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,105,0,0,0,0,
00183 0,0,0,0,92,92,92,92,92,92,5,5,5,5,5,5,5,5,5,5,
00184 5,5,5,5,5,5,5,105,0,0,0,0,0,0,0,0,92,92,92,92,
00185 92,5,5,92,92,92,92,92,92,92,92,92,92,5,5,5,5,5,5,105,
00186 0,0,0,0,0,0,0,0,92,92,92,92,5,5,92,92,92,92,92,92,
00187 92,92,92,92,92,5,5,5,5,5,5,105,0,0,0,0,0,0,0,0,
00188 92,92,92,5,5,5,92,92,92,92,92,92,92,92,92,92,5,5,5,5,
00189 5,5,5,105,0,0,0,0,0,0,0,0,92,92,5,5,5,5,5,92,
00190 92,92,92,92,92,92,92,5,5,5,5,5,5,5,5,105,0,0,0,0,
00191 0,0,0,0,92,5,5,5,5,5,5,5,92,92,92,92,92,92,5,5,
00192 5,5,5,5,5,5,5,105,0,0,0,0,0,0,0,0,92,105,105,105,
00193 105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
00194 0,0,0,0,};
00195 
00196 static const unsigned char small_icon_8_data[] = {
00197 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
00198 92,92,92,92,92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92,
00199 92,92,92,92,92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,
00200 92,92,92,105,92,92,92,92,92,92,92,92,92,92,92,92,92,5,92,105,
00201 92,92,92,92,92,92,92,92,92,92,92,92,5,5,92,105,92,92,92,92,
00202 92,92,92,92,92,92,92,5,5,5,92,105,92,92,92,92,92,92,92,92,
00203 92,92,5,5,5,5,92,105,92,92,92,92,92,92,92,92,92,5,92,5,
00204 5,5,92,105,92,105,105,105,92,92,92,92,5,92,92,5,105,105,92,105,
00205 92,105,0,0,92,92,92,5,92,92,92,5,0,0,105,105,0,0,92,92,
00206 92,92,5,92,92,92,92,5,5,5,0,0,0,0,92,92,92,5,5,5,
00207 5,5,5,5,5,5,0,0,0,0,92,92,5,92,92,92,92,92,92,5,
00208 5,5,0,0,0,0,92,5,5,92,92,92,92,92,5,5,5,5,0,0,
00209 0,0,5,5,5,5,105,105,105,5,5,5,5,5,0,0,};
00210 
00211 static const unsigned char icon_4_data[] = {
00212 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,69,69,69,
00213 69,69,69,69,69,69,69,69,69,69,69,69,84,84,84,84,84,84,84,84,
00214 84,84,84,84,84,84,84,85,69,69,69,69,69,69,69,69,69,69,69,69,
00215 69,69,69,69,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,85,
00216 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,84,84,84,84,
00217 84,84,84,84,84,84,84,84,84,84,84,85,69,69,69,69,69,69,69,69,
00218 69,69,69,69,69,69,69,69,84,84,84,84,84,84,84,84,84,84,84,84,
00219 84,84,84,85,69,69,69,69,69,69,69,69,69,69,69,69,69,21,69,69,
00220 84,84,84,84,84,84,84,84,84,84,84,84,81,20,84,85,69,69,69,69,
00221 69,69,69,69,69,69,69,69,17,21,69,69,84,84,84,84,84,84,84,84,
00222 84,84,84,81,17,20,84,85,69,69,69,69,69,69,69,69,69,69,69,17,
00223 17,21,69,69,84,84,84,84,84,84,84,84,84,84,81,17,17,20,84,85,
00224 69,69,69,69,69,69,69,69,69,69,17,17,17,21,69,69,84,84,84,84,
00225 84,84,84,84,84,81,17,17,17,20,84,85,69,69,69,69,69,69,69,69,
00226 69,17,65,17,17,21,69,69,84,85,85,85,84,84,84,84,81,20,81,21,
00227 85,85,84,85,69,69,0,0,69,69,69,69,17,69,65,21,0,0,69,69,
00228 85,85,0,0,84,84,84,81,20,84,81,21,0,0,85,85,0,0,0,0,
00229 69,69,69,17,69,69,65,21,0,0,0,0,0,0,0,0,84,84,81,20,
00230 84,84,81,21,0,0,0,0,0,0,69,69,69,69,17,69,69,69,65,17,
00231 17,30,0,0,0,0,84,84,84,81,17,17,17,17,17,17,17,21,0,0,
00232 0,0,69,69,69,17,17,17,17,17,17,17,17,21,0,0,0,0,84,84,
00233 81,20,84,84,84,84,81,17,17,21,0,0,0,0,69,69,17,69,69,69,
00234 69,69,65,17,17,21,0,0,0,0,84,81,17,84,84,84,84,84,17,17,
00235 17,21,0,0,0,0,69,17,17,21,69,69,69,65,17,17,17,21,0,0,
00236 0,0,81,17,17,17,84,84,84,17,17,17,17,21,0,0,0,0,229,85,
00237 85,85,85,85,85,85,85,85,85,85,0,0,};
00238 
00239 static const unsigned char small_icon_4_data[] = {
00240 84,84,84,84,84,84,84,85,69,69,69,69,69,69,69,69,84,84,84,84,
00241 84,84,84,85,69,69,69,69,69,69,69,69,84,84,84,84,84,84,81,85,
00242 69,69,69,69,69,69,17,69,84,84,84,84,84,81,17,85,69,69,69,69,
00243 69,17,17,69,84,84,84,84,81,81,17,85,69,85,69,69,21,65,85,69,
00244 85,0,84,81,84,81,0,85,0,69,69,21,69,65,17,0,0,84,81,17,
00245 17,17,17,0,0,69,21,69,69,65,17,0,0,81,20,84,84,17,17,0,
00246 0,17,17,85,81,17,17,0,};
00247 
00248 
00249 /* fseek with fatal_error */
00250 
00251 static void
00252 reposition(FILE *fi, int32 absolute)
00253 {
00254   if (fseek(fi, absolute, 0) == -1)
00255     fatal_error("can't seek to position %d", absolute);
00256 }
00257 
00258 /* Some functions to write one, two, three, and four byte integers in 68000
00259    byte order (most significant byte first). */
00260 
00261 static void
00262 write_one(int c, FILE *f)
00263 {
00264   putc(c, f);
00265 }
00266 
00267 static void
00268 write_two(int c, FILE *f)
00269 {
00270   putc((c >> 8) & 255, f);
00271   putc(c & 255, f);
00272 }
00273 
00274 static void
00275 write_three(int32 c, FILE *f)
00276 {
00277   putc((c >> 16) & 255, f);
00278   putc((c >> 8) & 255, f);
00279   putc(c & 255, f);
00280 }
00281 
00282 static void
00283 write_four(int32 c, FILE *f)
00284 {
00285   putc((c >> 24) & 255, f);
00286   putc((c >> 16) & 255, f);
00287   putc((c >> 8) & 255, f);
00288   putc(c & 255, f);
00289 }
00290 
00291 /* Some functions to store one, two, three, and four byte integers in 68000
00292    byte order (most significant byte first). */
00293 
00294 static void
00295 store_one(int c, char *s)
00296 {
00297   s[0] = (char)(c & 255);
00298 }
00299 
00300 static void
00301 store_two(int c, char *s)
00302 {
00303   s[0] = (char)((c >> 8) & 255);
00304   s[1] = (char)(c & 255);
00305 }
00306 
00307 static void
00308 store_four(int32 c, char *s)
00309 {
00310   s[0] = (char)((c >> 24) & 255);
00311   s[1] = (char)((c >> 16) & 255);
00312   s[2] = (char)((c >> 8) & 255);
00313   s[3] = (char)(c & 255);
00314 }
00315 
00316 static void
00317 output_new_rsrc(const char *rtype, int rid, int attrs,
00318                 const char *data, uint32 len)
00319 {
00320   Rsrc *r;
00321   if (nrsrc >= rsrc_cap) {
00322     rsrc_cap = (rsrc_cap ? rsrc_cap * 2 : 256);
00323     r = (Rsrc *)malloc(sizeof(Rsrc) * rsrc_cap);
00324     if (!r)
00325       fatal_error("out of memory");
00326     memcpy(r, rsrc, sizeof(Rsrc) * nrsrc);
00327     free(rsrc);
00328     rsrc = r;
00329   }
00330   r = &rsrc[nrsrc];
00331   nrsrc++;
00332 
00333   /* prepare resource record */
00334   {
00335     const unsigned char *b = (const unsigned char *)rtype;
00336     r->type = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
00337   }
00338   r->id = rid;
00339   r->attrs = attrs;
00340   if (nrsrc == 1)
00341     r->data_offset = 0;
00342   else
00343     r->data_offset = rsrc[nrsrc-2].data_offset + rsrc[nrsrc-2].data_len + 4;
00344   r->data_len = len;
00345   r->next_in_type = r->next_type = -2;
00346   
00347   /* resource consists of length, then data */
00348   write_four(r->data_len, rfork_f);
00349   fwrite(data, 1, len, rfork_f);
00350 }
00351 
00352 static void
00353 init_current_post(void)
00354 {
00355   bufpos = 2;
00356   cur_post_id = 501;
00357   blocktyp = POST_ASCII;
00358 }
00359 
00360 static void
00361 output_current_post(void)
00362 {
00363   if (blocktyp != POST_END && bufpos <= 2)
00364     return;
00365   buf[0] = blocktyp;
00366   buf[1] = 0;
00367   output_new_rsrc("POST", cur_post_id, 0, (char *)buf, bufpos);
00368   bufpos = 2;
00369   cur_post_id++;
00370 }
00371 
00372 /* font_reader functions */
00373 
00374 static void
00375 t1mac_output_data(byte *s, int len)
00376 {
00377   while (len > 0) {
00378     int n;
00379     /* In some Mac fonts, the ASCII sections terminate with a line-end */
00380     if (bufpos >= MAX_RSRC_LEN
00381         || (blocktyp == POST_ASCII && len + bufpos > MAX_RSRC_LEN && bufpos))
00382       output_current_post();
00383     n = (len + bufpos <= MAX_RSRC_LEN ? len : MAX_RSRC_LEN - bufpos);
00384     memcpy(buf + bufpos, s, n);
00385     bufpos += n;
00386     s += n;
00387     len -= n;
00388   }
00389 }
00390 
00391 static void
00392 t1mac_output_ascii(char *s)
00393 {
00394   int l = strlen(s);
00395   if (blocktyp == POST_BINARY) {
00396     output_current_post();
00397     blocktyp = POST_ASCII;
00398   }
00399   /* Mac line endings */
00400   if (l > 0 && s[l-1] == '\n')
00401     s[l-1] = '\r';
00402   t1mac_output_data((byte *)s, l);
00403   if (strncmp(s, "/FontName", 9) == 0) {
00404     for (s += 9; isspace(*s); s++) ;
00405     if (*s == '/') {
00406       const char *t = ++s;
00407       while (*t && !isspace(*t)) t++;
00408       free(font_name);
00409       font_name = malloc(t - s + 1);
00410       memcpy(font_name, s, t - s);
00411       font_name[t - s] = 0;
00412     }
00413   }
00414 }
00415 
00416 static void
00417 t1mac_output_binary(unsigned char *s, int len)
00418 {
00419   if (blocktyp == POST_ASCII) {
00420     output_current_post();
00421     blocktyp = POST_BINARY;
00422   }
00423   t1mac_output_data(s, len);
00424 }
00425 
00426 static void
00427 t1mac_output_end(void)
00428 {
00429   output_current_post();
00430   blocktyp = POST_END;
00431   output_current_post();
00432 }
00433 
00434 
00435 /* finish off the resource fork */
00436 
00437 static uint32
00438 complete_rfork(void)
00439 {
00440   uint32 reflist_offset, total_data_len;
00441   uint32 typelist_len;
00442   int i, j, ntypes;
00443 
00444   /* analyze resources */
00445   {
00446     int last_type = -1;
00447     ntypes = 0;
00448     for (i = 0; i < nrsrc; i++)
00449       if (rsrc[i].next_in_type == -2) {
00450         int last = -1;
00451         if (last_type >= 0)
00452           rsrc[last_type].next_type = i;
00453         for (j = i; j < nrsrc; j++)
00454           if (rsrc[j].type == rsrc[i].type) {
00455             if (last >= 0)
00456               rsrc[last].next_in_type = j;
00457             last = j;
00458           }
00459         rsrc[last].next_in_type = -1;
00460         last_type = i;
00461         ntypes++;
00462       }
00463   }
00464 
00465   /* have just finished writing data */
00466   /* now write resource map */
00467   for (i = 0; i < RFORK_MAP_RESERVEDLEN; i++)
00468     putc(0, rfork_f);           /* reserved */
00469   write_two(0, rfork_f);        /* resource fork attributes */
00470   typelist_len = ntypes * RFORK_RTYPE_LEN + 2;
00471   write_two(RFORK_MAP_HEADERLEN, rfork_f); /* offset from start of map to typelist */
00472   write_two(RFORK_MAP_HEADERLEN + typelist_len + nrsrc * RFORK_RSRC_LEN, rfork_f); /* offset from start of map to namelist */
00473 
00474   /* output type map */
00475   write_two(ntypes - 1, rfork_f);/* number of types - 1 */
00476   reflist_offset = typelist_len;
00477   for (i = 0; i >= 0; i = rsrc[i].next_type) {
00478     int n_in_type = 0;
00479     for (j = i; j >= 0; j = rsrc[j].next_in_type)
00480       n_in_type++;
00481     write_four(rsrc[i].type, rfork_f);  /* resource type */
00482     write_two(n_in_type - 1, rfork_f);  /* number in type - 1 */
00483     write_two(reflist_offset, rfork_f); /* offset to reflist from start of typelist */
00484     reflist_offset += n_in_type * RFORK_RSRC_LEN;
00485   }
00486 
00487   /* output reference list */
00488   for (i = 0; i >= 0; i = rsrc[i].next_type)
00489     for (j = i; j >= 0; j = rsrc[j].next_in_type) {
00490       write_two(rsrc[j].id, rfork_f);   /* ID */
00491       write_two(-1, rfork_f);           /* offset to name */
00492       write_one(rsrc[j].attrs, rfork_f); /* attributes */
00493       write_three(rsrc[j].data_offset, rfork_f); /* offset to data from start of data */
00494       write_four(0, rfork_f);           /* reserved */
00495     }
00496 
00497   /* finally, patch up resource fork header */
00498   {
00499     total_data_len = rsrc[nrsrc-1].data_offset + rsrc[nrsrc-1].data_len + 4;
00500     reposition(rfork_f, 0);
00501     write_four(RFORK_HEADERLEN, rfork_f); /* offset from rfork to data */
00502     write_four(RFORK_HEADERLEN + total_data_len, rfork_f); /* offset from rfork to map */
00503     write_four(total_data_len, rfork_f); /* length of data */
00504     write_four(RFORK_MAP_HEADERLEN + reflist_offset, rfork_f); /* length of map */
00505   }
00506 
00507   return RFORK_HEADERLEN + total_data_len + RFORK_MAP_HEADERLEN + reflist_offset;
00508 }
00509 
00510 
00511 /* write a MacBinary II file */
00512 
00513 static void
00514 output_raw(FILE *rf, int32 len, FILE *f)
00515 {
00516   char buf[2048];
00517   reposition(rf, 0);
00518   while (len > 0) {
00519     int n = (len < 2048 ? len : 2048);
00520     fread(buf, 1, n, rf);
00521     fwrite(buf, 1, n, f);
00522     len -= n;
00523   }
00524 }
00525 
00526 static void
00527 output_macbinary(FILE *rf, int32 rf_len, const char *filename, FILE *f)
00528 {
00529   int i, len = strlen(filename);
00530   char buf[128];
00531   if (len < 1 || len > 63)
00532     fatal_error("filename length must be between 1 and 63");
00533   store_one(0, buf+0);          /* old version number */
00534   store_one(len, buf+1);        /* filename length */
00535   memset(buf+2, 0, 63);         /* filename padding */
00536   memcpy(buf+2, filename, len); /* filename */
00537   store_four(T1_FILETYPE, buf+65); /* file type */
00538   store_four(T1_FILECREATOR, buf+69); /* file creator */
00539   store_one(T1_FINDERFLAGS, buf+73); /* finder flags */
00540   store_one(0, buf+74);         /* zero byte */
00541   store_two(0, buf+75);         /* vertical position in window */
00542   store_two(0, buf+77);         /* horizontal position in window */
00543   store_two(0, buf+79);         /* window or folder ID */
00544   store_one(0, buf+81);         /* protected flag */
00545   store_one(0, buf+82);         /* zero byte */
00546   store_four(0, buf+83);        /* data fork length */
00547   store_four(rf_len, buf+87);   /* resource fork length */
00548   {
00549     time_t t = time(0) + MAC_TIME_DELTA;
00550     store_four(t, buf+91);      /* creation date */
00551     store_four(t, buf+95);      /* modification date */
00552   }
00553   store_two(0, buf+99);         /* GetInfo comment length */
00554   store_one(0, buf+101);        /* finder flags part 2 */
00555   memset(buf+102, 0, 116 - 102); /* padding */
00556   store_four(0, buf+116);       /* total length when unpacked */
00557   store_two(0, buf+120);        /* length of secondary header */
00558   store_one(129, buf+122);      /* version number */
00559   store_one(129, buf+123);      /* minimum acceptable version number */
00560   store_two(crcbuf(0, 124, buf), buf+124); /* CRC */
00561   store_two(0, buf+126);        /* padding to 128 bytes */
00562 
00563   /* write out the header */
00564   fwrite(buf, 1, 128, f);
00565 
00566   /* now write resource fork */
00567   output_raw(rf, rf_len, f);
00568   for (i = rf_len % 128; i && i < 128; i++)
00569     putc(0, f);
00570 }
00571 
00572 
00573 /* write an AppleSingle file */
00574 
00575 #define APPLESINGLE_MAGIC 0x00051600
00576 #define APPLEDOUBLE_MAGIC 0x00051607
00577 #define APPLESINGLE_VERSION 0x00020000
00578 #define APPLESINGLE_TIME_DELTA 883612800
00579 #define APPLESINGLE_HEADERLEN 26
00580 #define APPLESINGLE_ENTRYLEN 12
00581 #define APPLESINGLE_DFORK_ENTRY 1
00582 #define APPLESINGLE_RFORK_ENTRY 2
00583 #define APPLESINGLE_DATES_ENTRY 8
00584 #define APPLESINGLE_DATES_LEN 16
00585 #define APPLESINGLE_FINDERINFO_ENTRY 9
00586 #define APPLESINGLE_FINDERINFO_LEN 32
00587 #define APPLESINGLE_REALNAME_ENTRY 3
00588 
00589 static void
00590 output_applesingle(FILE *rf, int32 rf_len, const char *filename, FILE *f,
00591                    int appledouble)
00592 {
00593   uint32 offset;
00594   int i, nentries, len = strlen(filename);
00595   if (appledouble)              /* magic number */
00596     write_four(APPLEDOUBLE_MAGIC, f);
00597   else
00598     write_four(APPLESINGLE_MAGIC, f);
00599   write_four(APPLESINGLE_VERSION, f); /* version number */
00600   for (i = 0; i < 4; i++)
00601     write_four(0, f);           /* filler */
00602   nentries = (appledouble ? 4 : 5);
00603   write_two(nentries, f); /* number of entries */
00604 
00605   /* real name entry */
00606   offset = APPLESINGLE_HEADERLEN + nentries * APPLESINGLE_ENTRYLEN;
00607   write_four(APPLESINGLE_REALNAME_ENTRY, f);
00608   write_four(offset, f);
00609   write_four(len, f);
00610   offset += len;
00611 
00612   /* time entry */
00613   write_four(APPLESINGLE_DATES_ENTRY, f);
00614   write_four(offset, f);
00615   write_four(APPLESINGLE_DATES_LEN, f);
00616   offset += APPLESINGLE_DATES_LEN;
00617   
00618   /* finder info entry */
00619   write_four(APPLESINGLE_FINDERINFO_ENTRY, f);
00620   write_four(offset, f);
00621   write_four(APPLESINGLE_FINDERINFO_LEN, f);
00622   offset += APPLESINGLE_FINDERINFO_LEN;
00623 
00624   /* resource fork entry */
00625   write_four(APPLESINGLE_RFORK_ENTRY, f);
00626   write_four(offset, f);
00627   write_four(rf_len, f);
00628   offset += rf_len;
00629 
00630   /* data fork entry */
00631   if (!appledouble) {
00632     write_four(APPLESINGLE_DFORK_ENTRY, f);
00633     write_four(offset, f);
00634     write_four(0, f);
00635   }
00636 
00637   /* real name data */
00638   fwrite(filename, 1, len, f);
00639 
00640   /* time data */
00641   i = time(0) - APPLESINGLE_TIME_DELTA;
00642   write_four(i, f);             /* creation date */
00643   write_four(i, f);             /* modification date */
00644   write_four(0x80000000, f);    /* backup date */
00645   write_four(0, f);             /* access date */
00646 
00647   /* finder info data */
00648   write_four(T1_FILETYPE, f);   /* file type */
00649   write_four(T1_FILECREATOR, f); /* file creator */
00650   write_one(T1_FINDERFLAGS, f); /* finder flags */
00651   write_one(0, f);              /* extended finder flags */
00652   write_two(0, f);              /* vertical position in window */
00653   write_two(0, f);              /* horizontal position in window */
00654   write_two(0, f);              /* window or folder ID */
00655   write_four(0, f);             /* icon ID and reserved */
00656   write_four(0, f);             /* reserved */
00657   write_one(0, f);              /* script flag */
00658   write_one(0, f);              /* reserved */
00659   write_two(0, f);              /* comment ID */
00660   write_four(0, f);             /* put away */
00661 
00662   /* resource fork data */
00663   output_raw(rf, rf_len, f);
00664 }
00665 
00666 
00667 /* write a BinHex file */
00668 
00669 static void
00670 binhex_buffer(const byte *s, int len, FILE *f)
00671 {
00672   static int col = 1;
00673   static int bits = 0;
00674   static int bitspos = 2;
00675   static const char *table = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
00676   byte buf[5];
00677   int c, i, left;
00678 
00679   if (!s && bitspos > 2) {      /* output the remaining bits */
00680     s = (const byte *)"\0";
00681     len = 1;
00682   }
00683 
00684   for (left = len; left > 0; left--, s++) {
00685     int pos;
00686     if (s[0] == 0x90) {
00687       buf[0] = 0x90;
00688       buf[1] = 0x00;
00689       pos = 2;
00690     } else {
00691       buf[0] = s[0];
00692       pos = 1;
00693     }
00694 
00695     /* find a run */
00696     if (left > 2 && s[0] == s[1] && s[0] == s[2]) {
00697       for (i = 3; i < left && i < 255; i++)
00698         if (s[i] != s[0])
00699           break;
00700       buf[pos] = 0x90;
00701       buf[pos+1] = i;
00702       pos += 2;
00703       s += i - 1;
00704       left -= i - 1;
00705     }
00706 
00707     /* store those characters */
00708     for (i = 0; i < pos; i++) {
00709       bits |= buf[i];
00710       while (bitspos >= 0) {
00711         c = (bits >> bitspos) & 0x3F;
00712         putc(table[c], f);
00713         if (++col == 63) {
00714           putc('\n', f);
00715           col = 0;
00716         }
00717         bitspos -= 6;
00718       }
00719       bits <<= 8;
00720       bitspos += 8;
00721     }
00722   }
00723 }
00724 
00725 static void
00726 output_binhex(FILE *rf, int32 rf_len, const char *filename, FILE *f)
00727 {
00728   int crc, len = strlen(filename);
00729   char buf[2048];
00730 
00731   if (len < 1 || len > 63)
00732     fatal_error("filename length must be between 1 and 63");
00733   store_one(len, buf+0);        /* filename length */
00734   memcpy(buf+1, filename, len); /* filename */
00735   store_one(0, buf+1+len);      /* version */
00736   store_four(T1_FILETYPE, buf+2+len); /* file type */
00737   store_four(T1_FILECREATOR, buf+6+len); /* file creator */
00738   store_one(T1_FINDERFLAGS, buf+10+len); /* finder flags */
00739   store_one(0, buf+10+len);     /* extended finder flags */
00740   store_four(0, buf+12+len);    /* length of data fork */
00741   store_four(rf_len, buf+16+len); /* length of resource fork */
00742   store_two(hqx_crcbuf(0, 20+len, buf), buf+20+len); /* CRC */
00743   store_two(0, buf+22+len);     /* data fork CRC */
00744 
00745   /* output BinHex comment */
00746   fputs("(This file must be converted with BinHex 4.0)\n:", f);
00747 
00748   /* BinHex the header */
00749   binhex_buffer(buf, 24+len, f);
00750 
00751   /* resource fork data */
00752   reposition(rf, 0);
00753   crc = 0;
00754   while (rf_len > 0) {
00755     int n = (rf_len < 2048 ? rf_len : 2048);
00756     fread(buf, 1, n, rf);
00757     crc = hqx_crcbuf(crc, n, buf);      /* update CRC */
00758     binhex_buffer(buf, n, f);
00759     rf_len -= n;
00760   }
00761   store_two(crc, buf);          /* resource fork CRC */
00762   binhex_buffer(buf, 2, f);
00763   binhex_buffer(0, 0, f);       /* get rid of any remaining bits */
00764   fputs(":\n", f);              /* trailer */
00765 }
00766 
00767 
00768 /*****
00769  * command line
00770  **/
00771 
00772 #define OUTPUT_OPT      301
00773 #define VERSION_OPT     302
00774 #define HELP_OPT        303
00775 #define MACBINARY_OPT   304
00776 #define RAW_OPT         305
00777 #define APPLESINGLE_OPT 306
00778 #define APPLEDOUBLE_OPT 307
00779 #define BINHEX_OPT      308
00780 #define FILENAME_OPT    309
00781 
00782 static Clp_Option options[] = {
00783   { "appledouble", 0, APPLEDOUBLE_OPT, 0, 0 },
00784   { "applesingle", 0, APPLESINGLE_OPT, 0, 0 },
00785   { "binhex", 0, BINHEX_OPT, 0, 0 },
00786   { "help", 0, HELP_OPT, 0, 0 },
00787   { "macbinary", 0, MACBINARY_OPT, 0, 0 },
00788   { "filename", 'n', FILENAME_OPT, Clp_ArgString, 0 },
00789   { "output", 'o', OUTPUT_OPT, Clp_ArgString, 0 },
00790   { "raw", 'r', RAW_OPT, 0, 0 },
00791   { "version", 0, VERSION_OPT, 0, 0 },
00792 };
00793 static char *program_name;
00794 
00795 
00796 void
00797 fatal_error(const char *message, ...)
00798 {
00799   va_list val;
00800   va_start(val, message);
00801   fprintf(stderr, "%s: ", program_name);
00802   vfprintf(stderr, message, val);
00803   putc('\n', stderr);
00804   exit(1);
00805 }
00806 
00807 void
00808 error(const char *message, ...)
00809 {
00810   va_list val;
00811   va_start(val, message);
00812   fprintf(stderr, "%s: ", program_name);
00813   vfprintf(stderr, message, val);
00814   putc('\n', stderr);
00815 }
00816 
00817 
00818 void
00819 short_usage(void)
00820 {
00821   fprintf(stderr, "Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\
00822 Try `%s --help' for more information.\n",
00823           program_name, program_name);
00824 }
00825 
00826 
00827 void
00828 usage(void)
00829 {
00830   printf("\
00831 `T1mac' translates a PostScript Type 1 font from PFA or PFB format into\n\
00832 Macintosh Type 1 format. The result can be written in MacBinary II format (the\n\
00833 default), AppleSingle format, AppleDouble format, or BinHex format, or as a\n\
00834 raw resource fork. It is sent to the standard output unless an OUTPUT file is\n\
00835 given.\n\
00836 \n\
00837 Usage: %s [OPTION]... [INPUT [OUTPUT]]\n\
00838 \n\
00839 Options:\n\
00840   -r, --raw                   Output is a raw Macintosh resource fork.\n\
00841       --macbinary             Output is in MacBinary format (default).\n\
00842       --applesingle           Output is in AppleSingle format.\n\
00843       --appledouble           Output is in AppleDouble format.\n\
00844       --binhex                Output is in BinHex format.\n\
00845   -n, --filename NAME         Macintosh font filename will be NAME.\n\
00846   -o, --output FILE           Write output to FILE.\n\
00847   -h, --help                  Print this message and exit.\n\
00848       --version               Print version number and warranty and exit.\n\
00849 \n\
00850 Report bugs to <eddietwo@lcs.mit.edu>.\n", program_name);
00851 }
00852 
00853 
00854 int
00855 main(int argc, char **argv)
00856 {
00857   int i, c;
00858   FILE *ifp = 0, *ofp = 0;
00859   const char *ifp_filename = "<stdin>";
00860   const char *ofp_filename = "<stdout>";
00861   const char *set_font_name = 0;
00862   struct font_reader fr;
00863   uint32 rfork_len;
00864   int raw = 0, macbinary = 1, applesingle = 0, appledouble = 0, binhex = 0;
00865   
00866   Clp_Parser *clp =
00867     Clp_NewParser(argc, argv, sizeof(options) / sizeof(options[0]), options);
00868   program_name = (char *)Clp_ProgramName(clp);
00869   
00870   /* interpret command line arguments using CLP */
00871   while (1) {
00872     int opt = Clp_Next(clp);
00873     switch (opt) {
00874 
00875      case RAW_OPT:
00876       raw = 1;
00877       macbinary = applesingle = appledouble = binhex = 0;
00878       break;
00879       
00880      case MACBINARY_OPT:
00881       macbinary = 1;
00882       raw = applesingle = appledouble = binhex = 0;
00883       break;
00884       
00885      case APPLESINGLE_OPT:
00886       applesingle = 1;
00887       raw = macbinary = appledouble = binhex = 0;
00888       break;
00889       
00890      case APPLEDOUBLE_OPT:
00891       appledouble = 1;
00892       raw = macbinary = applesingle = binhex = 0;
00893       break;
00894       
00895      case BINHEX_OPT:
00896       binhex = 1;
00897       raw = macbinary = applesingle = appledouble = 0;
00898       break;
00899       
00900      output_file:
00901      case OUTPUT_OPT:
00902       if (ofp)
00903         fatal_error("output file already specified");
00904       if (strcmp(clp->arg, "-") == 0)
00905         ofp = stdout;
00906       else {
00907         ofp = fopen(clp->arg, "wb");
00908         ofp_filename = clp->arg;
00909         if (!ofp) fatal_error("%s: %s", clp->arg, strerror(errno));
00910       }
00911       break;
00912 
00913      case FILENAME_OPT:
00914       if (set_font_name)
00915         fatal_error("Macintosh font filename already specified");
00916       set_font_name = clp->arg;
00917       break;
00918       
00919      case HELP_OPT:
00920       usage();
00921       exit(0);
00922       break;
00923       
00924      case VERSION_OPT:
00925       printf("t1mac (LCDF t1utils) %s\n", VERSION);
00926       printf("Copyright (C) 2000 Eddie Kohler et al.\n\
00927 This is free software; see the source for copying conditions.\n\
00928 There is NO warranty, not even for merchantability or fitness for a\n\
00929 particular purpose.\n");
00930       exit(0);
00931       break;
00932       
00933      case Clp_NotOption:
00934       if (ifp && ofp)
00935         fatal_error("too many arguments");
00936       else if (ifp)
00937         goto output_file;
00938       if (strcmp(clp->arg, "-") == 0)
00939         ifp = stdin;
00940       else {
00941         ifp_filename = clp->arg;
00942         ifp = fopen(clp->arg, "r");
00943         if (!ifp) fatal_error("%s: %s", clp->arg, strerror(errno));
00944       }
00945       break;
00946       
00947      case Clp_Done:
00948       goto done;
00949       
00950      case Clp_BadOption:
00951       short_usage();
00952       exit(1);
00953       break;
00954       
00955     }
00956   }
00957   
00958  done:
00959   if (!ifp) ifp = stdin;
00960   if (!ofp) ofp = stdout;
00961   
00962 #if defined(_MSDOS) || defined(_WIN32)
00963   /* As we are processing a PFB (binary) output */
00964   /* file, we must set its file mode to binary. */
00965   _setmode(_fileno(ofp), _O_BINARY);
00966 #endif
00967   
00968   /* prepare font reader */
00969   fr.output_ascii = t1mac_output_ascii;
00970   fr.output_binary = t1mac_output_binary;
00971   fr.output_end = t1mac_output_end;
00972 
00973   /* prepare resource fork file */
00974   rfork_f = fopen("/tmp/rfork", "w+b");//tmpfile();
00975   if (!rfork_f)
00976     fatal_error("cannot open temorary file: %s", strerror(errno));
00977   for (i = 0; i < RFORK_HEADERLEN; i++)
00978     putc(0, rfork_f);
00979   init_current_post();
00980 
00981   /* peek at first byte to see if it is the PFB marker 0x80 */
00982   c = getc(ifp);
00983   ungetc(c, ifp);
00984   
00985   /* do the file */
00986   if (c == PFB_MARKER)
00987     process_pfb(ifp, ifp_filename, &fr);
00988   else if (c == '%')
00989     process_pfa(ifp, ifp_filename, &fr);
00990   else
00991     fatal_error("%s does not start with font marker (`%%' or 0x80)", ifp_filename);
00992   if (ifp != stdin)
00993     fclose(ifp);
00994 
00995   /* check if anything was read */
00996   if (nrsrc == 0)
00997     error("no POST resources written -- are you sure this was a font?");
00998 
00999   /* output large B/W icon */
01000   output_new_rsrc("ICN#", 256, 32, (const char *)icon_bw_data, 256);
01001   /* output FREF */
01002   output_new_rsrc("FREF", 256, 32, "LWFN\0\0\0", 7);
01003   /* output BNDL */
01004   output_new_rsrc("BNDL", 256, 32, "T1UT\0\0\0\1FREF\0\0\0\0\1\0ICN#\0\0\0\0\1\0", 28);
01005   /* output other icons */
01006   output_new_rsrc("icl8", 256, 32, (const char *)icon_8_data, 1024);
01007   output_new_rsrc("icl4", 256, 32, (const char *)icon_4_data, 512);
01008   output_new_rsrc("ics#", 256, 32, (const char *)small_icon_bw_data, 64);
01009   output_new_rsrc("ics8", 256, 32, (const char *)small_icon_8_data, 256);
01010   output_new_rsrc("ics4", 256, 32, (const char *)small_icon_4_data, 128);
01011   /* output T1UT (signature) */
01012   output_new_rsrc("T1UT", 0, 0, "DConverted by t1mac (t1utils) \251Eddie Kohler http://www.lcdf.org/type/", 69);
01013 
01014   /* finish off resource file */
01015   rfork_len = complete_rfork();
01016 
01017   /* prepare font name */
01018   if (!set_font_name && font_name) {
01019     int part = 0, len = 0;
01020     char *x, *s;
01021     for (x = s = font_name; *s; s++)
01022       if (isupper(*s) || isdigit(*s)) {
01023         *x++ = *s;
01024         part++;
01025         len = 1;
01026       } else if (islower(*s)) {
01027         if (len < (part <= 1 ? 5 : 3))
01028           *x++ = *s;
01029         len++;
01030       }
01031     *x++ = 0;
01032     set_font_name = font_name;
01033   } else if (!set_font_name)
01034     set_font_name = "Unknown Font";
01035   
01036   /* now, output the file */
01037   if (macbinary)
01038     output_macbinary(rfork_f, rfork_len, set_font_name, ofp);
01039   else if (raw)
01040     output_raw(rfork_f, rfork_len, ofp);
01041   else if (applesingle || appledouble)
01042     output_applesingle(rfork_f, rfork_len, set_font_name, ofp, appledouble);
01043   else if (binhex)
01044     output_binhex(rfork_f, rfork_len, set_font_name, ofp);
01045   else
01046     fatal_error("strange output format");
01047   fclose(rfork_f);
01048 
01049   if (ofp != stdout)
01050     fclose(ofp);
01051   return 0;
01052 }

Generated at Mon Dec 11 22:46:28 2000 for Postscript Utility Library by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000