Beispiel #1
0
  static FT_Error
  tt_glyph_load( FT_GlyphSlot  ttslot,      /* TT_GlyphSlot */
                 FT_Size       ttsize,      /* TT_Size      */
                 FT_UInt       glyph_index,
                 FT_Int32      load_flags )
  {
    TT_GlyphSlot  slot = (TT_GlyphSlot)ttslot;
    TT_Size       size = (TT_Size)ttsize;
    FT_Face       face = ttslot->face;
    FT_Error      error;


    if ( !slot )
      return FT_THROW( Invalid_Slot_Handle );

    if ( !size )
      return FT_THROW( Invalid_Size_Handle );

    if ( !face )
      return FT_THROW( Invalid_Argument );

#ifdef FT_CONFIG_OPTION_INCREMENTAL
    if ( glyph_index >= (FT_UInt)face->num_glyphs &&
         !face->internal->incremental_interface   )
#else
    if ( glyph_index >= (FT_UInt)face->num_glyphs )
#endif
      return FT_THROW( Invalid_Argument );

    if ( load_flags & FT_LOAD_NO_HINTING )
    {
      /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT   */
      /* are necessary to disable hinting for tricky fonts */

      if ( FT_IS_TRICKY( face ) )
        load_flags &= ~FT_LOAD_NO_HINTING;

      if ( load_flags & FT_LOAD_NO_AUTOHINT )
        load_flags |= FT_LOAD_NO_HINTING;
    }

    if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) )
    {
      load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE;

      if ( !FT_IS_TRICKY( face ) )
        load_flags |= FT_LOAD_NO_HINTING;
    }

    /* now load the glyph outline if necessary */
    error = TT_Load_Glyph( size, slot, glyph_index, load_flags );

    /* force drop-out mode to 2 - irrelevant now */
    /* slot->outline.dropout_mode = 2; */

    return error;
  }
Beispiel #2
0
  static FT_Error
  Load_Glyph( FT_GlyphSlot  ttslot,         /* TT_GlyphSlot */
              FT_Size       ttsize,         /* TT_Size      */
              FT_UInt       glyph_index,
              FT_Int32      load_flags )
  {
    TT_GlyphSlot  slot = (TT_GlyphSlot)ttslot;
    TT_Size       size = (TT_Size)ttsize;
    FT_Error      error;


    if ( !slot )
      return TT_Err_Invalid_Slot_Handle;

    /* check whether we want a scaled outline or bitmap */
    if ( !size )
      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;

    if ( load_flags & FT_LOAD_NO_SCALE )
      size = NULL;

    /* reset the size object if necessary */
    if ( size )
    {
      /* these two object must have the same parent */
      if ( size->root.face != slot->face )
        return TT_Err_Invalid_Face_Handle;

      if ( !size->ttmetrics.valid )
      {
        if ( FT_SET_ERROR( tt_size_reset( size ) ) )
          return error;
      }
    }

    /* now load the glyph outline if necessary */
    error = TT_Load_Glyph( size, slot, glyph_index, load_flags );

    /* force drop-out mode to 2 - irrelevant now */
    /* slot->outline.dropout_mode = 2; */

    return error;
  }
Beispiel #3
0
SWFFont loadSWFFontfromTTF(char *filename)
{
  int i;

  TT_Engine *engine;
  TT_Face face;
  TT_Instance instance;
  TT_Glyph glyph;
  TT_Glyph_Metrics metrics;
  TT_Outline outline;
  TT_CharMap charmap;
  TT_Face_Properties properties;
  TT_UShort pid, eid;

  TT_Init_FreeType(engine);

  error = TT_Open_Face(engine, filename, &face);

  if(error)
    fprintf(stderr, "Could not open face.\n");

  TT_Get_Face_Properties(face, &properties);

  for(i=0; i<properties->num_CharMaps; ++i)
    TT_Get_CharMap_ID(face, i, &pid, &eid);

  TT_Get_CharMap(face, charmapIndex, &charmap);

  TT_New_Instance(face, &instance);

  TT_New_Glyph(face, &glyph);

  for(i=0; i<whatever; ++i)
  {
    TT_Load_Glyph(instance, glyph, TT_Char_Index(charmap, i), loadFlags);

    TT_Get_Glyph_Outline(glyph, &outline);

    TT_Get_Glyph_Metrics(glyph, &metrics);
  }

  TT_Done_FreeType(engine);
}
Beispiel #4
0
  TT_Error  LoadTrueTypeChar( int  idx )
  {
    error = TT_Load_Glyph( instance, glyph, idx, TTLOAD_DEFAULT );
    if ( error )
      return error;

    TT_Get_Glyph_Outline( glyph, &outline );

    outline.second_pass    = 0;
    outline.high_precision = 0;
    outline.dropout_mode   = 0;

    /* debugging */
#if 0
    if ( idx == 0 && !visual )
    {
      printf( "points = %d\n", outline.points );
      for ( j = 0; j < outline.points; j++ )
        printf( "%02x  (%01hx,%01hx)\n",
                 j, outline.xCoord[j], outline.yCoord[j] );
      printf( "\n" );
    }
#endif

    /* create a new outline */
    TT_New_Outline( outline.n_points,
                    outline.n_contours,
                    &outlines[cur_glyph] );

    /* copy the glyph outline into it */
    outline.high_precision = 0;
    outline.second_pass    = 0;
    TT_Copy_Outline( &outline, &outlines[cur_glyph] );

    /* translate it */
    TT_Translate_Outline( &outlines[cur_glyph],
                          vio_Width * 16,
                          vio_Height * 16 );
    cur_glyph++;

    return TT_Err_Ok;
  }
Beispiel #5
0
static TT_Error
LoadTrueTypeChar(Font *fnt,
                 int idx,
                 Boolean hint,
                 Boolean quiet)
{
  TT_Error error;
  int flags;


  flags = TTLOAD_SCALE_GLYPH;
  if (hint)
    flags |= TTLOAD_HINT_GLYPH;

  error = TT_Load_Glyph(instance, glyph, idx, flags);
  if (!error)
    error = TT_Get_Glyph_Big_Metrics(glyph, &metrics);
  if (!error)
    error = TT_Get_Glyph_Outline(glyph, &outline);
  if (!error)
  {
    if (fnt->efactor != 1.0 || fnt->slant != 0.0 )
      TT_Transform_Outline(&outline, &matrix1);
    if (fnt->rotate)
      TT_Transform_Outline(&outline, &matrix2);
  }
  if (!error)
    error = TT_Get_Outline_BBox(&outline, &bbox); /* we need the non-
                                                     grid-fitted bbox */
  if (fnt->rotate)
    TT_Translate_Outline(&outline,
                         metrics.vertBearingY - bbox.xMin,
                         -fnt->y_offset * ppem * 64);
  if (!error)
    error = TT_Get_Outline_BBox(&outline, &bbox);
  if (!error)
    SetRasterArea(quiet);
  return error;
}
Beispiel #6
0
  static FT_Error
  Load_Glyph( FT_GlyphSlot  ttslot,         /* TT_GlyphSlot */
              FT_Size       ttsize,         /* TT_Size      */
              FT_UInt       glyph_index,
              FT_Int32      load_flags )
  {
    TT_GlyphSlot  slot = (TT_GlyphSlot)ttslot;
    TT_Size       size = (TT_Size)ttsize;
    FT_Face       face = ttslot->face;
    FT_Error      error;


    if ( !slot )
      return TT_Err_Invalid_Slot_Handle;

    if ( !size )
      return TT_Err_Invalid_Size_Handle;

    if ( !face || glyph_index >= (FT_UInt)face->num_glyphs )
      return TT_Err_Invalid_Argument;

    if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) )
    {
      load_flags |= FT_LOAD_NO_HINTING |
                    FT_LOAD_NO_BITMAP  |
                    FT_LOAD_NO_SCALE;
    }

    /* now load the glyph outline if necessary */
    error = TT_Load_Glyph( size, slot, glyph_index, load_flags );

    /* force drop-out mode to 2 - irrelevant now */
    /* slot->outline.dropout_mode = 2; */

    return error;
  }
Beispiel #7
0
static TT_Error Load_Glyph(TTF_Font *font, Uint16 ch, struct glyph *glyph)
{
	TT_UShort index;
	TT_Glyph_Metrics metrics;
	TT_Outline outline;
	int x_offset;
	int y_offset;
	TT_Error error;

	/* Load the glyph */
	index = TT_Char_Index(font->map, UNICODE(ch));
	error = TT_Load_Glyph(font->inst, font->glyph, index, TTLOAD_DEFAULT);
	if ( error ) return error;

	/* Get the bounding box */
	TT_Get_Glyph_Metrics(font->glyph, &metrics);
	glyph->minx = (metrics.bbox.xMin & -64) / 64;
	glyph->maxx = ((metrics.bbox.xMax + 63) & -64) / 64;
	glyph->miny = (metrics.bbox.yMin & -64) / 64;
	glyph->maxy = ((metrics.bbox.yMax + 63) & -64) / 64;
	glyph->advance = (metrics.advance & -64) / 64;

	/* Adjust for bold and italic text */
	if ( font->style & TTF_STYLE_BOLD ) {
		glyph->maxx += font->glyph_overhang;
	}
	if ( font->style & TTF_STYLE_ITALIC ) {
		glyph->maxx += round(font->glyph_italics);
	}

	/* Get the bitmap memory */
	glyph->bitmap.width = ((glyph->maxx - glyph->minx) + 7) & ~7;
	glyph->bitmap.rows = font->height;
	glyph->bitmap.cols = glyph->bitmap.width/8;
	glyph->bitmap.flow = TT_Flow_Down;
	glyph->bitmap.size = (glyph->bitmap.rows * glyph->bitmap.cols);
	if ( glyph->bitmap.size ) {
		glyph->bitmap.bitmap = malloc(glyph->bitmap.size);
		if ( ! glyph->bitmap.bitmap ) {
			error = TT_Err_Out_Of_Memory;
			goto was_error;
		}
		memset(glyph->bitmap.bitmap, 0, glyph->bitmap.size);
	} else {
		glyph->bitmap.bitmap = 0;
	}

	/* Get the pixmap memory */
	glyph->pixmap.width = ((glyph->maxx - glyph->minx) + 3) & ~3;
	glyph->pixmap.rows = font->height;
	glyph->pixmap.cols = glyph->pixmap.width;
	glyph->pixmap.flow = TT_Flow_Down;
	glyph->pixmap.size = (glyph->pixmap.rows * glyph->pixmap.cols);
	if ( glyph->pixmap.size ) {
		glyph->pixmap.bitmap = malloc(glyph->pixmap.size);
		if ( ! glyph->pixmap.bitmap ) {
			error = TT_Err_Out_Of_Memory;
			goto was_error;
		}
		memset(glyph->pixmap.bitmap, 0, glyph->pixmap.size);
	} else {
		glyph->pixmap.bitmap = 0;
	}

	/* Render the glyph into the bitmap and pixmap */
	error = TT_Get_Glyph_Outline(font->glyph, &outline);
	/* Handle the italic style */
	if ( font->style & TTF_STYLE_ITALIC ) {
		TT_Matrix shear;

		shear.xx = 1<<16;
		shear.xy = (int)(font->glyph_italics*(1<<16))/font->height;
		shear.yx = 0;
		shear.yy = 1<<16;
		TT_Transform_Outline(&outline, &shear);
	}
	x_offset = -glyph->minx * 64;
	y_offset = -round(font->descent) * 64;
	TT_Translate_Outline(&outline, x_offset, y_offset);
	error += TT_Get_Outline_Bitmap(engine, &outline, &glyph->bitmap);
	error += TT_Get_Outline_Pixmap(engine, &outline, &glyph->pixmap);
	/* Handle the bold style */
	if ( font->style & TTF_STYLE_BOLD ) {
		int row, col;
		int offset;
		int pixel;
		Uint8 *pixmap;

		/* The bitmap is easy, just render another copy */
		for ( offset=0; offset < font->glyph_overhang; ++offset ) {
			TT_Translate_Outline(&outline, 64, 0);
			error += TT_Get_Outline_Bitmap(engine,
			                               &outline,&glyph->bitmap);
		}
		x_offset += font->glyph_overhang*64;

		/* The pixmap is a little harder, we have to add and clamp */
		for ( row=glyph->pixmap.rows-1; row >= 0; --row ) {
			pixmap = (Uint8 *)glyph->pixmap.bitmap +
			                  row*glyph->pixmap.cols;
			for (offset=1; offset<=font->glyph_overhang; ++offset) {
				for (col=glyph->pixmap.cols-1; col > 0; --col) {
					pixel=(pixmap[col]+pixmap[col-1]);
					if ( pixel > 4 ) {
						pixel = 4;
					}
					pixmap[col] = (Uint8)pixel;
				}
			}
		}
	}
	TT_Translate_Outline(&outline, -x_offset, -y_offset);
was_error:
	if ( error ) {
		if ( glyph->bitmap.bitmap ) {
			free(glyph->bitmap.bitmap);
			glyph->bitmap.bitmap = 0;
		}
		if ( glyph->pixmap.bitmap ) {
			free(glyph->pixmap.bitmap);
			glyph->pixmap.bitmap = 0;
		}
		return error;
	}

	/* We're done, mark this glyph cached */
	glyph->cached = ch;
	return TT_Err_Ok;
}
Beispiel #8
0
  int
  main( int  argc, char**  argv )
  {
    int    i, orig_ptsize, file;
    char   filename[128 + 4];
    char   alt_filename[128 + 4];
    char*  execname;
    int    option;

    int    ptsize;
    int    num_Faces = 0;
    int    glyph_index = 0;
    int    load_flags = TTLOAD_DEFAULT;

    int    force_sbit = 0;

    TT_Engine    engine;

    TT_Face      face;
    TT_Instance  instance;
    TT_Glyph     glyph;

    TT_Raster_Map  map;

    TT_Big_Glyph_Metrics  metrics;
    TT_Face_Properties    properties;
    TT_Instance_Metrics   imetrics;

    TT_EBLC         eblc;
    TT_SBit_Image*  bitmap = NULL;

    TT_Error  error;


    int res = 72;

#ifdef HAVE_LIBINTL_H
    setlocale( LC_ALL, "" );
    bindtextdomain( "freetype", LOCALEDIR );
    textdomain( "freetype" );
#endif

    execname = ft_basename( argv[0] );

    while ( 1 )
    {
      option = ft_getopt( argc, argv, "c:r:i:B" );

      if ( option == -1 )
        break;

      switch ( option )
      {
      case 'r':
        res = atoi( ft_optarg );
        if ( res < 1 )
          usage( execname );
        break;

      case 'c':
        num_Faces = atoi( ft_optarg );
        if ( num_Faces < 0 )
          usage( execname );
        break;

      case 'i':
        glyph_index = atoi( ft_optarg );
        if ( glyph_index < 0 )
          usage( execname );
        break;

      case 'B':
        force_sbit = 1;
        break;

      default:
        usage( execname );
        break;
      }
    }

    argc -= ft_optind;
    argv += ft_optind;

    if ( argc <= 1 )
      usage( execname );

    if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 )
      orig_ptsize = 64;

    file = 1;

    ptsize = orig_ptsize;

    i = strlen( argv[file] );
    while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' )
    {
      if ( argv[file][i] == '.' )
        i = 0;
        i--;
    }

    filename[128] = '\0';
    alt_filename[128] = '\0';

    strncpy( filename, argv[file], 128 );
    strncpy( alt_filename, argv[file], 128 );

    if ( i >= 0 )
    {
      strncpy( filename + strlen( filename ), ".ttf", 4 );
      strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
    }

    /* Initialize engine */

    error = TT_Init_FreeType( &engine );
    if ( error )
    {
      fprintf( stderr, gettext( "Error while initializing engine.\n" ) );
      goto Failure;
    }

    error = TT_Init_SBit_Extension( engine );
    if ( error )
    {
      fprintf( stderr, gettext(
               "Error while initializing embedded bitmap extension.\n" ) );
      goto Failure;
    }

    /* Load face */

    error = TT_Open_Face( engine, filename, &face );

    if ( error == TT_Err_Could_Not_Open_File )
    {
      strcpy( filename, alt_filename );
      error = TT_Open_Face( engine, alt_filename, &face );
    }

    if ( error == TT_Err_Could_Not_Open_File )
      Panic( gettext( "Could not find or open %s.\n" ), filename );
    if ( error )
    {
      fprintf( stderr, gettext( "Error while opening %s.\n" ),
               filename );
      goto Failure;
    }

    TT_Get_Face_Properties( face, &properties );

    printf( gettext( "There are %d fonts in this collection.\n" ),
            (int)(properties.num_Faces) );

    if ( num_Faces >= properties.num_Faces )
      Panic( gettext(
             "There is no collection with index %d in this font file.\n" ),
             num_Faces );

    TT_Close_Face( face );

    error = TT_Open_Collection( engine, filename, num_Faces, &face );

    /* get face properties and eblc */

    TT_Get_Face_Properties( face, &properties );
    if ( force_sbit )
    {
      error = TT_Get_Face_Bitmaps( face, &eblc );
      if ( error == TT_Err_Table_Missing )
        Panic( gettext( "There is no embedded bitmap data in the font.\n" ) );
      if ( error )
      {
        fprintf( stderr, gettext(
                 "Error while retrieving embedded bitmaps table.\n" ) );
        goto Failure;
      }
    }

    /* create glyph */

    error = TT_New_Glyph( face, &glyph );
    if ( error )
    {
      fprintf( stderr, gettext( "Could not create glyph container.\n" ) );
      goto Failure;
    }

    /* create instance */

    error = TT_New_Instance( face, &instance );
    if ( error )
    {
      fprintf( stderr, gettext( "Could not create instance.\n" ) );
      goto Failure;
    }

    error = TT_Set_Instance_Resolutions( instance, res, res );
    if ( error )
    {
      fprintf( stderr, gettext( "Could not set device resolutions.\n" ) );
      goto Failure;
    }

    error = TT_Set_Instance_CharSize( instance, ptsize*64 );
    if ( error )
    {
      fprintf( stderr, gettext( "Could not reset instance.\n" ) );
      goto Failure;
    }

    TT_Get_Instance_Metrics( instance, &imetrics );

    printf( gettext( "Instance metrics: ppemX %d, ppemY %d\n" ),
            imetrics.x_ppem,
            imetrics.y_ppem );

    if ( force_sbit )
    {
      error = TT_New_SBit_Image( &bitmap );
      if ( error )
      {
        fprintf( stderr, gettext(
                 "Could not allocate glyph bitmap container.\n" ) );
        goto Failure;
      }

      error = TT_Load_Glyph_Bitmap( face, instance, glyph_index, bitmap );
      if ( error )
      {
        fprintf( stderr, gettext(
                 "Can't load bitmap for glyph %d.\n" ), glyph_index );
        goto Failure;
      }

      Show_Metrics( bitmap->metrics, "SBit's metrics" );

      printf( "SBit glyph:\n" );
      Show_Single_Glyph( &bitmap->map );
    }
    else
    {
      TT_Load_Glyph( instance, glyph, glyph_index, load_flags );
      TT_Get_Glyph_Big_Metrics( glyph, &metrics );

      map.width = ( metrics.bbox.xMax - metrics.bbox.xMin ) / 64;
      map.rows = ( metrics.bbox.yMax - metrics.bbox.yMin ) / 64;
      map.cols = ( map.width + 7 ) / 8;
      map.size = map.cols * map.rows;
      map.bitmap = malloc( map.size );
      map.flow = TT_Flow_Down;

      memset( map.bitmap, 0, map.size );

      error = TT_Get_Glyph_Bitmap( glyph, &map,
                                   -metrics.bbox.xMin,
                                   -metrics.bbox.yMin );

      Show_Metrics( metrics, gettext( "Outline's metrics" ) );

      printf( gettext( "Outline glyph\n" ) );
      Show_Single_Glyph( &map );
    }

    free( map.bitmap );

    if ( bitmap )
      TT_Done_SBit_Image( bitmap );

    TT_Done_Instance( instance );
    TT_Done_Glyph( glyph );
    TT_Done_FreeType( engine );

    exit( EXIT_SUCCESS );      /* for safety reasons */

    return 0;       /* never reached */

  Failure:
    fprintf( stderr, "  " );
    fprintf( stderr, gettext( "FreeType error message: %s\n" ),
             TT_ErrToString18( error ) );

    exit( EXIT_FAILURE );

    return 0;       /* never reached */
  }
Beispiel #9
0
void
readttf(Font *fnt, Boolean quiet, Boolean only_range)
{
  TT_Error error;
  ttfinfo *ti, *Ti;
  long Num, index;
  unsigned int i, j;
  long k, max_k;
  unsigned short num_cmap;
  unsigned short cmap_plat, cmap_enc;
  int index_array[257];

  static Boolean initialized = False;

  TT_UShort in_string[2];
  TTO_GSUB_String in, out;

  TT_UShort script_index, language_index, feature_index;
  TT_UShort req_feature_index = 0xFFFF;


  /*
   *   We allocate a placeholder boundary and the `.notdef' character.
   */

  if (!only_range)
  {
    ti = newchar(fnt);
    ti->charcode = -1;
    ti->adobename = ".notdef";

    ti = newchar(fnt);
    ti->charcode = -1;
    ti->adobename = "||"; /* boundary character name */
  }

  /*
   *   Initialize FreeType engine.
   */

  if (!initialized)
  {
    if ((error = TT_Init_FreeType(&engine)))
      oops("Cannot initialize engine (error code = 0x%x).", error);

    if ((error = TT_Init_Kerning_Extension(engine)))
      oops("Cannot initialize kerning (error code = 0x%x).", error);

    if (fnt->PSnames)
      if ((error = TT_Init_Post_Extension(engine)))
        oops("Cannot initialize PS name support (error code = 0x%x).", error);

    if (fnt->rotate)
      if ((error = TT_Init_GSUB_Extension(engine)))
        oops("Cannot initialize GSUB support (error code = 0x%x).", error);

    /*
     *   Load face.
     */

    real_ttfname = TeX_search_ttf_file(&(fnt->ttfname));
    if (!real_ttfname)
      oops("Cannot find `%s'.", fnt->ttfname);

    if ((error = TT_Open_Face(engine, real_ttfname, &face)))
      oops("Cannot open `%s'.", real_ttfname);

    /*
     *   Get face properties and allocate preload arrays.
     */

    TT_Get_Face_Properties(face, &properties);

    /*
     *   Now we try to open the proper font in a collection.
     */

    if (fnt->fontindex != 0)
    {
      if (properties.num_Faces == 1)
      {
        warning("This isn't a TrueType collection.\n"
                "Parameter `-f' is ignored.");
        fnt->fontindex = 0;
        fnt->fontindexparam = NULL;
      }
      else
      {
        TT_Close_Face(face);
        if ((error = TT_Open_Collection(engine, real_ttfname,
                                        fnt->fontindex, &face)))
          oops("Cannot open font %lu in TrueType Collection `%s'.",
               fnt->fontindex, real_ttfname);
      }
    }

    /*
     *   Create instance.
     */

    if ((error = TT_New_Instance(face, &instance)))
      oops("Cannot create instance for `%s' (error code = 0x%x).",
           real_ttfname, error);

    /*
     *   We use a dummy glyph size of 10pt.
     */

    if ((error = TT_Set_Instance_CharSize(instance, 10 * 64)))
      oops("Cannot set character size (error code = 0x%x).", error);

    matrix1.xx = (TT_Fixed)(floor(fnt->efactor * 1024) * (1L<<16)/1024);
    matrix1.xy = (TT_Fixed)(floor(fnt->slant * 1024) * (1L<<16)/1024);
    matrix1.yx = (TT_Fixed)0;
    matrix1.yy = (TT_Fixed)(1L<<16);

    if (fnt->rotate)
    {
      matrix2.xx = 0;
      matrix2.yx = 1L << 16;
      matrix2.xy = -matrix2.yx;
      matrix2.yy = matrix2.xx;
    }

    if ((error = TT_Set_Instance_Transform_Flags(
                   instance,
                   fnt->rotate ? 1 : 0,
                   fnt->efactor != 1.0 ? 1 : 0)))
      oops("Cannot set transform flags (error code = 0x%x).", error);

    /*
     *   Create glyph container.
     */

    if ((error = TT_New_Glyph(face, &glyph)))
      oops("Cannot create glyph container (error code = 0x%x).", error);

    fnt->units_per_em = properties.header->Units_Per_EM;
    fnt->fixedpitch = properties.postscript->isFixedPitch;
    fnt->italicangle = properties.postscript->italicAngle / 65536.0;

    if (fnt->PSnames != Only)
    {
      num_cmap = properties.num_CharMaps;
      for (i = 0; i < num_cmap; i++)
      {
        if ((error = TT_Get_CharMap_ID(face, i, &cmap_plat, &cmap_enc)))
          oops("Cannot query cmap (error code = 0x%x).", error);
        if (cmap_plat == fnt->pid && cmap_enc == fnt->eid)
          break;
      }
      if (i == num_cmap)
      {
        fprintf(stderr, "%s: ERROR: Invalid platform and/or encoding ID.\n",
                progname);
        if (num_cmap == 1)
          fprintf(stderr, "  The only valid PID/EID pair is");
        else
          fprintf(stderr, "  Valid PID/EID pairs are:\n");
        for (i = 0; i < num_cmap; i++)
        {
          TT_Get_CharMap_ID(face, i, &cmap_plat, &cmap_enc);
          fprintf(stderr, "    (%i,%i)\n", cmap_plat, cmap_enc);
        }
        fprintf(stderr, "\n");
        exit(1);
      }

      if ((error = TT_Get_CharMap(face, i, &char_map)))
        oops("Cannot load cmap (error code = 0x%x).", error);
    }

    if (fnt->PSnames)
    {
      if ((error = TT_Load_PS_Names(face, &post)))
        oops("Cannot load TrueType PS names (error code = 0x%x).", error);
    }
    else if (cmap_plat == Microsoft_platform &&
             cmap_enc == Microsoft_Unicode_encoding)
      set_encoding_scheme(encUnicode, fnt);
    else if (cmap_plat == Macintosh_platform &&
             cmap_enc == Macintosh_encoding)
      set_encoding_scheme(encMac, fnt);
    else
      set_encoding_scheme(encFontSpecific, fnt);

    if (fnt->rotate)
    {
      gsub = &gsub_;

      error = TT_Load_GSUB_Table(face, gsub, NULL);
      if (!error)
        has_gsub = True;
      else if (error != TT_Err_Table_Missing)
        warning("Cannot load GSUB table (error code = 0x%x).", error);
      else
        warning("No GSUB data available "
                "for vertical glyph presentation forms.");

      /* we check for the `vert' feature in Chinese, Japanese, and Korean */

      error = TT_GSUB_Select_Script(gsub,
                                    SCRIPT_kana,
                                    &script_index);
      if (error)
        goto check_hani;
      error = TT_GSUB_Select_Feature(gsub,
                                     FEATURE_vert,
                                     script_index,
                                     0xFFFF,
                                     &feature_index);
      if (error)
      {
        error = TT_GSUB_Select_Language(gsub,
                                        LANGUAGE_JAN,
                                        script_index,
                                        &language_index,
                                        &req_feature_index);
        if (error)
          goto check_hani;
        error = TT_GSUB_Select_Feature(gsub,
                                       FEATURE_vert,
                                       script_index,
                                       language_index,
                                       &feature_index);
        if (error)
          goto check_hani;
        else
          goto Done;
      }
      else
        goto Done;

    check_hani:
      error = TT_GSUB_Select_Script(gsub,
                                    SCRIPT_hani,
                                    &script_index);
      if (error)
        goto check_hang;
      error = TT_GSUB_Select_Feature(gsub,
                                     FEATURE_vert,
                                     script_index,
                                     0xFFFF,
                                     &feature_index);
      if (error)
      {
        error = TT_GSUB_Select_Language(gsub,
                                        LANGUAGE_CHN,
                                        script_index,
                                        &language_index,
                                        &req_feature_index);
        if (error)
          goto check_hang;
        error = TT_GSUB_Select_Feature(gsub,
                                       FEATURE_vert,
                                       script_index,
                                       language_index,
                                       &feature_index);
        if (error)
          goto check_hang;
        else
          goto Done;
      }
      else
        goto Done;

    check_hang:
      error = TT_GSUB_Select_Script(gsub,
                                    SCRIPT_hang,
                                    &script_index);
      if (error)
        goto Done;
      error = TT_GSUB_Select_Feature(gsub,
                                     FEATURE_vert,
                                     script_index,
                                     0xFFFF,
                                     &feature_index);
      if (error)
      {
        error = TT_GSUB_Select_Language(gsub,
                                        LANGUAGE_KOR,
                                        script_index,
                                        &language_index,
                                        &req_feature_index);
        if (error)
          goto Done;
        error = TT_GSUB_Select_Feature(gsub,
                                       FEATURE_vert,
                                       script_index,
                                       language_index,
                                       &feature_index);
      }

    Done:
      if (error)
      {
        warning("There is no data for vertical typesetting in GSUB table.");
        has_gsub = False;
      }

      if (req_feature_index != 0xFFFF)
        TT_GSUB_Add_Feature(gsub, req_feature_index, ALL_GLYPHS);
      TT_GSUB_Add_Feature(gsub, feature_index, ALL_GLYPHS);

      in.length = 1;
      in.pos = 0;
      in.string = in_string;
      in.properties = NULL;

      out.pos = 0;
      out.allocated = 0;
      out.string = NULL;
      out.properties = NULL;
    }

    initialized = True;
  }

  if (!quiet)
  {
    if (only_range)
      printf("\n\n%s:\n", fnt->fullname);
    printf("\n");
    printf("Glyph  Code   Glyph Name                ");
    printf("Width  llx    lly      urx    ury\n");
    printf("---------------------------------------");
    printf("---------------------------------\n");
  }

  /*
   *   We load only glyphs with a valid cmap entry.  Nevertheless, for
   *   the default mapping, we use the first 256 glyphs addressed by
   *   ascending code points, followed by glyphs not in the cmap.
   *
   *   If we compute a range, we take the character codes given in
   *   the fnt->sf_code array.
   *
   *   If the -N flag is set, no cmap is used at all.  Instead, the
   *   first 256 glyphs (with a valid PS name) are used for the default
   *   mapping.
   */

  if (!only_range)
    for (i = 0; i < 257; i++)
      index_array[i] = 0;
  else
    for (i = 0; i < 256; i++)
      fnt->inencptrs[i] = 0;

  j = 0;
  if (fnt->PSnames == Only)
    max_k = properties.num_Glyphs - 1;
  else
    max_k = only_range ? 0xFF : 0x16FFFF;

  for (k = 0; k <= max_k; k++)
  {
    char *an;


    if (fnt->PSnames != Only)
    {
      if (only_range)
      {
        index = fnt->sf_code[k];
        if (index < 0)
          continue;
        j = k;
      }
      else
        index = k;

      Num = TT_Char_Index(char_map, index);

      /* now we try to get a vertical glyph form */

      if (has_gsub)
      {
        in_string[0] = Num;
        error = TT_GSUB_Apply_String(gsub, &in, &out);
        if (error && error != TTO_Err_Not_Covered)
          warning("Cannot get the vertical glyph form for glyph index %d.",
                  Num);
        else
          Num = out.string[0];
      }

      if (Num < 0)
        oops("Failure on cmap mapping from %s.", fnt->ttfname);
      if (Num == 0)
        continue;
      if (!only_range)
        if (Num <= 256)
          index_array[Num] = 1;
    }
    else
    {
      Num = k;
      index = 0;
    }

    error = TT_Load_Glyph(instance, glyph, Num, 0);
    if (!error)
      error = TT_Get_Glyph_Big_Metrics(glyph, &metrics);
    if (!error)
      error = TT_Get_Glyph_Outline(glyph, &outline);
    if (!error)
    {
      if (fnt->efactor != 1.0 || fnt->slant != 0.0 )
        TT_Transform_Outline(&outline, &matrix1);
      if (fnt->rotate)
        TT_Transform_Outline(&outline, &matrix2);
    }
    if (!error)
      error = TT_Get_Outline_BBox(&outline, &bbox); /* we need the non-
                                                       grid-fitted bbox */
    if (!error)
    {
      if (fnt->PSnames)
        (void)TT_Get_PS_Name(face, Num, &an);
      else
        an = code_to_adobename(index);

      /* ignore characters not usable for typesetting with TeX */

      if (strcmp(an, ".notdef") == 0)
        continue;
      if (strcmp(an, ".null") == 0)
        continue;
      if (strcmp(an, "nonmarkingreturn") == 0)
        continue;

      ti = newchar(fnt);
      ti->charcode = index;
      ti->glyphindex = Num;
      ti->adobename = an;
      ti->llx = bbox.xMin * 1000 / fnt->units_per_em;
      ti->lly = bbox.yMin * 1000 / fnt->units_per_em;
      ti->urx = bbox.xMax * 1000 / fnt->units_per_em;
      ti->ury = bbox.yMax * 1000 / fnt->units_per_em;

      /*
       *   We must now shift the rotated character both horizontally
       *   and vertically.  The vertical amount is 25% by default.
       */

      if (fnt->rotate)
      {
        ti->llx += (metrics.vertBearingY - bbox.xMin) *
                     1000 / fnt->units_per_em;
        ti->lly -= 1000 * fnt->y_offset;
        ti->urx += (metrics.vertBearingY - bbox.xMin) *
                     1000 / fnt->units_per_em;
        ti->ury -= 1000 * fnt->y_offset;
      }

      /*
       *   We need to avoid negative heights or depths.  They break accents
       *   in math mode, among other things.
       */

      if (ti->lly > 0)
        ti->lly = 0;
      if (ti->ury < 0)
        ti->ury = 0;
      if (fnt->rotate)
        ti->width = metrics.vertAdvance * 1000 / fnt->units_per_em;
      else
        ti->width = transform(metrics.horiAdvance * 1000 / fnt->units_per_em,
                              0, fnt->efactor, fnt->slant);

      if (!quiet)
        printf("%5ld  %05lx  %-25s %5d  % 5d,% 5d -- % 5d,% 5d\n",
               Num, index, ti->adobename,
               ti->width,
               ti->llx, ti->lly, ti->urx, ti->ury);

      if (j < 256)
      {
        fnt->inencptrs[j] = ti;
        ti->incode = j;
      }
      j++;
    }
  }

  /*
   *   Now we load glyphs without a cmap entry, provided some slots are
   *   still free -- we skip this if we have to compute a range or use
   *   PS names.
   */

  if (!only_range && !fnt->PSnames)
  {
    for (i = 1; i <= properties.num_Glyphs; i++)
    {
      char *an;


      if (index_array[i] == 0)
      {
        error = TT_Load_Glyph(instance, glyph, i, 0);
        if (!error)
          error = TT_Get_Glyph_Big_Metrics(glyph, &metrics);
        if (!error)
          error = TT_Get_Glyph_Outline(glyph, &outline);
        if (!error)
          error = TT_Get_Outline_BBox(&outline, &bbox);
        if (!error)
        {
          an = code_to_adobename(i | 0x1000000);

          ti = newchar(fnt);
          ti->charcode = i | 0x1000000;
          ti->glyphindex = i;
          ti->adobename = an;
          ti->llx = bbox.xMin * 1000 / fnt->units_per_em;
          ti->lly = bbox.yMin * 1000 / fnt->units_per_em;
          ti->urx = bbox.xMax * 1000 / fnt->units_per_em;
          ti->ury = bbox.yMax * 1000 / fnt->units_per_em;

          if (ti->lly > 0)
            ti->lly = 0;
          if (ti->ury < 0)
            ti->ury = 0;
          ti->width = transform(metrics.horiAdvance*1000 / fnt->units_per_em,
                                0, fnt->efactor, fnt->slant);

          if (!quiet)
            printf("%5d         %-25s %5d  % 5d,% 5d -- % 5d,% 5d\n",
                   i, ti->adobename,
                   ti->width,
                   ti->llx, ti->lly, ti->urx, ti->ury);

          if (j < 256)
          {
            fnt->inencptrs[j] = ti;
            ti->incode = j;
          }
          else
            break;
          j++;
        }
      }
    }
  }

  /* Finally, we construct a `Germandbls' glyph if necessary */

  if (!only_range)
  {
    if (NULL == findadobe("Germandbls", fnt->charlist) &&
        NULL != (Ti = findadobe("S", fnt->charlist)))
    {
      pcc *np, *nq;


      ti = newchar(fnt);
      ti->charcode = properties.num_Glyphs | 0x1000000;
      ti->glyphindex = properties.num_Glyphs;
      ti->adobename = "Germandbls";
      ti->width = Ti->width << 1;
      ti->llx = Ti->llx;
      ti->lly = Ti->lly;
      ti->urx = Ti->width + Ti->urx;
      ti->ury = Ti->ury;
      ti->kerns = Ti->kerns;

      np = newpcc();
      np->partname = "S";
      nq = newpcc();
      nq->partname = "S";
      nq->xoffset = Ti->width;
      np->next = nq;
      ti->pccs = np;
      ti->constructed = True;

      if (!quiet)
        printf("*            %-25s %5d  % 5d,% 5d -- % 5d,% 5d\n",
               ti->adobename,
               ti->width,
               ti->llx, ti->lly, ti->urx, ti->ury);
    }
  }

  /* kerning between subfonts isn't available */
  if (!only_range)
    readttf_kern(fnt);
}
Beispiel #10
0
static void image_ttf_faceinstance_write(INT32 args)
{
   int **sstr;
   int *slen;
   int i,res=0,base=0,a;
   struct image_ttf_face_struct *face_s;
   struct image_ttf_faceinstance_struct *face_i=THISi;
   TT_CharMap charMap;
   TT_Kerning kerning;
   int has_kerning = 0;
   char *errs=NULL;
   int scalefactor=0;
   int xmin=1000,xmax=-1000,pos=0,ypos;
   int width,height,mod;

   unsigned char* pixmap;
   int maxcharwidth = 0;

   if (!(face_s=(struct image_ttf_face_struct*)
	 get_storage(THISi->faceobj,image_ttf_face_program)))
      Pike_error("Image.TTF.FaceInstance->write(): lost Face\n");

   if(!TT_Get_Kerning_Directory( face_s->face, &kerning ))
   {
     TT_Instance_Metrics metrics;
/*      fprintf(stderr, "has kerning!\n"); */
     has_kerning = 1;
     if(TT_Get_Instance_Metrics( face_i->instance, &metrics ))
       Pike_error("Nope. No way.\n");
     scalefactor = metrics.x_scale;
/*      fprintf(stderr, "offset=%d\n", (int)metrics.x_scale); */
   }

   if (args && sp[-1].type==T_INT)
   {
      base=sp[-1].u.integer;
      args--;
      pop_stack();
   }

   if (!args)
   {
      push_empty_string();
      args=1;
   }

   ttf_get_nice_charmap(face_s->face,&charMap,
			"Image.TTF.FaceInstance->write()");

   sstr=alloca(args*sizeof(int*));
   slen=alloca(args*sizeof(int));

   /* first pass: figure out total bounding box */

   for (a=0; a<args; a++)
   {
     char *errs=NULL;
     TT_Glyph_Metrics metrics;

      if (sp[a-args].type!=T_STRING)
	 Pike_error("Image.TTF.FaceInstance->write(): illegal argument %d\n",a+1);

      switch(sp[a-args].u.string->size_shift)
      {
       case 0:
	 ttf_translate_8bit(charMap,(unsigned char*)sp[a-args].u.string->str,
			    sstr+a,
			    DO_NOT_WARN(slen[a]=sp[a-args].u.string->len),
			    base);
	 break;
       case 1:
	 ttf_translate_16bit(charMap,(unsigned short*)sp[a-args].u.string->str,
			     sstr+a,
			     DO_NOT_WARN(slen[a]=sp[a-args].u.string->len),
			     base);
	 break;
       case 2:
	 Pike_error("Too wide string for truetype\n");
	 break;
      }

      pos=0;
      for (i=0; i<slen[a]; i++)
      {
	 TT_Glyph glyph;
	 int ind;

	 ind=sstr[a][i];
/* 	 fprintf(stderr,"glyph: %d\n",ind); */

	 if ((res=TT_New_Glyph(face_s->face,&glyph)))
	    { errs="TT_New_Glyph: "; break; }

	 if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind,
				(TT_UShort)face_i->load_flags)))
	    { errs="TT_Load_Glyph: "; break; }

	 if ((res=TT_Get_Glyph_Metrics(glyph,&metrics)))
	    { errs="TT_Get_Glyph_Metrics: "; break; }

	 if (pos+metrics.bbox.xMin<xmin)
	   xmin=pos+metrics.bbox.xMin;
	 if (pos+metrics.bbox.xMax>xmax)
	   xmax=pos+metrics.bbox.xMax;

	 if((metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0))
	    >maxcharwidth)
	   maxcharwidth =
	     (metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0));

	 pos+=metrics.advance;
	 if(has_kerning && i<slen[a]-1)
	 {
	   int kern = find_kerning( kerning, ind, sstr[a][i+1] );
	   pos += DOUBLE_TO_INT(kern * (scalefactor/65535.0));
	 }
	 if ((res=TT_Done_Glyph(glyph)))
	    { errs="TT_Done_Glyph: "; break; }
      }
      pos -= metrics.advance;
      pos += metrics.bbox.xMax-metrics.bbox.xMin;
      if (pos>xmax)
	xmax=pos;
      if (errs)
      {
	 for (i=0; i<a; i++) free(sstr[i]);
	 my_tt_error("Image.TTF.FaceInstance->write()",errs,res);
      }
   }

   pop_n_elems(args);

/*    fprintf(stderr,"xmin=%f xmax=%f\n",xmin/64.0,xmax/64.0); */

   xmin&=~63;
   width=((xmax-xmin+63)>>6)+4;
   height=face_i->height*args;
   mod=(4-(maxcharwidth&3))&3;
   if (width<1) width=1;

   if ((pixmap=malloc((maxcharwidth+mod)*face_i->height)))
   {
      /* second pass: write the stuff */

      TT_Raster_Map rastermap;
      struct object *o;
      struct image *img;
      rgb_group *d;


      rastermap.rows=face_i->height;
      rastermap.cols=rastermap.width=maxcharwidth+mod;
      rastermap.flow=TT_Flow_Down;
      rastermap.bitmap=pixmap;
      rastermap.size=rastermap.cols*rastermap.rows;

      ypos=0;

/*       fprintf(stderr,"rastermap.rows=%d cols=%d width=%d\n", */
/* 	      rastermap.rows,rastermap.cols,rastermap.width); */


      push_int(width);
      push_int(height);
      o=clone_object(image_program,2);
      img=(struct image*)get_storage(o,image_program);
      d=img->img;

      for (a=0; a<args; a++)
      {
         pos=-xmin;
	 for (i=0; i<slen[a]; i++)
	 {
    	    int sw, xp;
	    TT_Glyph glyph;
	    TT_Glyph_Metrics metrics;
	    int ind, x, y;

	    ind=sstr[a][i];
/* 	    fprintf(stderr,"glyph: %d\n",ind); */


	    if ((res=TT_New_Glyph(face_s->face,&glyph)))
	       { errs="TT_New_Glyph: "; break; }

	    if ((res=TT_Load_Glyph(face_i->instance, glyph, (TT_UShort)ind,
				   (TT_UShort)face_i->load_flags)))
	       { errs="TT_Load_Glyph: "; break; }

	    if ((res=TT_Get_Glyph_Metrics(glyph,&metrics)))
	       { errs="TT_Get_Glyph_Metrics: "; break; }

	    MEMSET(pixmap,0,rastermap.size);

	    if ((res=TT_Get_Glyph_Pixmap(glyph,
					 &rastermap,
					 -metrics.bbox.xMin
                                         /*+pos%64*/,
					 face_i->height*64-
					 face_i->trans)))
	       { errs="TT_Get_Glyph_Pixmap: "; break; }


	    sw = metrics.bbox.xMax-(metrics.bbox.xMin<0?metrics.bbox.xMin:0);
	    /* Copy source pixmap to destination image object. */
	    for(y=0; y<face_i->height; y++)
	    {
	      unsigned int s;
	      unsigned char * source = pixmap+rastermap.width*y;
	      rgb_group *dt=d+(ypos+y)*width+(xp=(metrics.bbox.xMin+pos)/64);

	      for(x=0; x<sw && xp<width; x++,xp++,source++,dt++)
		if(xp<0 || !(s = *source))
		  continue;
		else if((s=dt->r+s) < 256)
		  dt->r=dt->g=dt->b=s;
		else
		  dt->r=dt->g=dt->b=255;
	    }

	    pos+=metrics.advance;
/* 	    if(metrics.bbox.xMin < 0) */
/* 	      pos += metrics.bbox.xMin; */
	    if(has_kerning && i<slen[a]-1)
	    {
	      int kern = find_kerning( kerning, sstr[a][i], sstr[a][i+1] );
	      pos += DOUBLE_TO_INT(kern * (scalefactor/65535.0));
/* 	      fprintf(stderr, "Adjusted is %d\n", */
/* 		      (int)(kern * (scalefactor/65535.0))); */
	    }

	    if ((res=TT_Done_Glyph(glyph)))
	       { errs="TT_Done_Glyph: "; break; }
	 }
	 if (errs)
	 {
	    for (a=0; a<args; a++) free(sstr[a]);
	    free(pixmap);
	    free_object(o);
	    my_tt_error("Image.TTF.FaceInstance->write()",errs,res);
	 }
	 ypos+=face_i->height;
      }
      free(pixmap);
      push_object(o);
   }
   else
   {
      Pike_error("Image.TTF.FaceInstance->write(): out of memory\n");
   }

   for (a=0; a<args; a++)
      free(sstr[a]);
}
Beispiel #11
0
static void image_ttf_faceinstance_ponder(INT32 args)
{
   int *sstr;
   int len,i,res,base=0;
   struct image_ttf_face_struct *face_s;
   struct image_ttf_faceinstance_struct *face_i=THISi;

   int xmin=1000,xmax=-1000,pos=0;

   if (!(face_s=(struct image_ttf_face_struct*)
	 get_storage(THISi->faceobj,image_ttf_face_program)))
      Pike_error("Image.TTF.FaceInstance->ponder(): lost Face\n");

   if (args && sp[-1].type==T_INT)
   {
      base=sp[-1].u.integer;
      args--;
      pop_stack();
   }

   if (sp[-args].type!=T_STRING)
      Pike_error("Image.TTF.FaceInstance->ponder(): illegal argument 1\n");

   switch( sp[-args].u.string->size_shift )
   {
    case 0:
      ttf_please_translate_8bit(face_s->face,
                                sp[-args].u.string,&sstr,&len,base,
                                "Image.TTF.FaceInstance->ponder()");
      break;
    case 1:
      ttf_please_translate_16bit(face_s->face,
                                 sp[-args].u.string,&sstr,&len,base,
                                 "Image.TTF.FaceInstance->ponder()");
      break;
    default:
     Pike_error("Too wide string for truetype\n");
   }
   pop_n_elems(args);

   for (i=0; i<len; i++)
   {
      TT_Glyph glyph;
      TT_Glyph_Metrics metrics;
      int ind;

      ind=sstr[i];
/*       fprintf(stderr,"glyph: %d\n",ind); */

      if ((res=TT_New_Glyph(face_s->face,&glyph)))
	 my_tt_error("Image.TTF.FaceInstance->ponder()","TT_New_Glyph: ",res);

      if ((res=TT_Load_Glyph(face_i->instance, glyph,
			     (TT_UShort)ind, (TT_UShort)face_i->load_flags)))
	 my_tt_error("Image.TTF.FaceInstance->ponder()","TT_Load_Glyph: ",res);

      if ((res=TT_Get_Glyph_Metrics(glyph,&metrics)))
	 my_tt_error("Image.TTF.FaceInstance->ponder()",
		     "TT_Get_Glyph_Metrics: ",res);

      if (pos+metrics.bbox.xMin<xmin) xmin=pos+metrics.bbox.xMin;
      if (pos+metrics.bbox.xMax>xmax) xmax=pos+metrics.bbox.xMax;
      pos+=metrics.advance; /* insert kerning stuff here */

/*       fprintf(stderr,"bbox: (%f,%f)-(%f,%f)\n", */
/* 	      metrics.bbox.xMin/64.0, */
/* 	      metrics.bbox.yMin/64.0, */
/* 	      metrics.bbox.xMax/64.0, */
/* 	      metrics.bbox.yMax/64.0); */

/*       fprintf(stderr,"BearingX: %f\n",metrics.bearingX/64.0); */
/*       fprintf(stderr,"BearingY: %f\n",metrics.bearingY/64.0); */
/*       fprintf(stderr,"advance: %f\n",metrics.advance/64.0); */

/*       fprintf(stderr,"\n"); */
   }

   free(sstr);

/*    fprintf(stderr,"xmin: %f\n",xmin/64.0); */
/*    fprintf(stderr,"xmax: %f\n",xmax/64.0); */

   ref_push_object(THISOBJ);
}
Beispiel #12
0
static
int
i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) {
  unsigned short load_flags, code;
  TT_Error error;

  mm_log((1, "i_tt_get_glyph(handle %p, inst %d, j %lu (%c))\n",
          handle,inst,j, (int)((j >= ' ' && j <= '~') ? j : '.')));
  
  /*mm_log((1, "handle->instanceh[inst].glyphs[j]=0x%08X\n",handle->instanceh[inst].glyphs[j] ));*/

  if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)
       && handle->instanceh[inst].glyphs[TT_HASH(j)].ch == j) {
    mm_log((1,"i_tt_get_glyph: %lu in cache\n",j));
    return 1;
  }

  if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph) ) {
    /* clean up the entry */
    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
    handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
  }
  
  /* Ok - it wasn't cached - try to get it in */
  load_flags = TTLOAD_SCALE_GLYPH;
  if ( LTT_hinted ) load_flags |= TTLOAD_HINT_GLYPH;
  
  if ( !TT_VALID(handle->char_map) ) {
    code = (j - ' ' + 1) < 0 ? 0 : (j - ' ' + 1);
    if ( code >= handle->properties.num_Glyphs ) code = 0;
  } else code = TT_Char_Index( handle->char_map, j );
  
  if ( (error = TT_New_Glyph( handle->face, &handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)) ) {
    mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
    i_push_error(error, "TT_New_Glyph()");
    return 0;
  }
  if ( (error = TT_Load_Glyph( handle->instanceh[inst].instance, handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, code, load_flags)) ) {
    mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
    /* Don't leak */
    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
    i_push_error(error, "TT_Load_Glyph()");
    return 0;
  }

  /* At this point the glyph should be allocated and loaded */
  handle->instanceh[inst].glyphs[TT_HASH(j)].ch = j;

  /* Next get the glyph metrics */
  error = TT_Get_Glyph_Metrics( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, 
                                &handle->instanceh[inst].gmetrics[TT_HASH(j)] );
  if (error) {
    mm_log((1, "TT_Get_Glyph_Metrics: error %#x.\n", (unsigned)error ));
    TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
    USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
    handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
    i_push_error(error, "TT_Get_Glyph_Metrics()");
    return 0;
  }

  return 1;
}