1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* ftmac.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* Mac FOND support. Written by just@letterror.com. */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 1996-2001, 2002 by */ 8*37da2899SCharles.Forsyth /* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth /* 20*37da2899SCharles.Forsyth Notes 21*37da2899SCharles.Forsyth 22*37da2899SCharles.Forsyth Mac suitcase files can (and often do!) contain multiple fonts. To 23*37da2899SCharles.Forsyth support this I use the face_index argument of FT_(Open|New)_Face() 24*37da2899SCharles.Forsyth functions, and pretend the suitcase file is a collection. 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth Warning: Although the FOND driver sets face->num_faces field to the 27*37da2899SCharles.Forsyth number of available fonts, but the Type 1 driver sets it to 1 anyway. 28*37da2899SCharles.Forsyth So this field is currently not reliable, and I don't see a clean way 29*37da2899SCharles.Forsyth to resolve that. The face_index argument translates to 30*37da2899SCharles.Forsyth 31*37da2899SCharles.Forsyth Get1IndResource( 'FOND', face_index + 1 ); 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsyth so clients should figure out the resource index of the FOND. 34*37da2899SCharles.Forsyth (I'll try to provide some example code for this at some point.) 35*37da2899SCharles.Forsyth 36*37da2899SCharles.Forsyth The Mac FOND support works roughly like this: 37*37da2899SCharles.Forsyth 38*37da2899SCharles.Forsyth - Check whether the offered stream points to a Mac suitcase file. 39*37da2899SCharles.Forsyth This is done by checking the file type: it has to be 'FFIL' or 'tfil'. 40*37da2899SCharles.Forsyth The stream that gets passed to our init_face() routine is a stdio 41*37da2899SCharles.Forsyth stream, which isn't usable for us, since the FOND resources live 42*37da2899SCharles.Forsyth in the resource fork. So we just grab the stream->pathname field. 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsyth - Read the FOND resource into memory, then check whether there is 45*37da2899SCharles.Forsyth a TrueType font and/or(!) a Type 1 font available. 46*37da2899SCharles.Forsyth 47*37da2899SCharles.Forsyth - If there is a Type 1 font available (as a separate 'LWFN' file), 48*37da2899SCharles.Forsyth read its data into memory, massage it slightly so it becomes 49*37da2899SCharles.Forsyth PFB data, wrap it into a memory stream, load the Type 1 driver 50*37da2899SCharles.Forsyth and delegate the rest of the work to it by calling FT_Open_Face(). 51*37da2899SCharles.Forsyth (XXX TODO: after this has been done, the kerning data from the FOND 52*37da2899SCharles.Forsyth resource should be appended to the face: On the Mac there are usually 53*37da2899SCharles.Forsyth no AFM files available. However, this is tricky since we need to map 54*37da2899SCharles.Forsyth Mac char codes to ps glyph names to glyph ID's...) 55*37da2899SCharles.Forsyth 56*37da2899SCharles.Forsyth - If there is a TrueType font (an 'sfnt' resource), read it into 57*37da2899SCharles.Forsyth memory, wrap it into a memory stream, load the TrueType driver 58*37da2899SCharles.Forsyth and delegate the rest of the work to it, by calling FT_Open_Face(). 59*37da2899SCharles.Forsyth */ 60*37da2899SCharles.Forsyth 61*37da2899SCharles.Forsyth 62*37da2899SCharles.Forsyth #include <ft2build.h> 63*37da2899SCharles.Forsyth #include FT_FREETYPE_H 64*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H 65*37da2899SCharles.Forsyth #include "truetype/ttobjs.h" 66*37da2899SCharles.Forsyth #include "type1/t1objs.h" 67*37da2899SCharles.Forsyth 68*37da2899SCharles.Forsyth #include <Resources.h> 69*37da2899SCharles.Forsyth #include <Fonts.h> 70*37da2899SCharles.Forsyth #include <Errors.h> 71*37da2899SCharles.Forsyth #include <Files.h> 72*37da2899SCharles.Forsyth #include <TextUtils.h> 73*37da2899SCharles.Forsyth 74*37da2899SCharles.Forsyth 75*37da2899SCharles.Forsyth #include FT_MAC_H 76*37da2899SCharles.Forsyth 77*37da2899SCharles.Forsyth 78*37da2899SCharles.Forsyth /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over 79*37da2899SCharles.Forsyth TrueType in case *both* are available (this is not common, 80*37da2899SCharles.Forsyth but it *is* possible). */ 81*37da2899SCharles.Forsyth #ifndef PREFER_LWFN 82*37da2899SCharles.Forsyth #define PREFER_LWFN 1 83*37da2899SCharles.Forsyth #endif 84*37da2899SCharles.Forsyth 85*37da2899SCharles.Forsyth /* Given a pathname, fill in a file spec. */ 86*37da2899SCharles.Forsyth static int file_spec_from_path(const char * pathname,FSSpec * spec)87*37da2899SCharles.Forsyth file_spec_from_path( const char* pathname, 88*37da2899SCharles.Forsyth FSSpec* spec ) 89*37da2899SCharles.Forsyth { 90*37da2899SCharles.Forsyth #if TARGET_API_MAC_CARBON 91*37da2899SCharles.Forsyth 92*37da2899SCharles.Forsyth OSErr e; 93*37da2899SCharles.Forsyth FSRef ref; 94*37da2899SCharles.Forsyth 95*37da2899SCharles.Forsyth 96*37da2899SCharles.Forsyth e = FSPathMakeRef( (UInt8 *)pathname, &ref, false /* not a directory */ ); 97*37da2899SCharles.Forsyth if ( e == noErr ) 98*37da2899SCharles.Forsyth e = FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL, spec, NULL ); 99*37da2899SCharles.Forsyth 100*37da2899SCharles.Forsyth return ( e == noErr ) ? 0 : (-1); 101*37da2899SCharles.Forsyth 102*37da2899SCharles.Forsyth #else 103*37da2899SCharles.Forsyth 104*37da2899SCharles.Forsyth Str255 p_path; 105*37da2899SCharles.Forsyth FT_ULong path_len; 106*37da2899SCharles.Forsyth 107*37da2899SCharles.Forsyth 108*37da2899SCharles.Forsyth /* convert path to a pascal string */ 109*37da2899SCharles.Forsyth path_len = ft_strlen( pathname ); 110*37da2899SCharles.Forsyth if ( path_len > 255 ) 111*37da2899SCharles.Forsyth return -1; 112*37da2899SCharles.Forsyth p_path[0] = (unsigned char)path_len; 113*37da2899SCharles.Forsyth ft_strncpy( (char*)p_path + 1, pathname, path_len ); 114*37da2899SCharles.Forsyth 115*37da2899SCharles.Forsyth if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr ) 116*37da2899SCharles.Forsyth return -1; 117*37da2899SCharles.Forsyth else 118*37da2899SCharles.Forsyth return 0; 119*37da2899SCharles.Forsyth 120*37da2899SCharles.Forsyth #endif 121*37da2899SCharles.Forsyth } 122*37da2899SCharles.Forsyth 123*37da2899SCharles.Forsyth 124*37da2899SCharles.Forsyth /* Return the file type of the file specified by spec. */ 125*37da2899SCharles.Forsyth static OSType get_file_type(FSSpec * spec)126*37da2899SCharles.Forsyth get_file_type( FSSpec* spec ) 127*37da2899SCharles.Forsyth { 128*37da2899SCharles.Forsyth FInfo finfo; 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth 131*37da2899SCharles.Forsyth if ( FSpGetFInfo( spec, &finfo ) != noErr ) 132*37da2899SCharles.Forsyth return 0; /* file might not exist */ 133*37da2899SCharles.Forsyth 134*37da2899SCharles.Forsyth return finfo.fdType; 135*37da2899SCharles.Forsyth } 136*37da2899SCharles.Forsyth 137*37da2899SCharles.Forsyth 138*37da2899SCharles.Forsyth #if TARGET_API_MAC_CARBON 139*37da2899SCharles.Forsyth 140*37da2899SCharles.Forsyth /* is this a Mac OS X .dfont file */ 141*37da2899SCharles.Forsyth static Boolean is_dfont(FSSpec * spec)142*37da2899SCharles.Forsyth is_dfont( FSSpec* spec ) 143*37da2899SCharles.Forsyth { 144*37da2899SCharles.Forsyth int nameLen = spec->name[0]; 145*37da2899SCharles.Forsyth 146*37da2899SCharles.Forsyth 147*37da2899SCharles.Forsyth return nameLen >= 6 && 148*37da2899SCharles.Forsyth !memcmp( spec->name + nameLen - 5, ".dfont", 6 ); 149*37da2899SCharles.Forsyth } 150*37da2899SCharles.Forsyth 151*37da2899SCharles.Forsyth #endif 152*37da2899SCharles.Forsyth 153*37da2899SCharles.Forsyth 154*37da2899SCharles.Forsyth /* Given a PostScript font name, create the Macintosh LWFN file name. */ 155*37da2899SCharles.Forsyth static void create_lwfn_name(char * ps_name,Str255 lwfn_file_name)156*37da2899SCharles.Forsyth create_lwfn_name( char* ps_name, 157*37da2899SCharles.Forsyth Str255 lwfn_file_name ) 158*37da2899SCharles.Forsyth { 159*37da2899SCharles.Forsyth int max = 5, count = 0; 160*37da2899SCharles.Forsyth FT_Byte* p = lwfn_file_name; 161*37da2899SCharles.Forsyth FT_Byte* q = (FT_Byte*)ps_name; 162*37da2899SCharles.Forsyth 163*37da2899SCharles.Forsyth 164*37da2899SCharles.Forsyth lwfn_file_name[0] = 0; 165*37da2899SCharles.Forsyth 166*37da2899SCharles.Forsyth while ( *q ) 167*37da2899SCharles.Forsyth { 168*37da2899SCharles.Forsyth if ( isupper( *q ) ) 169*37da2899SCharles.Forsyth { 170*37da2899SCharles.Forsyth if ( count ) 171*37da2899SCharles.Forsyth max = 3; 172*37da2899SCharles.Forsyth count = 0; 173*37da2899SCharles.Forsyth } 174*37da2899SCharles.Forsyth if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) ) 175*37da2899SCharles.Forsyth { 176*37da2899SCharles.Forsyth *++p = *q; 177*37da2899SCharles.Forsyth lwfn_file_name[0]++; 178*37da2899SCharles.Forsyth count++; 179*37da2899SCharles.Forsyth } 180*37da2899SCharles.Forsyth q++; 181*37da2899SCharles.Forsyth } 182*37da2899SCharles.Forsyth } 183*37da2899SCharles.Forsyth 184*37da2899SCharles.Forsyth 185*37da2899SCharles.Forsyth /* Given a file reference, answer its location as a vRefNum 186*37da2899SCharles.Forsyth and a dirID. */ 187*37da2899SCharles.Forsyth static FT_Error get_file_location(short ref_num,short * v_ref_num,long * dir_id,unsigned char * file_name)188*37da2899SCharles.Forsyth get_file_location( short ref_num, 189*37da2899SCharles.Forsyth short* v_ref_num, 190*37da2899SCharles.Forsyth long* dir_id, 191*37da2899SCharles.Forsyth unsigned char* file_name ) 192*37da2899SCharles.Forsyth { 193*37da2899SCharles.Forsyth FCBPBRec pb; 194*37da2899SCharles.Forsyth OSErr error; 195*37da2899SCharles.Forsyth 196*37da2899SCharles.Forsyth 197*37da2899SCharles.Forsyth pb.ioNamePtr = file_name; 198*37da2899SCharles.Forsyth pb.ioVRefNum = 0; 199*37da2899SCharles.Forsyth pb.ioRefNum = ref_num; 200*37da2899SCharles.Forsyth pb.ioFCBIndx = 0; 201*37da2899SCharles.Forsyth 202*37da2899SCharles.Forsyth error = PBGetFCBInfoSync( &pb ); 203*37da2899SCharles.Forsyth if ( error == noErr ) 204*37da2899SCharles.Forsyth { 205*37da2899SCharles.Forsyth *v_ref_num = pb.ioFCBVRefNum; 206*37da2899SCharles.Forsyth *dir_id = pb.ioFCBParID; 207*37da2899SCharles.Forsyth } 208*37da2899SCharles.Forsyth return error; 209*37da2899SCharles.Forsyth } 210*37da2899SCharles.Forsyth 211*37da2899SCharles.Forsyth 212*37da2899SCharles.Forsyth /* Make a file spec for an LWFN file from a FOND resource and 213*37da2899SCharles.Forsyth a file name. */ 214*37da2899SCharles.Forsyth static FT_Error make_lwfn_spec(Handle fond,unsigned char * file_name,FSSpec * spec)215*37da2899SCharles.Forsyth make_lwfn_spec( Handle fond, 216*37da2899SCharles.Forsyth unsigned char* file_name, 217*37da2899SCharles.Forsyth FSSpec* spec ) 218*37da2899SCharles.Forsyth { 219*37da2899SCharles.Forsyth FT_Error error; 220*37da2899SCharles.Forsyth short ref_num, v_ref_num; 221*37da2899SCharles.Forsyth long dir_id; 222*37da2899SCharles.Forsyth Str255 fond_file_name; 223*37da2899SCharles.Forsyth 224*37da2899SCharles.Forsyth 225*37da2899SCharles.Forsyth ref_num = HomeResFile( fond ); 226*37da2899SCharles.Forsyth 227*37da2899SCharles.Forsyth error = ResError(); 228*37da2899SCharles.Forsyth if ( !error ) 229*37da2899SCharles.Forsyth error = get_file_location( ref_num, &v_ref_num, 230*37da2899SCharles.Forsyth &dir_id, fond_file_name ); 231*37da2899SCharles.Forsyth if ( !error ) 232*37da2899SCharles.Forsyth error = FSMakeFSSpec( v_ref_num, dir_id, file_name, spec ); 233*37da2899SCharles.Forsyth 234*37da2899SCharles.Forsyth return error; 235*37da2899SCharles.Forsyth } 236*37da2899SCharles.Forsyth 237*37da2899SCharles.Forsyth 238*37da2899SCharles.Forsyth /* Look inside the FOND data, answer whether there should be an SFNT 239*37da2899SCharles.Forsyth resource, and answer the name of a possible LWFN Type 1 file. 240*37da2899SCharles.Forsyth 241*37da2899SCharles.Forsyth Thanks to Paul Miller (paulm@profoundeffects.com) for the fix 242*37da2899SCharles.Forsyth to load a face OTHER than the first one in the FOND! 243*37da2899SCharles.Forsyth */ 244*37da2899SCharles.Forsyth static void parse_fond(char * fond_data,short * have_sfnt,short * sfnt_id,Str255 lwfn_file_name,short face_index)245*37da2899SCharles.Forsyth parse_fond( char* fond_data, 246*37da2899SCharles.Forsyth short* have_sfnt, 247*37da2899SCharles.Forsyth short* sfnt_id, 248*37da2899SCharles.Forsyth Str255 lwfn_file_name, 249*37da2899SCharles.Forsyth short face_index ) 250*37da2899SCharles.Forsyth { 251*37da2899SCharles.Forsyth AsscEntry* assoc; 252*37da2899SCharles.Forsyth AsscEntry* base_assoc; 253*37da2899SCharles.Forsyth FamRec* fond; 254*37da2899SCharles.Forsyth 255*37da2899SCharles.Forsyth 256*37da2899SCharles.Forsyth *sfnt_id = 0; 257*37da2899SCharles.Forsyth *have_sfnt = 0; 258*37da2899SCharles.Forsyth lwfn_file_name[0] = 0; 259*37da2899SCharles.Forsyth 260*37da2899SCharles.Forsyth fond = (FamRec*)fond_data; 261*37da2899SCharles.Forsyth assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); 262*37da2899SCharles.Forsyth base_assoc = assoc; 263*37da2899SCharles.Forsyth assoc += face_index; /* add on the face_index! */ 264*37da2899SCharles.Forsyth 265*37da2899SCharles.Forsyth /* if the face at this index is not scalable, 266*37da2899SCharles.Forsyth fall back to the first one (old behavior) */ 267*37da2899SCharles.Forsyth if ( assoc->fontSize == 0 ) 268*37da2899SCharles.Forsyth { 269*37da2899SCharles.Forsyth *have_sfnt = 1; 270*37da2899SCharles.Forsyth *sfnt_id = assoc->fontID; 271*37da2899SCharles.Forsyth } 272*37da2899SCharles.Forsyth else if ( base_assoc->fontSize == 0 ) 273*37da2899SCharles.Forsyth { 274*37da2899SCharles.Forsyth *have_sfnt = 1; 275*37da2899SCharles.Forsyth *sfnt_id = base_assoc->fontID; 276*37da2899SCharles.Forsyth } 277*37da2899SCharles.Forsyth 278*37da2899SCharles.Forsyth if ( fond->ffStylOff ) 279*37da2899SCharles.Forsyth { 280*37da2899SCharles.Forsyth unsigned char* p = (unsigned char*)fond_data; 281*37da2899SCharles.Forsyth StyleTable* style; 282*37da2899SCharles.Forsyth unsigned short string_count; 283*37da2899SCharles.Forsyth char ps_name[256]; 284*37da2899SCharles.Forsyth unsigned char* names[64]; 285*37da2899SCharles.Forsyth int i; 286*37da2899SCharles.Forsyth 287*37da2899SCharles.Forsyth 288*37da2899SCharles.Forsyth p += fond->ffStylOff; 289*37da2899SCharles.Forsyth style = (StyleTable*)p; 290*37da2899SCharles.Forsyth p += sizeof ( StyleTable ); 291*37da2899SCharles.Forsyth string_count = *(unsigned short*)(p); 292*37da2899SCharles.Forsyth p += sizeof ( short ); 293*37da2899SCharles.Forsyth 294*37da2899SCharles.Forsyth for ( i = 0 ; i < string_count && i < 64; i++ ) 295*37da2899SCharles.Forsyth { 296*37da2899SCharles.Forsyth names[i] = p; 297*37da2899SCharles.Forsyth p += names[i][0]; 298*37da2899SCharles.Forsyth p++; 299*37da2899SCharles.Forsyth } 300*37da2899SCharles.Forsyth 301*37da2899SCharles.Forsyth { 302*37da2899SCharles.Forsyth size_t ps_name_len = (size_t)names[0][0]; 303*37da2899SCharles.Forsyth 304*37da2899SCharles.Forsyth 305*37da2899SCharles.Forsyth if ( ps_name_len != 0 ) 306*37da2899SCharles.Forsyth { 307*37da2899SCharles.Forsyth memcpy(ps_name, names[0] + 1, ps_name_len); 308*37da2899SCharles.Forsyth ps_name[ps_name_len] = 0; 309*37da2899SCharles.Forsyth } 310*37da2899SCharles.Forsyth if ( style->indexes[0] > 1 ) 311*37da2899SCharles.Forsyth { 312*37da2899SCharles.Forsyth unsigned char* suffixes = names[style->indexes[0] - 1]; 313*37da2899SCharles.Forsyth 314*37da2899SCharles.Forsyth 315*37da2899SCharles.Forsyth for ( i = 1; i < suffixes[0]; i++ ) 316*37da2899SCharles.Forsyth { 317*37da2899SCharles.Forsyth unsigned char* s; 318*37da2899SCharles.Forsyth size_t j = suffixes[i] - 1; 319*37da2899SCharles.Forsyth 320*37da2899SCharles.Forsyth 321*37da2899SCharles.Forsyth if ( j < string_count && ( s = names[j] ) != NULL ) 322*37da2899SCharles.Forsyth { 323*37da2899SCharles.Forsyth size_t s_len = (size_t)s[0]; 324*37da2899SCharles.Forsyth 325*37da2899SCharles.Forsyth 326*37da2899SCharles.Forsyth if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) ) 327*37da2899SCharles.Forsyth { 328*37da2899SCharles.Forsyth memcpy( ps_name + ps_name_len, s + 1, s_len ); 329*37da2899SCharles.Forsyth ps_name_len += s_len; 330*37da2899SCharles.Forsyth ps_name[ps_name_len] = 0; 331*37da2899SCharles.Forsyth } 332*37da2899SCharles.Forsyth } 333*37da2899SCharles.Forsyth } 334*37da2899SCharles.Forsyth } 335*37da2899SCharles.Forsyth } 336*37da2899SCharles.Forsyth 337*37da2899SCharles.Forsyth create_lwfn_name( ps_name, lwfn_file_name ); 338*37da2899SCharles.Forsyth } 339*37da2899SCharles.Forsyth } 340*37da2899SCharles.Forsyth 341*37da2899SCharles.Forsyth 342*37da2899SCharles.Forsyth /* Read Type 1 data from the POST resources inside the LWFN file, 343*37da2899SCharles.Forsyth return a PFB buffer. This is somewhat convoluted because the FT2 344*37da2899SCharles.Forsyth PFB parser wants the ASCII header as one chunk, and the LWFN 345*37da2899SCharles.Forsyth chunks are often not organized that way, so we'll glue chunks 346*37da2899SCharles.Forsyth of the same type together. */ 347*37da2899SCharles.Forsyth static FT_Error read_lwfn(FT_Memory memory,FSSpec * lwfn_spec,FT_Byte ** pfb_data,FT_ULong * size)348*37da2899SCharles.Forsyth read_lwfn( FT_Memory memory, 349*37da2899SCharles.Forsyth FSSpec* lwfn_spec, 350*37da2899SCharles.Forsyth FT_Byte** pfb_data, 351*37da2899SCharles.Forsyth FT_ULong* size ) 352*37da2899SCharles.Forsyth { 353*37da2899SCharles.Forsyth FT_Error error = FT_Err_Ok; 354*37da2899SCharles.Forsyth short res_ref, res_id; 355*37da2899SCharles.Forsyth unsigned char *buffer, *p, *size_p = NULL; 356*37da2899SCharles.Forsyth FT_ULong total_size = 0; 357*37da2899SCharles.Forsyth FT_ULong post_size, pfb_chunk_size; 358*37da2899SCharles.Forsyth Handle post_data; 359*37da2899SCharles.Forsyth char code, last_code; 360*37da2899SCharles.Forsyth 361*37da2899SCharles.Forsyth 362*37da2899SCharles.Forsyth res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm ); 363*37da2899SCharles.Forsyth if ( ResError() ) 364*37da2899SCharles.Forsyth return FT_Err_Out_Of_Memory; 365*37da2899SCharles.Forsyth UseResFile( res_ref ); 366*37da2899SCharles.Forsyth 367*37da2899SCharles.Forsyth /* First pass: load all POST resources, and determine the size of 368*37da2899SCharles.Forsyth the output buffer. */ 369*37da2899SCharles.Forsyth res_id = 501; 370*37da2899SCharles.Forsyth last_code = -1; 371*37da2899SCharles.Forsyth 372*37da2899SCharles.Forsyth for (;;) 373*37da2899SCharles.Forsyth { 374*37da2899SCharles.Forsyth post_data = Get1Resource( 'POST', res_id++ ); 375*37da2899SCharles.Forsyth if ( post_data == NULL ) 376*37da2899SCharles.Forsyth break; /* we're done */ 377*37da2899SCharles.Forsyth 378*37da2899SCharles.Forsyth code = (*post_data)[0]; 379*37da2899SCharles.Forsyth 380*37da2899SCharles.Forsyth if ( code != last_code ) 381*37da2899SCharles.Forsyth { 382*37da2899SCharles.Forsyth if ( code == 5 ) 383*37da2899SCharles.Forsyth total_size += 2; /* just the end code */ 384*37da2899SCharles.Forsyth else 385*37da2899SCharles.Forsyth total_size += 6; /* code + 4 bytes chunk length */ 386*37da2899SCharles.Forsyth } 387*37da2899SCharles.Forsyth 388*37da2899SCharles.Forsyth total_size += GetHandleSize( post_data ) - 2; 389*37da2899SCharles.Forsyth last_code = code; 390*37da2899SCharles.Forsyth } 391*37da2899SCharles.Forsyth 392*37da2899SCharles.Forsyth if ( FT_ALLOC( buffer, (FT_Long)total_size ) ) 393*37da2899SCharles.Forsyth goto Error; 394*37da2899SCharles.Forsyth 395*37da2899SCharles.Forsyth /* Second pass: append all POST data to the buffer, add PFB fields. 396*37da2899SCharles.Forsyth Glue all consecutive chunks of the same type together. */ 397*37da2899SCharles.Forsyth p = buffer; 398*37da2899SCharles.Forsyth res_id = 501; 399*37da2899SCharles.Forsyth last_code = -1; 400*37da2899SCharles.Forsyth pfb_chunk_size = 0; 401*37da2899SCharles.Forsyth 402*37da2899SCharles.Forsyth for (;;) 403*37da2899SCharles.Forsyth { 404*37da2899SCharles.Forsyth post_data = Get1Resource( 'POST', res_id++ ); 405*37da2899SCharles.Forsyth if ( post_data == NULL ) 406*37da2899SCharles.Forsyth break; /* we're done */ 407*37da2899SCharles.Forsyth 408*37da2899SCharles.Forsyth post_size = (FT_ULong)GetHandleSize( post_data ) - 2; 409*37da2899SCharles.Forsyth code = (*post_data)[0]; 410*37da2899SCharles.Forsyth 411*37da2899SCharles.Forsyth if ( code != last_code ) 412*37da2899SCharles.Forsyth { 413*37da2899SCharles.Forsyth if ( last_code != -1 ) 414*37da2899SCharles.Forsyth { 415*37da2899SCharles.Forsyth /* we're done adding a chunk, fill in the size field */ 416*37da2899SCharles.Forsyth if ( size_p != NULL ) 417*37da2899SCharles.Forsyth { 418*37da2899SCharles.Forsyth *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF ); 419*37da2899SCharles.Forsyth *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF ); 420*37da2899SCharles.Forsyth *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF ); 421*37da2899SCharles.Forsyth *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF ); 422*37da2899SCharles.Forsyth } 423*37da2899SCharles.Forsyth pfb_chunk_size = 0; 424*37da2899SCharles.Forsyth } 425*37da2899SCharles.Forsyth 426*37da2899SCharles.Forsyth *p++ = 0x80; 427*37da2899SCharles.Forsyth if ( code == 5 ) 428*37da2899SCharles.Forsyth *p++ = 0x03; /* the end */ 429*37da2899SCharles.Forsyth else if ( code == 2 ) 430*37da2899SCharles.Forsyth *p++ = 0x02; /* binary segment */ 431*37da2899SCharles.Forsyth else 432*37da2899SCharles.Forsyth *p++ = 0x01; /* ASCII segment */ 433*37da2899SCharles.Forsyth 434*37da2899SCharles.Forsyth if ( code != 5 ) 435*37da2899SCharles.Forsyth { 436*37da2899SCharles.Forsyth size_p = p; /* save for later */ 437*37da2899SCharles.Forsyth p += 4; /* make space for size field */ 438*37da2899SCharles.Forsyth } 439*37da2899SCharles.Forsyth } 440*37da2899SCharles.Forsyth 441*37da2899SCharles.Forsyth ft_memcpy( p, *post_data + 2, post_size ); 442*37da2899SCharles.Forsyth pfb_chunk_size += post_size; 443*37da2899SCharles.Forsyth p += post_size; 444*37da2899SCharles.Forsyth last_code = code; 445*37da2899SCharles.Forsyth } 446*37da2899SCharles.Forsyth 447*37da2899SCharles.Forsyth *pfb_data = buffer; 448*37da2899SCharles.Forsyth *size = total_size; 449*37da2899SCharles.Forsyth 450*37da2899SCharles.Forsyth Error: 451*37da2899SCharles.Forsyth CloseResFile( res_ref ); 452*37da2899SCharles.Forsyth return error; 453*37da2899SCharles.Forsyth } 454*37da2899SCharles.Forsyth 455*37da2899SCharles.Forsyth 456*37da2899SCharles.Forsyth /* Finalizer for a memory stream; gets called by FT_Done_Face(). 457*37da2899SCharles.Forsyth It frees the memory it uses. */ 458*37da2899SCharles.Forsyth static void memory_stream_close(FT_Stream stream)459*37da2899SCharles.Forsyth memory_stream_close( FT_Stream stream ) 460*37da2899SCharles.Forsyth { 461*37da2899SCharles.Forsyth FT_Memory memory = stream->memory; 462*37da2899SCharles.Forsyth 463*37da2899SCharles.Forsyth 464*37da2899SCharles.Forsyth FT_FREE( stream->base ); 465*37da2899SCharles.Forsyth 466*37da2899SCharles.Forsyth stream->size = 0; 467*37da2899SCharles.Forsyth stream->base = 0; 468*37da2899SCharles.Forsyth stream->close = 0; 469*37da2899SCharles.Forsyth } 470*37da2899SCharles.Forsyth 471*37da2899SCharles.Forsyth 472*37da2899SCharles.Forsyth /* Create a new memory stream from a buffer and a size. */ 473*37da2899SCharles.Forsyth static FT_Error new_memory_stream(FT_Library library,FT_Byte * base,FT_ULong size,FT_Stream_CloseFunc close,FT_Stream * astream)474*37da2899SCharles.Forsyth new_memory_stream( FT_Library library, 475*37da2899SCharles.Forsyth FT_Byte* base, 476*37da2899SCharles.Forsyth FT_ULong size, 477*37da2899SCharles.Forsyth FT_Stream_CloseFunc close, 478*37da2899SCharles.Forsyth FT_Stream *astream ) 479*37da2899SCharles.Forsyth { 480*37da2899SCharles.Forsyth FT_Error error; 481*37da2899SCharles.Forsyth FT_Memory memory; 482*37da2899SCharles.Forsyth FT_Stream stream; 483*37da2899SCharles.Forsyth 484*37da2899SCharles.Forsyth 485*37da2899SCharles.Forsyth if ( !library ) 486*37da2899SCharles.Forsyth return FT_Err_Invalid_Library_Handle; 487*37da2899SCharles.Forsyth 488*37da2899SCharles.Forsyth if ( !base ) 489*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 490*37da2899SCharles.Forsyth 491*37da2899SCharles.Forsyth *astream = 0; 492*37da2899SCharles.Forsyth memory = library->memory; 493*37da2899SCharles.Forsyth if ( FT_NEW( stream ) ) 494*37da2899SCharles.Forsyth goto Exit; 495*37da2899SCharles.Forsyth 496*37da2899SCharles.Forsyth FT_Stream_OpenMemory( stream, base, size ); 497*37da2899SCharles.Forsyth 498*37da2899SCharles.Forsyth stream->close = close; 499*37da2899SCharles.Forsyth 500*37da2899SCharles.Forsyth *astream = stream; 501*37da2899SCharles.Forsyth 502*37da2899SCharles.Forsyth Exit: 503*37da2899SCharles.Forsyth return error; 504*37da2899SCharles.Forsyth } 505*37da2899SCharles.Forsyth 506*37da2899SCharles.Forsyth 507*37da2899SCharles.Forsyth /* Create a new FT_Face given a buffer and a driver name. */ 508*37da2899SCharles.Forsyth static FT_Error open_face_from_buffer(FT_Library library,FT_Byte * base,FT_ULong size,FT_Long face_index,char * driver_name,FT_Face * aface)509*37da2899SCharles.Forsyth open_face_from_buffer( FT_Library library, 510*37da2899SCharles.Forsyth FT_Byte* base, 511*37da2899SCharles.Forsyth FT_ULong size, 512*37da2899SCharles.Forsyth FT_Long face_index, 513*37da2899SCharles.Forsyth char* driver_name, 514*37da2899SCharles.Forsyth FT_Face *aface ) 515*37da2899SCharles.Forsyth { 516*37da2899SCharles.Forsyth FT_Open_Args args; 517*37da2899SCharles.Forsyth FT_Error error; 518*37da2899SCharles.Forsyth FT_Stream stream; 519*37da2899SCharles.Forsyth FT_Memory memory = library->memory; 520*37da2899SCharles.Forsyth 521*37da2899SCharles.Forsyth 522*37da2899SCharles.Forsyth error = new_memory_stream( library, 523*37da2899SCharles.Forsyth base, 524*37da2899SCharles.Forsyth size, 525*37da2899SCharles.Forsyth memory_stream_close, 526*37da2899SCharles.Forsyth &stream ); 527*37da2899SCharles.Forsyth if ( error ) 528*37da2899SCharles.Forsyth { 529*37da2899SCharles.Forsyth FT_FREE( base ); 530*37da2899SCharles.Forsyth return error; 531*37da2899SCharles.Forsyth } 532*37da2899SCharles.Forsyth 533*37da2899SCharles.Forsyth args.flags = FT_OPEN_STREAM; 534*37da2899SCharles.Forsyth args.stream = stream; 535*37da2899SCharles.Forsyth if ( driver_name ) 536*37da2899SCharles.Forsyth { 537*37da2899SCharles.Forsyth args.flags = args.flags | FT_OPEN_DRIVER; 538*37da2899SCharles.Forsyth args.driver = FT_Get_Module( library, driver_name ); 539*37da2899SCharles.Forsyth } 540*37da2899SCharles.Forsyth 541*37da2899SCharles.Forsyth error = FT_Open_Face( library, &args, face_index, aface ); 542*37da2899SCharles.Forsyth if ( error == FT_Err_Ok ) 543*37da2899SCharles.Forsyth (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; 544*37da2899SCharles.Forsyth else 545*37da2899SCharles.Forsyth { 546*37da2899SCharles.Forsyth FT_Stream_CloseFunc( stream ); 547*37da2899SCharles.Forsyth FT_FREE( stream ); 548*37da2899SCharles.Forsyth } 549*37da2899SCharles.Forsyth 550*37da2899SCharles.Forsyth return error; 551*37da2899SCharles.Forsyth } 552*37da2899SCharles.Forsyth 553*37da2899SCharles.Forsyth 554*37da2899SCharles.Forsyth /* Create a new FT_Face from a file spec to an LWFN file. */ 555*37da2899SCharles.Forsyth static FT_Error FT_New_Face_From_LWFN(FT_Library library,FSSpec * spec,FT_Long face_index,FT_Face * aface)556*37da2899SCharles.Forsyth FT_New_Face_From_LWFN( FT_Library library, 557*37da2899SCharles.Forsyth FSSpec* spec, 558*37da2899SCharles.Forsyth FT_Long face_index, 559*37da2899SCharles.Forsyth FT_Face *aface ) 560*37da2899SCharles.Forsyth { 561*37da2899SCharles.Forsyth FT_Byte* pfb_data; 562*37da2899SCharles.Forsyth FT_ULong pfb_size; 563*37da2899SCharles.Forsyth FT_Error error; 564*37da2899SCharles.Forsyth 565*37da2899SCharles.Forsyth 566*37da2899SCharles.Forsyth error = read_lwfn( library->memory, spec, &pfb_data, &pfb_size ); 567*37da2899SCharles.Forsyth if ( error ) 568*37da2899SCharles.Forsyth return error; 569*37da2899SCharles.Forsyth 570*37da2899SCharles.Forsyth return open_face_from_buffer( library, 571*37da2899SCharles.Forsyth pfb_data, 572*37da2899SCharles.Forsyth pfb_size, 573*37da2899SCharles.Forsyth face_index, 574*37da2899SCharles.Forsyth "type1", 575*37da2899SCharles.Forsyth aface ); 576*37da2899SCharles.Forsyth } 577*37da2899SCharles.Forsyth 578*37da2899SCharles.Forsyth 579*37da2899SCharles.Forsyth /* Create a new FT_Face from an SFNT resource, specified by res ID. */ 580*37da2899SCharles.Forsyth static FT_Error FT_New_Face_From_SFNT(FT_Library library,short sfnt_id,FT_Long face_index,FT_Face * aface)581*37da2899SCharles.Forsyth FT_New_Face_From_SFNT( FT_Library library, 582*37da2899SCharles.Forsyth short sfnt_id, 583*37da2899SCharles.Forsyth FT_Long face_index, 584*37da2899SCharles.Forsyth FT_Face *aface ) 585*37da2899SCharles.Forsyth { 586*37da2899SCharles.Forsyth Handle sfnt = NULL; 587*37da2899SCharles.Forsyth FT_Byte* sfnt_data; 588*37da2899SCharles.Forsyth size_t sfnt_size; 589*37da2899SCharles.Forsyth FT_Error error = 0; 590*37da2899SCharles.Forsyth FT_Memory memory = library->memory; 591*37da2899SCharles.Forsyth 592*37da2899SCharles.Forsyth 593*37da2899SCharles.Forsyth sfnt = GetResource( 'sfnt', sfnt_id ); 594*37da2899SCharles.Forsyth if ( ResError() ) 595*37da2899SCharles.Forsyth return FT_Err_Invalid_Handle; 596*37da2899SCharles.Forsyth 597*37da2899SCharles.Forsyth sfnt_size = (FT_ULong)GetHandleSize( sfnt ); 598*37da2899SCharles.Forsyth if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) ) 599*37da2899SCharles.Forsyth { 600*37da2899SCharles.Forsyth ReleaseResource( sfnt ); 601*37da2899SCharles.Forsyth return error; 602*37da2899SCharles.Forsyth } 603*37da2899SCharles.Forsyth 604*37da2899SCharles.Forsyth HLock( sfnt ); 605*37da2899SCharles.Forsyth ft_memcpy( sfnt_data, *sfnt, sfnt_size ); 606*37da2899SCharles.Forsyth HUnlock( sfnt ); 607*37da2899SCharles.Forsyth ReleaseResource( sfnt ); 608*37da2899SCharles.Forsyth 609*37da2899SCharles.Forsyth return open_face_from_buffer( library, 610*37da2899SCharles.Forsyth sfnt_data, 611*37da2899SCharles.Forsyth sfnt_size, 612*37da2899SCharles.Forsyth face_index, 613*37da2899SCharles.Forsyth "truetype", 614*37da2899SCharles.Forsyth aface ); 615*37da2899SCharles.Forsyth } 616*37da2899SCharles.Forsyth 617*37da2899SCharles.Forsyth 618*37da2899SCharles.Forsyth /* Create a new FT_Face from a file spec to a suitcase file. */ 619*37da2899SCharles.Forsyth static FT_Error FT_New_Face_From_Suitcase(FT_Library library,FSSpec * spec,FT_Long face_index,FT_Face * aface)620*37da2899SCharles.Forsyth FT_New_Face_From_Suitcase( FT_Library library, 621*37da2899SCharles.Forsyth FSSpec* spec, 622*37da2899SCharles.Forsyth FT_Long face_index, 623*37da2899SCharles.Forsyth FT_Face *aface ) 624*37da2899SCharles.Forsyth { 625*37da2899SCharles.Forsyth FT_Error error = FT_Err_Ok; 626*37da2899SCharles.Forsyth short res_ref, res_index; 627*37da2899SCharles.Forsyth Handle fond; 628*37da2899SCharles.Forsyth 629*37da2899SCharles.Forsyth 630*37da2899SCharles.Forsyth res_ref = FSpOpenResFile( spec, fsRdPerm ); 631*37da2899SCharles.Forsyth if ( ResError() ) 632*37da2899SCharles.Forsyth return FT_Err_Cannot_Open_Resource; 633*37da2899SCharles.Forsyth UseResFile( res_ref ); 634*37da2899SCharles.Forsyth 635*37da2899SCharles.Forsyth /* face_index may be -1, in which case we 636*37da2899SCharles.Forsyth just need to do a sanity check */ 637*37da2899SCharles.Forsyth if ( face_index < 0 ) 638*37da2899SCharles.Forsyth res_index = 1; 639*37da2899SCharles.Forsyth else 640*37da2899SCharles.Forsyth { 641*37da2899SCharles.Forsyth res_index = (short)( face_index + 1 ); 642*37da2899SCharles.Forsyth face_index = 0; 643*37da2899SCharles.Forsyth } 644*37da2899SCharles.Forsyth fond = Get1IndResource( 'FOND', res_index ); 645*37da2899SCharles.Forsyth if ( ResError() ) 646*37da2899SCharles.Forsyth { 647*37da2899SCharles.Forsyth error = FT_Err_Cannot_Open_Resource; 648*37da2899SCharles.Forsyth goto Error; 649*37da2899SCharles.Forsyth } 650*37da2899SCharles.Forsyth 651*37da2899SCharles.Forsyth error = FT_New_Face_From_FOND( library, fond, face_index, aface ); 652*37da2899SCharles.Forsyth 653*37da2899SCharles.Forsyth Error: 654*37da2899SCharles.Forsyth CloseResFile( res_ref ); 655*37da2899SCharles.Forsyth return error; 656*37da2899SCharles.Forsyth } 657*37da2899SCharles.Forsyth 658*37da2899SCharles.Forsyth 659*37da2899SCharles.Forsyth #if TARGET_API_MAC_CARBON 660*37da2899SCharles.Forsyth 661*37da2899SCharles.Forsyth /* Create a new FT_Face from a file spec to a suitcase file. */ 662*37da2899SCharles.Forsyth static FT_Error FT_New_Face_From_dfont(FT_Library library,FSSpec * spec,FT_Long face_index,FT_Face * aface)663*37da2899SCharles.Forsyth FT_New_Face_From_dfont( FT_Library library, 664*37da2899SCharles.Forsyth FSSpec* spec, 665*37da2899SCharles.Forsyth FT_Long face_index, 666*37da2899SCharles.Forsyth FT_Face* aface ) 667*37da2899SCharles.Forsyth { 668*37da2899SCharles.Forsyth FT_Error error = FT_Err_Ok; 669*37da2899SCharles.Forsyth short res_ref, res_index; 670*37da2899SCharles.Forsyth Handle fond; 671*37da2899SCharles.Forsyth FSRef hostContainerRef; 672*37da2899SCharles.Forsyth 673*37da2899SCharles.Forsyth 674*37da2899SCharles.Forsyth error = FSpMakeFSRef( spec, &hostContainerRef ); 675*37da2899SCharles.Forsyth if ( error == noErr ) 676*37da2899SCharles.Forsyth error = FSOpenResourceFile( &hostContainerRef, 677*37da2899SCharles.Forsyth 0, NULL, fsRdPerm, &res_ref ); 678*37da2899SCharles.Forsyth 679*37da2899SCharles.Forsyth if ( error != noErr ) 680*37da2899SCharles.Forsyth return FT_Err_Cannot_Open_Resource; 681*37da2899SCharles.Forsyth 682*37da2899SCharles.Forsyth UseResFile( res_ref ); 683*37da2899SCharles.Forsyth 684*37da2899SCharles.Forsyth /* face_index may be -1, in which case we 685*37da2899SCharles.Forsyth just need to do a sanity check */ 686*37da2899SCharles.Forsyth if ( face_index < 0 ) 687*37da2899SCharles.Forsyth res_index = 1; 688*37da2899SCharles.Forsyth else 689*37da2899SCharles.Forsyth { 690*37da2899SCharles.Forsyth res_index = (short)( face_index + 1 ); 691*37da2899SCharles.Forsyth face_index = 0; 692*37da2899SCharles.Forsyth } 693*37da2899SCharles.Forsyth fond = Get1IndResource( 'FOND', res_index ); 694*37da2899SCharles.Forsyth if ( ResError() ) 695*37da2899SCharles.Forsyth { 696*37da2899SCharles.Forsyth error = FT_Err_Cannot_Open_Resource; 697*37da2899SCharles.Forsyth goto Error; 698*37da2899SCharles.Forsyth } 699*37da2899SCharles.Forsyth 700*37da2899SCharles.Forsyth error = FT_New_Face_From_FOND( library, fond, face_index, aface ); 701*37da2899SCharles.Forsyth 702*37da2899SCharles.Forsyth Error: 703*37da2899SCharles.Forsyth CloseResFile( res_ref ); 704*37da2899SCharles.Forsyth return error; 705*37da2899SCharles.Forsyth } 706*37da2899SCharles.Forsyth 707*37da2899SCharles.Forsyth #endif 708*37da2899SCharles.Forsyth 709*37da2899SCharles.Forsyth 710*37da2899SCharles.Forsyth /* documentation is in ftmac.h */ 711*37da2899SCharles.Forsyth 712*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_New_Face_From_FOND(FT_Library library,Handle fond,FT_Long face_index,FT_Face * aface)713*37da2899SCharles.Forsyth FT_New_Face_From_FOND( FT_Library library, 714*37da2899SCharles.Forsyth Handle fond, 715*37da2899SCharles.Forsyth FT_Long face_index, 716*37da2899SCharles.Forsyth FT_Face *aface ) 717*37da2899SCharles.Forsyth { 718*37da2899SCharles.Forsyth short sfnt_id, have_sfnt, have_lwfn = 0; 719*37da2899SCharles.Forsyth Str255 lwfn_file_name; 720*37da2899SCharles.Forsyth short fond_id; 721*37da2899SCharles.Forsyth OSType fond_type; 722*37da2899SCharles.Forsyth Str255 fond_name; 723*37da2899SCharles.Forsyth FSSpec lwfn_spec; 724*37da2899SCharles.Forsyth 725*37da2899SCharles.Forsyth 726*37da2899SCharles.Forsyth GetResInfo( fond, &fond_id, &fond_type, fond_name ); 727*37da2899SCharles.Forsyth if ( ResError() != noErr || fond_type != 'FOND' ) 728*37da2899SCharles.Forsyth return FT_Err_Invalid_File_Format; 729*37da2899SCharles.Forsyth 730*37da2899SCharles.Forsyth HLock( fond ); 731*37da2899SCharles.Forsyth parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index ); 732*37da2899SCharles.Forsyth HUnlock( fond ); 733*37da2899SCharles.Forsyth 734*37da2899SCharles.Forsyth if ( lwfn_file_name[0] ) 735*37da2899SCharles.Forsyth { 736*37da2899SCharles.Forsyth if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok ) 737*37da2899SCharles.Forsyth have_lwfn = 1; /* yeah, we got one! */ 738*37da2899SCharles.Forsyth else 739*37da2899SCharles.Forsyth have_lwfn = 0; /* no LWFN file found */ 740*37da2899SCharles.Forsyth } 741*37da2899SCharles.Forsyth 742*37da2899SCharles.Forsyth if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) ) 743*37da2899SCharles.Forsyth return FT_New_Face_From_LWFN( library, 744*37da2899SCharles.Forsyth &lwfn_spec, 745*37da2899SCharles.Forsyth face_index, 746*37da2899SCharles.Forsyth aface ); 747*37da2899SCharles.Forsyth else if ( have_sfnt ) 748*37da2899SCharles.Forsyth return FT_New_Face_From_SFNT( library, 749*37da2899SCharles.Forsyth sfnt_id, 750*37da2899SCharles.Forsyth face_index, 751*37da2899SCharles.Forsyth aface ); 752*37da2899SCharles.Forsyth 753*37da2899SCharles.Forsyth return FT_Err_Unknown_File_Format; 754*37da2899SCharles.Forsyth } 755*37da2899SCharles.Forsyth 756*37da2899SCharles.Forsyth 757*37da2899SCharles.Forsyth /* documentation is in ftmac.h */ 758*37da2899SCharles.Forsyth 759*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_GetFile_From_Mac_Name(char * fontName,FSSpec * pathSpec,FT_Long * face_index)760*37da2899SCharles.Forsyth FT_GetFile_From_Mac_Name( char* fontName, 761*37da2899SCharles.Forsyth FSSpec* pathSpec, 762*37da2899SCharles.Forsyth FT_Long* face_index ) 763*37da2899SCharles.Forsyth { 764*37da2899SCharles.Forsyth OptionBits options = kFMUseGlobalScopeOption; 765*37da2899SCharles.Forsyth 766*37da2899SCharles.Forsyth FMFontFamilyIterator famIter; 767*37da2899SCharles.Forsyth OSStatus status = FMCreateFontFamilyIterator( NULL, NULL, 768*37da2899SCharles.Forsyth options, 769*37da2899SCharles.Forsyth &famIter ); 770*37da2899SCharles.Forsyth FMFont the_font = NULL; 771*37da2899SCharles.Forsyth FMFontFamily family = NULL; 772*37da2899SCharles.Forsyth 773*37da2899SCharles.Forsyth 774*37da2899SCharles.Forsyth *face_index = 0; 775*37da2899SCharles.Forsyth while ( status == 0 && !the_font ) 776*37da2899SCharles.Forsyth { 777*37da2899SCharles.Forsyth status = FMGetNextFontFamily( &famIter, &family ); 778*37da2899SCharles.Forsyth if ( status == 0 ) 779*37da2899SCharles.Forsyth { 780*37da2899SCharles.Forsyth int stat2; 781*37da2899SCharles.Forsyth FMFontFamilyInstanceIterator instIter; 782*37da2899SCharles.Forsyth Str255 famNameStr; 783*37da2899SCharles.Forsyth char famName[256]; 784*37da2899SCharles.Forsyth 785*37da2899SCharles.Forsyth 786*37da2899SCharles.Forsyth /* get the family name */ 787*37da2899SCharles.Forsyth FMGetFontFamilyName( family, famNameStr ); 788*37da2899SCharles.Forsyth CopyPascalStringToC( famNameStr, famName ); 789*37da2899SCharles.Forsyth 790*37da2899SCharles.Forsyth /* iterate through the styles */ 791*37da2899SCharles.Forsyth FMCreateFontFamilyInstanceIterator( family, &instIter ); 792*37da2899SCharles.Forsyth 793*37da2899SCharles.Forsyth *face_index = 0; 794*37da2899SCharles.Forsyth stat2 = 0; 795*37da2899SCharles.Forsyth while ( stat2 == 0 && !the_font ) 796*37da2899SCharles.Forsyth { 797*37da2899SCharles.Forsyth FMFontStyle style; 798*37da2899SCharles.Forsyth FMFontSize size; 799*37da2899SCharles.Forsyth FMFont font; 800*37da2899SCharles.Forsyth 801*37da2899SCharles.Forsyth 802*37da2899SCharles.Forsyth stat2 = FMGetNextFontFamilyInstance( &instIter, &font, 803*37da2899SCharles.Forsyth &style, &size ); 804*37da2899SCharles.Forsyth if ( stat2 == 0 && size == 0 ) 805*37da2899SCharles.Forsyth { 806*37da2899SCharles.Forsyth char fullName[256]; 807*37da2899SCharles.Forsyth 808*37da2899SCharles.Forsyth 809*37da2899SCharles.Forsyth /* build up a complete face name */ 810*37da2899SCharles.Forsyth ft_strcpy( fullName, famName ); 811*37da2899SCharles.Forsyth if ( style & bold ) 812*37da2899SCharles.Forsyth strcat( fullName, " Bold" ); 813*37da2899SCharles.Forsyth if ( style & italic ) 814*37da2899SCharles.Forsyth strcat( fullName, " Italic" ); 815*37da2899SCharles.Forsyth 816*37da2899SCharles.Forsyth /* compare with the name we are looking for */ 817*37da2899SCharles.Forsyth if ( ft_strcmp( fullName, fontName ) == 0 ) 818*37da2899SCharles.Forsyth { 819*37da2899SCharles.Forsyth /* found it! */ 820*37da2899SCharles.Forsyth the_font = font; 821*37da2899SCharles.Forsyth } 822*37da2899SCharles.Forsyth else 823*37da2899SCharles.Forsyth ++(*face_index); 824*37da2899SCharles.Forsyth } 825*37da2899SCharles.Forsyth } 826*37da2899SCharles.Forsyth 827*37da2899SCharles.Forsyth FMDisposeFontFamilyInstanceIterator( &instIter ); 828*37da2899SCharles.Forsyth } 829*37da2899SCharles.Forsyth } 830*37da2899SCharles.Forsyth 831*37da2899SCharles.Forsyth FMDisposeFontFamilyIterator( &famIter ); 832*37da2899SCharles.Forsyth 833*37da2899SCharles.Forsyth if ( the_font ) 834*37da2899SCharles.Forsyth { 835*37da2899SCharles.Forsyth FMGetFontContainer( the_font, pathSpec ); 836*37da2899SCharles.Forsyth return FT_Err_Ok; 837*37da2899SCharles.Forsyth } 838*37da2899SCharles.Forsyth else 839*37da2899SCharles.Forsyth return FT_Err_Unknown_File_Format; 840*37da2899SCharles.Forsyth } 841*37da2899SCharles.Forsyth 842*37da2899SCharles.Forsyth 843*37da2899SCharles.Forsyth static long ResourceForkSize(FSSpec * spec)844*37da2899SCharles.Forsyth ResourceForkSize(FSSpec* spec) 845*37da2899SCharles.Forsyth { 846*37da2899SCharles.Forsyth long len; 847*37da2899SCharles.Forsyth short refNum; 848*37da2899SCharles.Forsyth OSErr e; 849*37da2899SCharles.Forsyth 850*37da2899SCharles.Forsyth 851*37da2899SCharles.Forsyth e = FSpOpenRF( spec, fsRdPerm, &refNum ); /* I.M. Files 2-155 */ 852*37da2899SCharles.Forsyth if ( e == noErr ) 853*37da2899SCharles.Forsyth { 854*37da2899SCharles.Forsyth e = GetEOF( refNum, &len ); 855*37da2899SCharles.Forsyth FSClose( refNum ); 856*37da2899SCharles.Forsyth } 857*37da2899SCharles.Forsyth 858*37da2899SCharles.Forsyth return ( e == noErr ) ? len : 0; 859*37da2899SCharles.Forsyth } 860*37da2899SCharles.Forsyth 861*37da2899SCharles.Forsyth 862*37da2899SCharles.Forsyth /*************************************************************************/ 863*37da2899SCharles.Forsyth /* */ 864*37da2899SCharles.Forsyth /* <Function> */ 865*37da2899SCharles.Forsyth /* FT_New_Face */ 866*37da2899SCharles.Forsyth /* */ 867*37da2899SCharles.Forsyth /* <Description> */ 868*37da2899SCharles.Forsyth /* This is the Mac-specific implementation of FT_New_Face. In */ 869*37da2899SCharles.Forsyth /* addition to the standard FT_New_Face() functionality, it also */ 870*37da2899SCharles.Forsyth /* accepts pathnames to Mac suitcase files. For further */ 871*37da2899SCharles.Forsyth /* documentation see the original FT_New_Face() in freetype.h. */ 872*37da2899SCharles.Forsyth /* */ 873*37da2899SCharles.Forsyth FT_EXPORT_DEF( FT_Error ) FT_New_Face(FT_Library library,const char * pathname,FT_Long face_index,FT_Face * aface)874*37da2899SCharles.Forsyth FT_New_Face( FT_Library library, 875*37da2899SCharles.Forsyth const char* pathname, 876*37da2899SCharles.Forsyth FT_Long face_index, 877*37da2899SCharles.Forsyth FT_Face *aface ) 878*37da2899SCharles.Forsyth { 879*37da2899SCharles.Forsyth FT_Open_Args args; 880*37da2899SCharles.Forsyth FSSpec spec; 881*37da2899SCharles.Forsyth OSType file_type; 882*37da2899SCharles.Forsyth 883*37da2899SCharles.Forsyth 884*37da2899SCharles.Forsyth /* test for valid `library' and `aface' delayed to FT_Open_Face() */ 885*37da2899SCharles.Forsyth if ( !pathname ) 886*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 887*37da2899SCharles.Forsyth 888*37da2899SCharles.Forsyth if ( file_spec_from_path( pathname, &spec ) ) 889*37da2899SCharles.Forsyth return FT_Err_Invalid_Argument; 890*37da2899SCharles.Forsyth 891*37da2899SCharles.Forsyth /* Regardless of type, don't try to use the resource fork if it is */ 892*37da2899SCharles.Forsyth /* empty. Some TTF fonts have type `FFIL', for example, but they */ 893*37da2899SCharles.Forsyth /* only have data forks. */ 894*37da2899SCharles.Forsyth 895*37da2899SCharles.Forsyth if ( ResourceForkSize( &spec ) != 0 ) 896*37da2899SCharles.Forsyth { 897*37da2899SCharles.Forsyth file_type = get_file_type( &spec ); 898*37da2899SCharles.Forsyth if ( file_type == 'FFIL' || file_type == 'tfil' ) 899*37da2899SCharles.Forsyth return FT_New_Face_From_Suitcase( library, &spec, face_index, aface ); 900*37da2899SCharles.Forsyth 901*37da2899SCharles.Forsyth if ( file_type == 'LWFN' ) 902*37da2899SCharles.Forsyth return FT_New_Face_From_LWFN( library, &spec, face_index, aface ); 903*37da2899SCharles.Forsyth } 904*37da2899SCharles.Forsyth 905*37da2899SCharles.Forsyth #if TARGET_API_MAC_CARBON 906*37da2899SCharles.Forsyth 907*37da2899SCharles.Forsyth if ( is_dfont( &spec ) ) 908*37da2899SCharles.Forsyth return FT_New_Face_From_dfont( library, &spec, face_index, aface ); 909*37da2899SCharles.Forsyth 910*37da2899SCharles.Forsyth #endif 911*37da2899SCharles.Forsyth 912*37da2899SCharles.Forsyth /* let it fall through to normal loader (.ttf, .otf, etc.) */ 913*37da2899SCharles.Forsyth args.flags = FT_OPEN_PATHNAME; 914*37da2899SCharles.Forsyth args.pathname = (char*)pathname; 915*37da2899SCharles.Forsyth return FT_Open_Face( library, &args, face_index, aface ); 916*37da2899SCharles.Forsyth } 917*37da2899SCharles.Forsyth 918*37da2899SCharles.Forsyth 919*37da2899SCharles.Forsyth /* END */ 920