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

📄 ftmac.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************/
/*                                                                         */
/*  ftmac.c                                                                */
/*                                                                         */
/*    Mac FOND support.  Written by just@letterror.com.                    */
/*  Heavily Fixed by mpsuzuki, George Williams and Sean McBride            */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 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: fbit and NFNT bitmap resources are not supported yet.  In old
    sfnt fonts, bitmap glyph data for each size is stored in each `NFNT'
    resources instead of the `bdat' table in the sfnt resource.  Therefore,
    face->num_fixed_sizes is set to 0, because bitmap data in `NFNT'
    resource is unavailable at present.

    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().

    - Some suitcase fonts (notably Onyx) might point the `LWFN' file to
      itself, even though it doesn't contains `POST' resources.  To handle
      this special case without opening the file an extra time, we just
      ignore errors from the `LWFN' and fallback to the `sfnt' if both are
      available.
  */


#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.                         */
#undef  OS_INLINE
#define OS_INLINE   static __inline__
#include <Carbon/Carbon.h>
#else
#include <Resources.h>
#include <Fonts.h>
#include <Endian.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

#undef FT_GetFile_From_Mac_Name
#undef FT_GetFile_From_Mac_ATS_Name
#undef FT_New_Face_From_FSSpec


  /* FSSpec functions are deprecated since Mac OS X 10.4 */
#ifndef HAVE_FSSPEC
#if TARGET_API_MAC_OS8 || TARGET_API_MAC_CARBON
#define HAVE_FSSPEC  1
#else
#define HAVE_FSSPEC  0
#endif
#endif

  /* most FSRef functions were introduced since Mac OS 9 */
#ifndef HAVE_FSREF
#if TARGET_API_MAC_OSX
#define HAVE_FSREF  1
#else
#define HAVE_FSREF  0
#endif
#endif

#ifndef HFS_MAXPATHLEN
#define HFS_MAXPATHLEN  1024
#endif


  /* QuickDraw is deprecated since Mac OS X 10.4 */
#ifndef HAVE_QUICKDRAW_CARBON
#if TARGET_API_MAC_OS8 || TARGET_API_MAC_CARBON
#define HAVE_QUICKDRAW_CARBON  1
#else
#define HAVE_QUICKDRAW_CARBON  0
#endif
#endif

  /* AppleTypeService is available since Mac OS X */
#ifndef HAVE_ATS
#if TARGET_API_MAC_OSX
#define HAVE_ATS  1
#else
#define HAVE_ATS  0
#endif
#endif

  /* 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 !HAVE_QUICKDRAW_CARBON  /* QuickDraw is deprecated since Mac OS X 10.4 */

  FT_EXPORT_DEF( FT_Error )
  FT_GetFile_From_Mac_Name( const char*  fontName,
                            FSSpec*      pathSpec,
                            FT_Long*     face_index )
  {
    return FT_Err_Unimplemented_Feature;
  }

#else

  FT_EXPORT_DEF( FT_Error )
  FT_GetFile_From_Mac_Name( const char*  fontName,
                            FSSpec*      pathSpec,
                            FT_Long*     face_index )
  {
    OptionBits            options = kFMUseGlobalScopeOption;

    FMFontFamilyIterator  famIter;
    OSStatus              status = FMCreateFontFamilyIterator( NULL, NULL,
                                                               options,
                                                               &famIter );
    FMFont                the_font = 0;
    FMFontFamily          family   = 0;


    *face_index = 0;
    while ( status == 0 && !the_font )
    {
      status = FMGetNextFontFamily( &famIter, &family );
      if ( status == 0 )
      {
        int                           stat2;
        FMFontFamilyInstanceIterator  instIter;
        Str255                        famNameStr;
        char                          famName[256];


        /* get the family name */
        FMGetFontFamilyName( family, famNameStr );
        CopyPascalStringToC( famNameStr, famName );

        /* iterate through the styles */
        FMCreateFontFamilyInstanceIterator( family, &instIter );

        *face_index = 0;
        stat2       = 0;

        while ( stat2 == 0 && !the_font )
        {
          FMFontStyle  style;
          FMFontSize   size;
          FMFont       font;


          stat2 = FMGetNextFontFamilyInstance( &instIter, &font,
                                               &style, &size );
          if ( stat2 == 0 && size == 0 )
          {
            char  fullName[256];


            /* build up a complete face name */
            ft_strcpy( fullName, famName );
            if ( style & bold )
              ft_strcat( fullName, " Bold" );
            if ( style & italic )
              ft_strcat( fullName, " Italic" );

            /* compare with the name we are looking for */
            if ( ft_strcmp( fullName, fontName ) == 0 )
            {
              /* found it! */
              the_font = font;
            }
            else
              ++(*face_index);
          }
        }

        FMDisposeFontFamilyInstanceIterator( &instIter );
      }
    }

    FMDisposeFontFamilyIterator( &famIter );

    if ( the_font )
    {
      FMGetFontContainer( the_font, pathSpec );
      return FT_Err_Ok;
    }
    else
      return FT_Err_Unknown_File_Format;
  }

#endif /* HAVE_QUICKDRAW_CARBON */


#if !HAVE_ATS

  FT_EXPORT_DEF( FT_Error )
  FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
                                FSSpec*      pathSpec,
                                FT_Long*     face_index )
  {
    return FT_Err_Unimplemented_Feature;
  }

#else

  FT_EXPORT_DEF( FT_Error )
  FT_GetFile_From_Mac_ATS_Name( const char*  fontName,
                                FSSpec*      pathSpec,
                                FT_Long*     face_index )
  {
    CFStringRef  cf_fontName;
    ATSFontRef   ats_font_id;


    *face_index = 0;

    cf_fontName = CFStringCreateWithCString( NULL, fontName,
                                             kCFStringEncodingMacRoman );
    ats_font_id = ATSFontFindFromName( cf_fontName,
                                       kATSOptionFlagsUnRestrictedScope );

    if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL )
      return FT_Err_Unknown_File_Format;

    if ( 0 != ATSFontGetFileSpecification( ats_font_id, pathSpec ) )
      return FT_Err_Unknown_File_Format;

    /* face_index calculation by searching preceding fontIDs */
    /* with same FSRef                                       */
    {
      int     i;
      FSSpec  f;


      for ( i = 1; i < ats_font_id; i++ )
      {
        if ( 0 != ATSFontGetFileSpecification( ats_font_id - i,
                                               &f               ) ||
             f.vRefNum != pathSpec->vRefNum                       ||
             f.parID   != pathSpec->parID                         ||
             f.name[0] != pathSpec->name[0]                       ||
             0 != ft_strncmp( (char *)f.name + 1,
                              (char *)pathSpec->name + 1,
                              f.name[0]                           ) )
          break;
      }
      *face_index = ( i - 1 );
    }
    return FT_Err_Ok;
  }

#endif /* HAVE_ATS */


#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO

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


  FT_CALLBACK_DEF( void )
  ft_FSp_stream_close( FT_Stream  stream )
  {
    ft_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 )
  {
    FT_FILE*  file;


    file = STREAM_FILE( stream );

    ft_fseek( file, offset, SEEK_SET );

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

#endif  /* __MWERKS__ && !TARGET_RT_MAC_MACHO */


#if HAVE_FSSPEC && !HAVE_FSREF

  static OSErr
  FT_FSPathMakeSpec( const UInt8*  pathname,
                     FSSpec*       spec_p,
                     Boolean       isDirectory )
  {
    const char  *p, *q;
    short       vRefNum;
    long        dirID;
    Str255      nodeName;
    OSErr       err;


    p = q = (const char *)pathname;
    dirID   = 0;
    vRefNum = 0;

    while ( 1 )
    {
      q = p + FT_MIN( 255, ft_strlen( p ) );

      if ( q == p )
        return 0;

      if ( 255 < ft_strlen( (char *)pathname ) )
      {
        while ( p < q && *q != ':' )
          q--;
      }

      if ( p < q )
        *(char *)nodeName = q - p;
      else if ( ft_strlen( p ) < 256 )
        *(char *)nodeName = ft_strlen( p );
      else
        return errFSNameTooLong;

      ft_strncpy( (char *)nodeName + 1, (char *)p, *(char *)nodeName );
      err = FSMakeFSSpec( vRefNum, dirID, nodeName, spec_p );
      if ( err || '\0' == *q )
        return err;

      vRefNum = spec_p->vRefNum;
      dirID   = spec_p->parID;

      p = q;
    }
  }


  static OSErr
  FT_FSpMakePath( const FSSpec*  spec_p,
                  UInt8*         path,
                  UInt32         maxPathSize )
  {
    OSErr   err;
    FSSpec  spec = *spec_p;
    short   vRefNum;
    long    dirID;
    Str255  parDir_name;


    FT_MEM_SET( path, 0, maxPathSize );
    while ( 1 )
    {
      int             child_namelen = ft_strlen( (char *)path );
      unsigned char   node_namelen  = spec.name[0];
      unsigned char*  node_name     = spec.name + 1;


      if ( node_namelen + child_namelen > maxPathSize )
        return errFSNameTooLong;

      FT_MEM_MOVE( path + node_namelen + 1, path, child_namelen );
      FT_MEM_COPY( path, node_name, node_namelen );
      if ( child_namelen > 0 )
        path[node_namelen] = ':';

      vRefNum        = spec.vRefNum;
      dirID          = spec.parID;
      parDir_name[0] = '\0';
      err = FSMakeFSSpec( vRefNum, dirID, parDir_name, &spec );
      if ( noErr != err || dirID == spec.parID )
        break;
    }
    return noErr;
  }

#endif /* HAVE_FSSPEC && !HAVE_FSREF */


  static OSErr
  FT_FSPathMakeRes( const UInt8*  pathname,
                    short*        res )
  {

#if HAVE_FSREF

    OSErr  err;
    FSRef  ref;


    if ( noErr != FSPathMakeRef( pathname, &ref, FALSE ) )
      return FT_Err_Cannot_Open_Resource;

    /* at present, no support for dfont format */
    err = FSOpenResourceFile( &ref, 0, NULL, fsRdPerm, res );
    if ( noErr == err )
      return err;

    /* fallback to original resource-fork font */
    *res = FSOpenResFile( &ref, fsRdPerm );
    err  = ResError();

#else

    OSErr   err;
    FSSpec  spec;


    if ( noErr != FT_FSPathMakeSpec( pathname, &spec, FALSE ) )
      return FT_Err_Cannot_Open_Resource;

    /* at present, no support for dfont format without FSRef */
    /* (see above), try original resource-fork font          */
    *res = FSpOpenResFile( &spec, fsRdPerm );
    err  = ResError();

#endif /* HAVE_FSREF */

    return err;
  }


  /* Return the file type for given pathname */
  static OSType
  get_file_type_from_path( const UInt8*  pathname )
  {

#if HAVE_FSREF

    FSRef          ref;
    FSCatalogInfo  info;


⌨️ 快捷键说明

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