⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftmac.c

📁 一个类似windows
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************/
/*                                                                         */
/*  ftmac.c                                                                */
/*                                                                         */
/*    Mac FOND support.  Written by just@letterror.com.                    */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2003, 2004 by                               */
/*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/***************************************************************************/


  /*
    Notes

    Mac suitcase files can (and often do!) contain multiple fonts.  To
    support this I use the face_index argument of FT_(Open|New)_Face()
    functions, and pretend the suitcase file is a collection.

    Warning: Although the FOND driver sets face->num_faces field to the
    number of available fonts, but the Type 1 driver sets it to 1 anyway.
    So this field is currently not reliable, and I don't see a clean way
    to  resolve that.  The face_index argument translates to

      Get1IndResource( 'FOND', face_index + 1 );

    so clients should figure out the resource index of the FOND.
    (I'll try to provide some example code for this at some point.)

    The Mac FOND support works roughly like this:

    - Check whether the offered stream points to a Mac suitcase file.
      This is done by checking the file type: it has to be 'FFIL' or 'tfil'.
      The stream that gets passed to our init_face() routine is a stdio
      stream, which isn't usable for us, since the FOND resources live
      in the resource fork.  So we just grab the stream->pathname field.

    - Read the FOND resource into memory, then check whether there is
      a TrueType font and/or(!) a Type 1 font available.

    - If there is a Type 1 font available (as a separate 'LWFN' file),
      read its data into memory, massage it slightly so it becomes
      PFB data, wrap it into a memory stream, load the Type 1 driver
      and delegate the rest of the work to it by calling FT_Open_Face().
      (XXX TODO: after this has been done, the kerning data from the FOND
      resource should be appended to the face: On the Mac there are usually
      no AFM files available.  However, this is tricky since we need to map
      Mac char codes to ps glyph names to glyph ID's...)

    - If there is a TrueType font (an 'sfnt' resource), read it into
      memory, wrap it into a memory stream, load the TrueType driver
      and delegate the rest of the work to it, by calling FT_Open_Face().
  */


#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_STREAM_H

#if defined( __GNUC__ ) || defined( __IBMC__ )
  /* This is for Mac OS X.  Without redefinition, OS_INLINE */
  /* expands to `static inline' which doesn't survive the   */
  /* -ansi compilation flag of GCC.                         */
#define OS_INLINE  static __inline__
#include <Carbon/Carbon.h>
#else
#include <Resources.h>
#include <Fonts.h>
#include <Errors.h>
#include <Files.h>
#include <TextUtils.h>
#endif

#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO
#include <FSp_fopen.h>
#endif

#include FT_MAC_H


  /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over
     TrueType in case *both* are available (this is not common,
     but it *is* possible). */
#ifndef PREFER_LWFN
#define PREFER_LWFN 1
#endif


#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO

#define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )


  FT_CALLBACK_DEF( void )
  ft_FSp_stream_close( FT_Stream  stream )
  {
    fclose( STREAM_FILE( stream ) );

    stream->descriptor.pointer = NULL;
    stream->size               = 0;
    stream->base               = 0;
  }


  FT_CALLBACK_DEF( unsigned long )
  ft_FSp_stream_io( FT_Stream       stream,
                    unsigned long   offset,
                    unsigned char*  buffer,
                    unsigned long   count )
  {
    FILE*  file;


    file = STREAM_FILE( stream );

    fseek( file, offset, SEEK_SET );

    return (unsigned long)fread( buffer, 1, count, file );
  }

#endif  /* __MWERKS__ && !TARGET_RT_MAC_MACHO */


  /* Given a pathname, fill in a file spec. */
  static int
  file_spec_from_path( const char*  pathname,
                       FSSpec*      spec )
  {

#if !TARGET_API_MAC_OS8 && \
    !( defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO )

    OSErr  e;
    FSRef  ref;


    e = FSPathMakeRef( (UInt8 *)pathname, &ref, false /* not a directory */ );
    if ( e == noErr )
      e = FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL, spec, NULL );

    return ( e == noErr ) ? 0 : (-1);

#else

    Str255    p_path;
    FT_ULong  path_len;


    /* convert path to a pascal string */
    path_len = ft_strlen( pathname );
    if ( path_len > 255 )
      return -1;
    p_path[0] = (unsigned char)path_len;
    ft_strncpy( (char*)p_path + 1, pathname, path_len );

    if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr )
      return -1;
    else
      return 0;

#endif

  }


  /* Return the file type of the file specified by spec. */
  static OSType
  get_file_type( const FSSpec*  spec )
  {
    FInfo  finfo;


    if ( FSpGetFInfo( spec, &finfo ) != noErr )
      return 0;  /* file might not exist */

    return finfo.fdType;
  }


  /* Given a PostScript font name, create the Macintosh LWFN file name. */
  static void
  create_lwfn_name( char*   ps_name,
                    Str255  lwfn_file_name )
  {
    int       max = 5, count = 0;
    FT_Byte*  p = lwfn_file_name;
    FT_Byte*  q = (FT_Byte*)ps_name;


    lwfn_file_name[0] = 0;

    while ( *q )
    {
      if ( ft_isupper( *q ) )
      {
        if ( count )
          max = 3;
        count = 0;
      }
      if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) )
      {
        *++p = *q;
        lwfn_file_name[0]++;
        count++;
      }
      q++;
    }
  }


  /* Given a file reference, answer its location as a vRefNum
     and a dirID. */
  static FT_Error
  get_file_location( short           ref_num,
                     short*          v_ref_num,
                     long*           dir_id,
                     unsigned char*  file_name )
  {
    FCBPBRec  pb;
    OSErr     error;


    pb.ioNamePtr = file_name;
    pb.ioVRefNum = 0;
    pb.ioRefNum  = ref_num;
    pb.ioFCBIndx = 0;

    error = PBGetFCBInfoSync( &pb );
    if ( error == noErr )
    {
      *v_ref_num = pb.ioFCBVRefNum;
      *dir_id    = pb.ioFCBParID;
    }
    return error;
  }


  /* Make a file spec for an LWFN file from a FOND resource and
     a file name. */
  static FT_Error
  make_lwfn_spec( Handle               fond,
                  const unsigned char* file_name,
                  FSSpec*              spec )
  {
    FT_Error  error;
    short     ref_num, v_ref_num;
    long      dir_id;
    Str255    fond_file_name;


    ref_num = HomeResFile( fond );

    error = ResError();
    if ( !error )
      error = get_file_location( ref_num, &v_ref_num,
                                 &dir_id, fond_file_name );
    if ( !error )
      error = FSMakeFSSpec( v_ref_num, dir_id, file_name, spec );

    return error;
  }


  static short
  count_faces_sfnt( char *fond_data )
  {
    /* The count is 1 greater than the value in the FOND.  */
    /* Isn't that cute? :-)                                */

    return 1 + *( (short *)( fond_data + sizeof ( FamRec ) ) );
  }


  /* Look inside the FOND data, answer whether there should be an SFNT
     resource, and answer the name of a possible LWFN Type 1 file.

     Thanks to Paul Miller (paulm@profoundeffects.com) for the fix
     to load a face OTHER than the first one in the FOND!
  */


  static void
  parse_fond( char*   fond_data,
              short*  have_sfnt,
              short*  sfnt_id,
              Str255  lwfn_file_name,
              short   face_index )
  {
    AsscEntry*  assoc;
    AsscEntry*  base_assoc;
    FamRec*     fond;


    *sfnt_id          = 0;
    *have_sfnt        = 0;
    lwfn_file_name[0] = 0;

    fond       = (FamRec*)fond_data;
    assoc      = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 );
    base_assoc = assoc;

    /* Let's do a little range checking before we get too excited here */
    if ( face_index < count_faces_sfnt( fond_data ) )
    {
      assoc += face_index;        /* add on the face_index! */

      /* if the face at this index is not scalable,
         fall back to the first one (old behavior) */
      if ( assoc->fontSize == 0 )
      {
        *have_sfnt = 1;
        *sfnt_id   = assoc->fontID;
      }
      else if ( base_assoc->fontSize == 0 )
      {
        *have_sfnt = 1;
        *sfnt_id   = base_assoc->fontID;
      }
    }

    if ( fond->ffStylOff )
    {
      unsigned char*  p = (unsigned char*)fond_data;
      StyleTable*     style;
      unsigned short  string_count;
      char            ps_name[256];
      unsigned char*  names[64];
      int             i;


      p += fond->ffStylOff;
      style = (StyleTable*)p;
      p += sizeof ( StyleTable );
      string_count = *(unsigned short*)(p);
      p += sizeof ( short );

      for ( i = 0 ; i < string_count && i < 64; i++ )
      {
        names[i] = p;
        p += names[i][0];
        p++;
      }

      {
        size_t  ps_name_len = (size_t)names[0][0];


        if ( ps_name_len != 0 )
        {
          ft_memcpy(ps_name, names[0] + 1, ps_name_len);
          ps_name[ps_name_len] = 0;
        }
        if ( style->indexes[0] > 1 )
        {
          unsigned char*  suffixes = names[style->indexes[0] - 1];


          for ( i = 1; i <= suffixes[0]; i++ )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -