1999-12-17 00:11:37 +01:00
|
|
|
/***************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* ttload.c */
|
|
|
|
/* */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* Load the basic TrueType tables, i.e., tables that can be either in */
|
|
|
|
/* TTF or OTF fonts (body). */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* Copyright 1996-2000 by */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
|
|
|
/* */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* This file is part of the FreeType project, and may only be used, */
|
|
|
|
/* modified, and distributed under the terms of the FreeType project */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* 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. */
|
|
|
|
/* */
|
|
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
|
2000-05-11 20:23:52 +02:00
|
|
|
#include <freetype/internal/ftdebug.h>
|
|
|
|
#include <freetype/internal/tterrors.h>
|
|
|
|
#include <freetype/tttags.h>
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
#include <ttload.h>
|
|
|
|
#include <ttcmap.h>
|
|
|
|
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
|
|
|
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
|
|
|
/* messages during execution. */
|
|
|
|
/* */
|
|
|
|
#undef FT_COMPONENT
|
|
|
|
#define FT_COMPONENT trace_ttload
|
2000-02-13 14:41:56 +01:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_LookUp_Table */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Looks for a TrueType table by name. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A face object handle. */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* tag :: The searched tag. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* A pointer to the table directory entry. 0 if not found. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2000-05-12 14:17:15 +02:00
|
|
|
LOCAL_FUNC
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_Table* TT_LookUp_Table( TT_Face face,
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong tag )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_Table* entry;
|
|
|
|
TT_Table* limit;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
2000-06-06 22:41:48 +02:00
|
|
|
FT_TRACE3(( "TT_LookUp_Table: %08p, `%c%c%c%c'\n",
|
2000-05-18 18:18:05 +02:00
|
|
|
face,
|
2000-06-16 21:34:52 +02:00
|
|
|
(FT_Char)( tag >> 24 ),
|
|
|
|
(FT_Char)( tag >> 16 ),
|
|
|
|
(FT_Char)( tag >> 8 ),
|
2000-07-02 02:27:53 +02:00
|
|
|
(FT_Char)( tag ) ));
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
entry = face->dir_tables;
|
|
|
|
limit = entry + face->num_tables;
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; entry < limit; entry++ )
|
|
|
|
{
|
|
|
|
if ( entry->Tag == tag )
|
|
|
|
return entry;
|
2000-05-17 01:44:38 +02:00
|
|
|
}
|
2000-06-05 07:26:15 +02:00
|
|
|
|
|
|
|
FT_TRACE3(( " Could not find table!\n" ));
|
1999-12-17 00:11:37 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Goto_Table */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Looks for a TrueType table by name, then seek a stream to it. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* face :: A face object handle. */
|
|
|
|
/* tag :: The searched tag. */
|
|
|
|
/* stream :: The stream to seek when the table is found. */
|
|
|
|
/* */
|
|
|
|
/* <Output> */
|
|
|
|
/* length :: The length of the table if found, undefined otherwise. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2000-05-12 14:17:15 +02:00
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Goto_Table( TT_Face face,
|
|
|
|
FT_ULong tag,
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_Stream stream,
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong* length )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_Table* table;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
table = TT_LookUp_Table( face, tag );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( table )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( length )
|
1999-12-17 00:11:37 +01:00
|
|
|
*length = table->Length;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
(void)FILE_Seek( table->Offset );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
error = TT_Err_Table_Missing;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* <Function> */
|
2000-05-29 22:37:41 +02:00
|
|
|
/* TT_Load_SFNT_Header */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Description> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* Loads the header of a SFNT font file. Supports collections. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Input> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* face_index :: If the font is a collection, the number of the font */
|
|
|
|
/* in the collection, ignored otherwise. */
|
2000-05-29 22:37:41 +02:00
|
|
|
/* */
|
2000-01-27 14:56:02 +01:00
|
|
|
/* <Output> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* sfnt :: The SFNT header. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Note> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* The stream cursor must be at the font file's origin. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* This function recognizes fonts embedded in a `TrueType collection' */
|
|
|
|
/* */
|
|
|
|
/* The header will be checked whether it is valid by looking at the */
|
|
|
|
/* values of `search_range', `entry_selector', and `range_shift'. */
|
2000-05-29 22:37:41 +02:00
|
|
|
/* */
|
1999-12-17 00:11:37 +01:00
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_SFNT_Header( TT_Face face,
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_Stream stream,
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long face_index,
|
2000-06-05 07:26:15 +02:00
|
|
|
SFNT_Header* sfnt )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
|
|
|
FT_ULong format_tag;
|
2000-06-14 01:21:00 +02:00
|
|
|
FT_Memory memory = stream->memory;
|
2000-06-05 16:32:32 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
const FT_Frame_Field sfnt_header_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 8 ),
|
|
|
|
FT_FRAME_USHORT( SFNT_Header, num_tables ),
|
|
|
|
FT_FRAME_USHORT( SFNT_Header, search_range ),
|
|
|
|
FT_FRAME_USHORT( SFNT_Header, entry_selector ),
|
|
|
|
FT_FRAME_USHORT( SFNT_Header, range_shift ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
2000-06-05 16:32:32 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
const FT_Frame_Field ttc_header_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 8 ),
|
|
|
|
FT_FRAME_LONG( TTC_Header, version ),
|
|
|
|
FT_FRAME_LONG( TTC_Header, DirCount ),
|
|
|
|
FT_FRAME_END };
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n",
|
2000-06-01 05:26:58 +02:00
|
|
|
face, face_index ));
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
face->ttc_header.Tag = 0;
|
|
|
|
face->ttc_header.version = 0;
|
|
|
|
face->ttc_header.DirCount = 0;
|
|
|
|
|
|
|
|
face->num_tables = 0;
|
|
|
|
|
2000-07-02 02:27:53 +02:00
|
|
|
/* first of all, read the first 4 bytes. If it is `ttcf', then the */
|
|
|
|
/* file is a TrueType collection, otherwise it can be any other */
|
|
|
|
/* kind of font. */
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_ULong( format_tag ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-05-29 22:37:41 +02:00
|
|
|
if ( format_tag == TTAG_ttcf )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Int n;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
|
|
|
FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" ));
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* it's a TrueType collection, i.e. a file containing several */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* font files. Read the font directory now */
|
2000-02-13 14:41:56 +01:00
|
|
|
if ( READ_Fields( ttc_header_fields, &face->ttc_header ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
/* now read the offsets of each font in the file */
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( ALLOC_ARRAY( face->ttc_header.TableDirectory,
|
|
|
|
face->ttc_header.DirCount,
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong ) ||
|
1999-12-17 00:11:37 +01:00
|
|
|
ACCESS_Frame( face->ttc_header.DirCount * 4L ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
for ( n = 0; n < face->ttc_header.DirCount; n++ )
|
|
|
|
face->ttc_header.TableDirectory[n] = GET_ULong();
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
|
|
|
/* check face index */
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( face_index >= face->ttc_header.DirCount )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
error = TT_Err_Bad_Argument;
|
|
|
|
goto Exit;
|
2000-05-17 01:44:38 +02:00
|
|
|
}
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* seek to the appropriate TrueType file, then read tag */
|
2000-05-29 22:37:41 +02:00
|
|
|
if ( FILE_Seek( face->ttc_header.TableDirectory[face_index] ) ||
|
|
|
|
READ_Long( format_tag ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
2000-05-29 22:37:41 +02:00
|
|
|
/* the format tag was read, now check the rest of the header */
|
|
|
|
sfnt->format_tag = format_tag;
|
|
|
|
if ( READ_Fields( sfnt_header_fields, sfnt ) )
|
|
|
|
goto Exit;
|
2000-06-05 16:32:32 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
/* now, check the values of `num_tables', `seach_range', etc. */
|
2000-05-29 22:37:41 +02:00
|
|
|
{
|
2000-07-02 02:27:53 +02:00
|
|
|
FT_UInt num_tables = sfnt->num_tables;
|
|
|
|
FT_ULong entry_selector = 1L << sfnt->entry_selector;
|
2000-06-01 05:26:58 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
|
|
|
/* IMPORTANT: Many fonts have an incorrect `search_range' value, so */
|
|
|
|
/* we only check the `entry_selector' correctness here. */
|
|
|
|
/* */
|
|
|
|
if ( num_tables == 0 ||
|
|
|
|
entry_selector > num_tables ||
|
|
|
|
entry_selector * 2 <= num_tables )
|
2000-06-01 05:26:58 +02:00
|
|
|
{
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
|
2000-05-29 22:37:41 +02:00
|
|
|
error = FT_Err_Unknown_File_Format;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
Exit:
|
|
|
|
return error;
|
2000-06-05 16:32:32 +02:00
|
|
|
}
|
2000-05-29 22:37:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-01-27 14:56:02 +01:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Directory */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the table directory into a face object. */
|
|
|
|
/* */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* <InOut> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* */
|
2000-01-27 14:56:02 +01:00
|
|
|
/* <Input> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* sfnt :: The SFNT directory header. */
|
2000-01-27 14:56:02 +01:00
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
2000-01-27 14:56:02 +01:00
|
|
|
/* */
|
|
|
|
/* <Note> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* The stream cursor must be at the font file's origin. */
|
2000-01-27 14:56:02 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Directory( TT_Face face,
|
2000-05-29 22:37:41 +02:00
|
|
|
FT_Stream stream,
|
|
|
|
SFNT_Header* sfnt )
|
2000-01-27 14:56:02 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
2000-01-27 14:56:02 +01:00
|
|
|
FT_Memory memory = stream->memory;
|
|
|
|
|
|
|
|
TT_Table *entry, *limit;
|
|
|
|
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_TRACE2(( "TT_Load_Directory: %08p\n", face ));
|
|
|
|
|
|
|
|
FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables ));
|
|
|
|
FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
|
2000-01-27 14:56:02 +01:00
|
|
|
|
2000-05-29 22:37:41 +02:00
|
|
|
face->num_tables = sfnt->num_tables;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( ALLOC_ARRAY( face->dir_tables,
|
|
|
|
face->num_tables,
|
|
|
|
TT_Table ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
if ( ACCESS_Frame( face->num_tables * 16L ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
entry = face->dir_tables;
|
|
|
|
limit = entry + face->num_tables;
|
|
|
|
|
|
|
|
for ( ; entry < limit; entry++ )
|
2000-01-27 14:56:02 +01:00
|
|
|
{ /* loop through the tables and get all entries */
|
1999-12-17 00:11:37 +01:00
|
|
|
entry->Tag = GET_Tag4();
|
|
|
|
entry->CheckSum = GET_ULong();
|
|
|
|
entry->Offset = GET_Long();
|
|
|
|
entry->Length = GET_Long();
|
|
|
|
|
|
|
|
FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
|
2000-06-16 21:34:52 +02:00
|
|
|
(FT_Char)( entry->Tag >> 24 ),
|
|
|
|
(FT_Char)( entry->Tag >> 16 ),
|
|
|
|
(FT_Char)( entry->Tag >> 8 ),
|
|
|
|
(FT_Char)( entry->Tag ),
|
2000-06-05 07:26:15 +02:00
|
|
|
entry->Offset,
|
|
|
|
entry->Length ));
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
|
|
|
FT_TRACE2(( "Directory loaded\n\n" ));
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Any */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads any font table into client memory. Used by the */
|
|
|
|
/* TT_Get_Font_Data() API function. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: The face object to look for. */
|
|
|
|
/* */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* tag :: The tag of table to load. Use the value 0 if you want */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* to access the whole font file, else set this parameter */
|
|
|
|
/* to a valid TrueType table tag that you can forge with */
|
|
|
|
/* the MAKE_TT_TAG macro. */
|
|
|
|
/* */
|
|
|
|
/* offset :: The starting offset in the table (or the file if */
|
|
|
|
/* tag == 0). */
|
|
|
|
/* */
|
|
|
|
/* length :: The address of the decision variable: */
|
|
|
|
/* */
|
|
|
|
/* If length == NULL: */
|
|
|
|
/* Loads the whole table. Returns an error if */
|
|
|
|
/* `offset' == 0! */
|
|
|
|
/* */
|
|
|
|
/* If *length == 0: */
|
|
|
|
/* Exits immediately; returning the length of the given */
|
|
|
|
/* table or of the font file, depending on the value of */
|
|
|
|
/* `tag'. */
|
|
|
|
/* */
|
|
|
|
/* If *length != 0: */
|
|
|
|
/* Loads the next `length' bytes of table or font, */
|
|
|
|
/* starting at offset `offset' (in table or font too). */
|
|
|
|
/* */
|
|
|
|
/* <Output> */
|
|
|
|
/* buffer :: The address of target buffer. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Any( TT_Face face,
|
|
|
|
FT_ULong tag,
|
|
|
|
FT_Long offset,
|
1999-12-17 00:11:37 +01:00
|
|
|
void* buffer,
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long* length )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream;
|
|
|
|
TT_Table* table;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong size;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( tag != 0 )
|
|
|
|
{
|
|
|
|
/* look for tag in font directory */
|
|
|
|
table = TT_LookUp_Table( face, tag );
|
|
|
|
if ( !table )
|
|
|
|
{
|
|
|
|
error = TT_Err_Table_Missing;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset += table->Offset;
|
|
|
|
size = table->Length;
|
|
|
|
}
|
|
|
|
else
|
2000-06-05 07:26:15 +02:00
|
|
|
/* tag == 0 -- the user wants to access the font file directly */
|
1999-12-17 00:11:37 +01:00
|
|
|
size = face->root.stream->size;
|
|
|
|
|
|
|
|
if ( length && *length == 0 )
|
|
|
|
{
|
|
|
|
*length = size;
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( length )
|
|
|
|
size = *length;
|
|
|
|
|
|
|
|
stream = face->root.stream;
|
|
|
|
(void)FILE_Read_At( offset, buffer, size );
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Header */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the TrueType font header. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Header( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_Header* header;
|
2000-05-29 22:37:41 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
static const FT_Frame_Field header_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 54 ),
|
|
|
|
FT_FRAME_ULONG( TT_Header, Table_Version ),
|
|
|
|
FT_FRAME_ULONG( TT_Header, Font_Revision ),
|
|
|
|
FT_FRAME_LONG( TT_Header, CheckSum_Adjust ),
|
|
|
|
FT_FRAME_LONG( TT_Header, Magic_Number ),
|
|
|
|
FT_FRAME_USHORT( TT_Header, Flags ),
|
|
|
|
FT_FRAME_USHORT( TT_Header, Units_Per_EM ),
|
|
|
|
FT_FRAME_LONG( TT_Header, Created[0] ),
|
|
|
|
FT_FRAME_LONG( TT_Header, Created[1] ),
|
|
|
|
FT_FRAME_LONG( TT_Header, Modified[0] ),
|
|
|
|
FT_FRAME_LONG( TT_Header, Modified[1] ),
|
|
|
|
FT_FRAME_SHORT( TT_Header, xMin ),
|
|
|
|
FT_FRAME_SHORT( TT_Header, yMin ),
|
|
|
|
FT_FRAME_SHORT( TT_Header, xMax ),
|
|
|
|
FT_FRAME_SHORT( TT_Header, yMax ),
|
|
|
|
FT_FRAME_USHORT( TT_Header, Mac_Style ),
|
|
|
|
FT_FRAME_USHORT( TT_Header, Lowest_Rec_PPEM ),
|
|
|
|
FT_FRAME_SHORT( TT_Header, Font_Direction ),
|
|
|
|
FT_FRAME_SHORT( TT_Header, Index_To_Loc_Format ),
|
|
|
|
FT_FRAME_SHORT( TT_Header, Glyph_Data_Format ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
FT_TRACE2(( "Load_TT_Header: %08p\n", face ));
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
error = face->goto_table( face, TTAG_head, stream, 0 );
|
|
|
|
if ( error )
|
|
|
|
{
|
|
|
|
FT_TRACE0(( "Font Header is missing!\n" ));
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
2000-02-13 14:41:56 +01:00
|
|
|
header = &face->header;
|
|
|
|
|
2000-05-29 22:37:41 +02:00
|
|
|
if ( READ_Fields( header_fields, header ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Exit;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_TRACE2(( " Units per EM: %8u\n", header->Units_Per_EM ));
|
|
|
|
FT_TRACE2(( " IndexToLoc: %8d\n", header->Index_To_Loc_Format ));
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_TRACE2(( "Font Header Loaded.\n" ));
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_MaxProfile */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the maximum profile into a face object. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_MaxProfile( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_MaxProfile* maxProfile = &face->max_profile;
|
2000-05-29 22:37:41 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
const FT_Frame_Field maxp_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 32 ),
|
|
|
|
FT_FRAME_ULONG( TT_MaxProfile, version ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, numGlyphs ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxPoints ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxContours ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxCompositePoints ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxCompositeContours ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxZones ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxTwilightPoints ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxStorage ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxFunctionDefs ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxInstructionDefs ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxStackElements ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxSizeOfInstructions ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxComponentElements ),
|
|
|
|
FT_FRAME_USHORT( TT_MaxProfile, maxComponentDepth ),
|
|
|
|
FT_FRAME_END };
|
|
|
|
|
|
|
|
|
|
|
|
FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
error = face->goto_table( face, TTAG_maxp, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( maxp_fields, maxProfile ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* XXX: an adjustment that is necessary to load certain */
|
2000-07-02 02:27:53 +02:00
|
|
|
/* broken fonts like `Keystrokes MT' :-( */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* We allocate 64 function entries by default when */
|
|
|
|
/* the maxFunctionDefs field is null. */
|
|
|
|
|
|
|
|
if ( maxProfile->maxFunctionDefs == 0 )
|
|
|
|
maxProfile->maxFunctionDefs = 64;
|
|
|
|
|
|
|
|
face->root.num_glyphs = maxProfile->numGlyphs;
|
|
|
|
|
|
|
|
face->root.max_points = MAX( maxProfile->maxCompositePoints,
|
|
|
|
maxProfile->maxPoints );
|
|
|
|
|
|
|
|
face->root.max_contours = MAX( maxProfile->maxCompositeContours,
|
|
|
|
maxProfile->maxContours );
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
face->max_components = (FT_ULong)maxProfile->maxComponentElements +
|
1999-12-17 00:11:37 +01:00
|
|
|
maxProfile->maxComponentDepth;
|
|
|
|
|
|
|
|
/* XXX: some fonts have maxComponents set to 0; we will */
|
|
|
|
/* then use 16 of them by default. */
|
|
|
|
if ( face->max_components == 0 )
|
|
|
|
face->max_components = 16;
|
|
|
|
|
|
|
|
/* We also increase maxPoints and maxContours in order to support */
|
|
|
|
/* some broken fonts. */
|
|
|
|
face->root.max_points += 8;
|
|
|
|
face->root.max_contours += 4;
|
|
|
|
|
|
|
|
FT_TRACE2(( "MAXP loaded.\n" ));
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Metrics */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the horizontal or vertical metrics table into a face object. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* vertical :: A boolean flag. If set, load vertical metrics. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
static
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Metrics( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream,
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Bool vertical )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Memory memory = stream->memory;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong table_len;
|
|
|
|
FT_Long num_shorts, num_longs, num_shorts_checked;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
TT_LongMetrics** longs;
|
|
|
|
TT_ShortMetrics** shorts;
|
|
|
|
|
2000-07-02 02:27:53 +02:00
|
|
|
|
|
|
|
FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
|
|
|
|
: "Horizontal",
|
|
|
|
face ));
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( vertical )
|
|
|
|
{
|
|
|
|
/* The table is optional, quit silently if it wasn't found */
|
|
|
|
/* XXX: Some fonts have a valid vertical header with a non-null */
|
|
|
|
/* `number_of_VMetrics' fields, but no corresponding `vmtx' */
|
|
|
|
/* table to get the metrics from (e.g. mingliu). */
|
|
|
|
/* */
|
|
|
|
/* For safety, we set the field to 0! */
|
|
|
|
/* */
|
|
|
|
error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
|
|
|
|
if ( error )
|
|
|
|
{
|
2000-06-05 07:26:15 +02:00
|
|
|
/* Set number_Of_VMetrics to 0! */
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_TRACE2(( " no vertical header in file.\n" ));
|
|
|
|
face->vertical.number_Of_VMetrics = 0;
|
|
|
|
error = TT_Err_Ok;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_longs = face->vertical.number_Of_VMetrics;
|
|
|
|
longs = (TT_LongMetrics**)&face->vertical.long_metrics;
|
|
|
|
shorts = (TT_ShortMetrics**)&face->vertical.short_metrics;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
FT_ERROR(( " no horizontal metrics in file!\n" ));
|
|
|
|
error = TT_Err_Hmtx_Table_Missing;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_longs = face->horizontal.number_Of_HMetrics;
|
|
|
|
longs = (TT_LongMetrics**)&face->horizontal.long_metrics;
|
|
|
|
shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* never trust derived values */
|
|
|
|
|
|
|
|
num_shorts = face->max_profile.numGlyphs - num_longs;
|
2000-06-05 07:26:15 +02:00
|
|
|
num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( num_shorts < 0 )
|
|
|
|
{
|
2000-07-02 02:27:53 +02:00
|
|
|
FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
|
|
|
|
vertical ? "Vertical"
|
|
|
|
: "Horizontal" ));
|
2000-06-05 07:26:15 +02:00
|
|
|
|
|
|
|
error = vertical ? TT_Err_Invalid_Vert_Metrics
|
|
|
|
: TT_Err_Invalid_Horiz_Metrics;
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( ALLOC_ARRAY( *longs, num_longs, TT_LongMetrics ) ||
|
1999-12-17 00:11:37 +01:00
|
|
|
ALLOC_ARRAY( *shorts, num_shorts, TT_ShortMetrics ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
if ( ACCESS_Frame( table_len ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
{
|
|
|
|
TT_LongMetrics* cur = *longs;
|
|
|
|
TT_LongMetrics* limit = cur + num_longs;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; cur < limit; cur++ )
|
|
|
|
{
|
|
|
|
cur->advance = GET_UShort();
|
|
|
|
cur->bearing = GET_Short();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
/* do we have an inconsistent number of metric values? */
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
TT_ShortMetrics* cur = *shorts;
|
|
|
|
TT_ShortMetrics* limit = cur + MIN( num_shorts, num_shorts_checked );
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; cur < limit; cur++ )
|
|
|
|
*cur = GET_Short();
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
/* we fill up the missing left side bearings with the */
|
|
|
|
/* last valid value. Since this will occur for buggy CJK */
|
|
|
|
/* fonts usually only, nothing serious will happen */
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Short val = *(shorts)[num_shorts_checked - 1];
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
limit = *shorts + num_shorts;
|
|
|
|
for ( ; cur < limit; cur++ )
|
|
|
|
*cur = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
|
|
|
FT_TRACE2(( "loaded\n" ));
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Metrics_Header */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the horizontal or vertical header in a face object. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* vertical :: A boolean flag. If set, load vertical metrics. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Metrics_Header( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream,
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Bool vertical )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_HoriHeader* header;
|
2000-05-29 22:37:41 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
const FT_Frame_Field metrics_header_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 36 ),
|
|
|
|
FT_FRAME_ULONG( TT_HoriHeader, Version ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, Ascender ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, Descender ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, Line_Gap ),
|
|
|
|
FT_FRAME_USHORT( TT_HoriHeader, advance_Width_Max ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, min_Left_Side_Bearing ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, min_Right_Side_Bearing ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, xMax_Extent ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Rise ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Run ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, Reserved[0] ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, Reserved[1] ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, Reserved[2] ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, Reserved[3] ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, Reserved[4] ),
|
|
|
|
FT_FRAME_SHORT( TT_HoriHeader, metric_Data_Format ),
|
|
|
|
FT_FRAME_USHORT( TT_HoriHeader, number_Of_HMetrics ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
|
|
|
|
2000-05-29 22:37:41 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
|
|
|
|
|
|
|
|
if ( vertical )
|
|
|
|
{
|
|
|
|
face->vertical_info = 0;
|
|
|
|
|
|
|
|
/* The vertical header table is optional, so return quietly if */
|
|
|
|
/* we don't find it. */
|
|
|
|
error = face->goto_table( face, TTAG_vhea, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
error = TT_Err_Ok;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
face->vertical_info = 1;
|
|
|
|
header = (TT_HoriHeader*)&face->vertical;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-07-02 02:27:53 +02:00
|
|
|
/* The horizontal header is mandatory; return an error if we */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* don't find it. */
|
|
|
|
error = face->goto_table( face, TTAG_hhea, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
error = TT_Err_Horiz_Header_Missing;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
header = &face->horizontal;
|
|
|
|
}
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( metrics_header_fields, header ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
header->long_metrics = NULL;
|
|
|
|
header->short_metrics = NULL;
|
|
|
|
|
|
|
|
FT_TRACE2(( "loaded\n" ));
|
|
|
|
|
|
|
|
/* Now try to load the corresponding metrics */
|
|
|
|
|
|
|
|
error = TT_Load_Metrics( face, stream, vertical );
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Names */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the name records. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Names( TT_Face face,
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_Stream stream )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Memory memory = stream->memory;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong table_pos, table_len;
|
|
|
|
FT_ULong storageSize;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
TT_NameTable* names;
|
2000-05-29 22:37:41 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
const FT_Frame_Field name_table_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 6 ),
|
|
|
|
FT_FRAME_USHORT( TT_NameTable, format ),
|
|
|
|
FT_FRAME_USHORT( TT_NameTable, numNameRecords ),
|
|
|
|
FT_FRAME_USHORT( TT_NameTable, storageOffset ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
|
|
|
|
|
|
|
const FT_Frame_Field name_record_fields[] =
|
|
|
|
{
|
|
|
|
/* no FT_FRAME_START */
|
|
|
|
FT_FRAME_USHORT( TT_NameRec, platformID ),
|
|
|
|
FT_FRAME_USHORT( TT_NameRec, encodingID ),
|
|
|
|
FT_FRAME_USHORT( TT_NameRec, languageID ),
|
|
|
|
FT_FRAME_USHORT( TT_NameRec, nameID ),
|
|
|
|
FT_FRAME_USHORT( TT_NameRec, stringLength ),
|
|
|
|
FT_FRAME_USHORT( TT_NameRec, stringOffset ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
FT_TRACE2(( "Names " ));
|
|
|
|
|
|
|
|
error = face->goto_table( face, TTAG_name, stream, &table_len );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* The name table is required so indicate failure. */
|
|
|
|
FT_TRACE2(( "is missing!\n" ));
|
|
|
|
error = TT_Err_Name_Table_Missing;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
table_pos = FILE_Pos();
|
|
|
|
|
2000-02-13 14:41:56 +01:00
|
|
|
names = &face->name_table;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( name_table_fields, names ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* Allocate the array of name records. */
|
|
|
|
if ( ALLOC_ARRAY( names->names,
|
|
|
|
names->numNameRecords,
|
|
|
|
TT_NameRec ) ||
|
|
|
|
ACCESS_Frame( names->numNameRecords * 12L ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
/* Load the name records and determine how much storage is needed */
|
|
|
|
/* to hold the strings themselves. */
|
|
|
|
{
|
2000-06-05 07:26:15 +02:00
|
|
|
TT_NameRec* cur = names->names;
|
|
|
|
TT_NameRec* limit = cur + names->numNameRecords;
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
storageSize = 0;
|
|
|
|
|
|
|
|
for ( ; cur < limit; cur ++ )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_ULong upper;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
2000-02-13 14:41:56 +01:00
|
|
|
(void)READ_Fields( name_record_fields, cur );
|
2000-05-29 22:37:41 +02:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
upper = (FT_ULong)( cur->stringOffset + cur->stringLength );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( upper > storageSize )
|
|
|
|
storageSize = upper;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( storageSize > 0 )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* allocate the name storage area in memory, then read it */
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( ALLOC( names->storage, storageSize ) ||
|
1999-12-17 00:11:37 +01:00
|
|
|
FILE_Read_At( table_pos + names->storageOffset,
|
|
|
|
(void*)names->storage, storageSize ) )
|
|
|
|
goto Exit;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Go through and assign the string pointers to the name records. */
|
|
|
|
{
|
|
|
|
TT_NameRec* cur = names->names;
|
|
|
|
TT_NameRec* limit = cur + names->numNameRecords;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; cur < limit; cur++ )
|
|
|
|
cur->string = names->storage + cur->stringOffset;
|
|
|
|
}
|
|
|
|
|
2000-05-17 01:44:38 +02:00
|
|
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* Print Name Record Table in case of debugging */
|
|
|
|
{
|
|
|
|
TT_NameRec* cur = names->names;
|
|
|
|
TT_NameRec* limit = cur + names->numNameRecords;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; cur < limit; cur++ )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt j;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
|
|
|
FT_TRACE3(( "%d %d %x %d\n ",
|
1999-12-17 00:11:37 +01:00
|
|
|
cur->platformID,
|
|
|
|
cur->encodingID,
|
|
|
|
cur->languageID,
|
|
|
|
cur->nameID ));
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* I know that M$ encoded strings are Unicode, */
|
|
|
|
/* but this works reasonable well for debugging purposes. */
|
|
|
|
if ( cur->string )
|
|
|
|
for ( j = 0; j < cur->stringLength; j++ )
|
|
|
|
{
|
2000-07-02 02:27:53 +02:00
|
|
|
FT_Char c = *( cur->string + j );
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
if ( (FT_Byte)c < 128 )
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_TRACE3(( "%c", c ));
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_TRACE3(( "\n" ));
|
|
|
|
|
|
|
|
#endif /* FT_DEBUG_LEVEL_TRACE */
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
FT_TRACE2(( "loaded\n" ));
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Free_Names */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Frees the name records. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
|
|
|
void TT_Free_Names( TT_Face face )
|
|
|
|
{
|
- MAJOR INTERNAL REDESIGN:
A lot of internal modifications have been performed lately on the
source in order to provide the following enhancements:
- more generic module support:
The FT_Module type is now defined to represent a handle to a given
module. The file <freetype/ftmodule.h> contains the FT_Module_Class
definition, as well as the module-loading public API
The FT_Driver type is still defined, and still represents a pointer
to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module,
FT_Get_Driver by FT_Get_Module, etc..
- support for generic glyph image types:
The FT_Renderer type is a pointer to a module used to perform various
operations on glyph image.
Each renderer is capable of handling images in a single format
(e.g. ft_glyph_format_outline). Its functions are used to:
- transform an glyph image
- render a glyph image into a bitmap
- return the control box (dimensions) of a given glyph image
The scan converters "ftraster.c" and "ftgrays.c" have been moved
to the new directory "src/renderer", and are used to provide two
default renderer modules.
One corresponds to the "standard" scan-converter, the other to the
"smooth" one.
The current renderer can be set through the new function
FT_Set_Renderer.
The old raster-related function FT_Set_Raster, FT_Get_Raster and
FT_Set_Raster_Mode have now disappeared, in favor of the new:
FT_Get_Renderer
FT_Set_Renderer
see the file <freetype/ftrender.h> for more details..
These changes were necessary to properly support different scalable
formats in the future, like bi-color glyphs, etc..
- glyph loader object:
A new internal object, called a 'glyph loader' has been introduced
in the base layer. It is used by all scalable format font drivers
to load glyphs and composites.
This object has been created to reduce the code size of each driver,
as each one of them basically re-implemented its functionality.
See <freetype/internal/ftobjs.h> and the FT_GlyphLoader type for
more information..
- FT_GlyphSlot had new fields:
In order to support extended features (see below), the FT_GlyphSlot
structure has a few new fields:
linearHoriAdvance: this field gives the linearly scaled (i.e.
scaled but unhinted) advance width for the glyph,
expressed as a 16.16 fixed pixel value. This
is useful to perform WYSIWYG text.
linearVertAdvance: this field gives the linearly scaled advance
height for the glyph (relevant in vertical glyph
layouts only). This is useful to perform
WYSIWYG text.
Note that the two above field replace the removed "metrics2" field
in the glyph slot.
advance: this field is a vector that gives the transformed
advance for the glyph. By default, it corresponds
to the advance width, unless FT_LOAD_VERTICAL_LAYOUT
was specified when calling FT_Load_Glyph or FT_Load_Char
bitmap_left: this field gives the distance in integer pixels from
the current pen position to the left-most pixel of
a glyph image WHEN IT IS A BITMAP. It is only valid
when the "format" field is set to
"ft_glyph_format_bitmap", for example, after calling
the new function FT_Render_Glyph.
bitmap_top: this field gives the distance in integer pixels from
the current pen position (located on the baseline) to
the top-most pixel of the glyph image WHEN IT IS A
BITMAP. Positive values correspond to upwards Y.
loader: this is a new private field for the glyph slot. Client
applications should not touch it..
- support for transforms and direct rendering in FT_Load_Glyph:
Most of the functionality found in <freetype/ftglyph.h> has been
moved to the core library. Hence, the following:
- a transform can be specified for a face through FT_Set_Transform.
this transform is applied by FT_Load_Glyph to scalable glyph images
(i.e. NOT TO BITMAPS) before the function returns, unless the
bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags..
- once a glyph image has been loaded, it can be directly converted to
a bitmap by using the new FT_Render_Glyph function. Note that this
function takes the glyph image from the glyph slot, and converts
it to a bitmap whose properties are returned in "face.glyph.bitmap",
"face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original
native image might be lost after the conversion.
- when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph
and FT_Load_Char functions will call FT_Render_Glyph automatically
when needed.
2000-06-22 02:17:42 +02:00
|
|
|
FT_Memory memory = face->root.driver->root.memory;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_NameTable* names = &face->name_table;
|
|
|
|
|
|
|
|
|
|
|
|
/* free strings table */
|
|
|
|
FREE( names->names );
|
|
|
|
|
|
|
|
/* free strings storage */
|
|
|
|
FREE( names->storage );
|
|
|
|
|
|
|
|
names->numNameRecords = 0;
|
|
|
|
names->format = 0;
|
|
|
|
names->storageOffset = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_CMap */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the cmap directory in a face object. The cmaps itselves are */
|
|
|
|
/* loaded on demand in the `ttcmap.c' module. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
2000-06-05 07:26:15 +02:00
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: A handle to the input stream. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_CMap( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Memory memory = stream->memory;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long table_start;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_CMapDir cmap_dir;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
const FT_Frame_Field cmap_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 4 ),
|
|
|
|
FT_FRAME_USHORT( TT_CMapDir, tableVersionNumber ),
|
|
|
|
FT_FRAME_USHORT( TT_CMapDir, numCMaps ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
|
|
|
|
|
|
|
const FT_Frame_Field cmap_rec_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 6 ),
|
|
|
|
FT_FRAME_USHORT( TT_CMapTable, format ),
|
|
|
|
FT_FRAME_USHORT( TT_CMapTable, length ),
|
|
|
|
FT_FRAME_USHORT( TT_CMapTable, version ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
2000-02-13 14:41:56 +01:00
|
|
|
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_TRACE2(( "CMaps " ));
|
|
|
|
|
|
|
|
error = face->goto_table( face, TTAG_cmap, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
error = TT_Err_CMap_Table_Missing;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
table_start = FILE_Pos();
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( cmap_fields, &cmap_dir ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-07-02 02:27:53 +02:00
|
|
|
/* reserve space in face table for cmap tables */
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( ALLOC_ARRAY( face->charmaps,
|
|
|
|
cmap_dir.numCMaps,
|
|
|
|
TT_CharMapRec ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
face->num_charmaps = cmap_dir.numCMaps;
|
|
|
|
{
|
|
|
|
TT_CharMap charmap = face->charmaps;
|
|
|
|
TT_CharMap limit = charmap + face->num_charmaps;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
2000-02-13 14:41:56 +01:00
|
|
|
/* read the header of each charmap first */
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( ACCESS_Frame( face->num_charmaps * 8L ) )
|
|
|
|
goto Exit;
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; charmap < limit; charmap++ )
|
|
|
|
{
|
|
|
|
TT_CMapTable* cmap;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
charmap->root.face = (FT_Face)face;
|
|
|
|
cmap = &charmap->cmap;
|
|
|
|
|
|
|
|
cmap->loaded = FALSE;
|
|
|
|
cmap->platformID = GET_UShort();
|
|
|
|
cmap->platformEncodingID = GET_UShort();
|
2000-06-16 21:34:52 +02:00
|
|
|
cmap->offset = (FT_ULong)GET_Long();
|
2000-02-13 14:41:56 +01:00
|
|
|
}
|
2000-06-05 07:26:15 +02:00
|
|
|
|
2000-02-13 14:41:56 +01:00
|
|
|
FORGET_Frame();
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-02-13 14:41:56 +01:00
|
|
|
/* now read the rest of each table */
|
|
|
|
for ( charmap = face->charmaps; charmap < limit; charmap++ )
|
|
|
|
{
|
|
|
|
TT_CMapTable* cmap = &charmap->cmap;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
if ( FILE_Seek( table_start + (FT_Long)cmap->offset ) ||
|
2000-02-13 14:41:56 +01:00
|
|
|
READ_Fields( cmap_rec_fields, cmap ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Exit;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
cmap->offset = FILE_Pos();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FT_TRACE2(( "loaded\n" ));
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_OS2 */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the OS2 table. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: A handle to the input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_OS2( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_OS2* os2;
|
2000-05-29 22:37:41 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
const FT_Frame_Field os2_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 78 ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, version ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, xAvgCharWidth ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usWeightClass ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usWidthClass ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, fsType ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, ySubscriptXSize ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, ySubscriptYSize ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, ySubscriptXOffset ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, ySubscriptYOffset ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, ySuperscriptXSize ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, ySuperscriptYSize ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, ySuperscriptXOffset ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, ySuperscriptYOffset ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, yStrikeoutSize ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, yStrikeoutPosition ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, sFamilyClass ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[0] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[1] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[2] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[3] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[4] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[5] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[6] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[7] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[8] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, panose[9] ),
|
|
|
|
FT_FRAME_ULONG( TT_OS2, ulUnicodeRange1 ),
|
|
|
|
FT_FRAME_ULONG( TT_OS2, ulUnicodeRange2 ),
|
|
|
|
FT_FRAME_ULONG( TT_OS2, ulUnicodeRange3 ),
|
|
|
|
FT_FRAME_ULONG( TT_OS2, ulUnicodeRange4 ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, achVendID[0] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, achVendID[1] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, achVendID[2] ),
|
|
|
|
FT_FRAME_BYTE( TT_OS2, achVendID[3] ),
|
|
|
|
|
|
|
|
FT_FRAME_USHORT( TT_OS2, fsSelection ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usFirstCharIndex ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usLastCharIndex ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, sTypoAscender ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, sTypoDescender ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, sTypoLineGap ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usWinAscent ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usWinDescent ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
|
|
|
|
|
|
|
const FT_Frame_Field os2_fields_extra[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 8 ),
|
|
|
|
FT_FRAME_ULONG( TT_OS2, ulCodePageRange1 ),
|
|
|
|
FT_FRAME_ULONG( TT_OS2, ulCodePageRange2 ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
|
|
|
|
|
|
|
const FT_Frame_Field os2_fields_extra2[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 10 ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, sxHeight ),
|
|
|
|
FT_FRAME_SHORT( TT_OS2, sCapHeight ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usDefaultChar ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usBreakChar ),
|
|
|
|
FT_FRAME_USHORT( TT_OS2, usMaxContext ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
FT_TRACE2(( "OS/2 Table " ));
|
|
|
|
|
|
|
|
/* We now support old Mac fonts where the OS/2 table doesn't */
|
|
|
|
/* exist. Simply put, we set the `version' field to 0xFFFF */
|
|
|
|
/* and test this value each time we need to access the table. */
|
|
|
|
error = face->goto_table( face, TTAG_OS2, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2000-07-02 02:27:53 +02:00
|
|
|
FT_TRACE2(( "is missing!\n" ));
|
1999-12-17 00:11:37 +01:00
|
|
|
face->os2.version = 0xFFFF;
|
|
|
|
error = TT_Err_Ok;
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
2000-02-13 14:41:56 +01:00
|
|
|
os2 = &face->os2;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( os2_fields, os2 ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
os2->ulCodePageRange1 = 0;
|
|
|
|
os2->ulCodePageRange2 = 0;
|
|
|
|
|
|
|
|
if ( os2->version >= 0x0001 )
|
|
|
|
{
|
|
|
|
/* only version 1 tables */
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( os2_fields_extra, os2 ) )
|
|
|
|
goto Exit;
|
2000-05-02 13:01:49 +02:00
|
|
|
|
|
|
|
if ( os2->version >= 0x0002 )
|
|
|
|
{
|
|
|
|
/* only version 2 tables */
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( os2_fields_extra2, os2 ) )
|
|
|
|
goto Exit;
|
2000-05-02 13:01:49 +02:00
|
|
|
}
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FT_TRACE2(( "loaded\n" ));
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Postscript */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the Postscript table. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: A handle to the input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_PostScript( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_Postscript* post = &face->postscript;
|
2000-05-29 22:37:41 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
static const FT_Frame_Field post_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 32 ),
|
|
|
|
FT_FRAME_ULONG( TT_Postscript, FormatType ),
|
|
|
|
FT_FRAME_ULONG( TT_Postscript, italicAngle ),
|
|
|
|
FT_FRAME_SHORT( TT_Postscript, underlinePosition ),
|
|
|
|
FT_FRAME_SHORT( TT_Postscript, underlineThickness ),
|
|
|
|
FT_FRAME_ULONG( TT_Postscript, isFixedPitch ),
|
|
|
|
FT_FRAME_ULONG( TT_Postscript, minMemType42 ),
|
|
|
|
FT_FRAME_ULONG( TT_Postscript, maxMemType42 ),
|
|
|
|
FT_FRAME_ULONG( TT_Postscript, minMemType1 ),
|
|
|
|
FT_FRAME_ULONG( TT_Postscript, maxMemType1 ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
FT_TRACE2(( "PostScript " ));
|
|
|
|
|
|
|
|
error = face->goto_table( face, TTAG_post, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
1999-12-17 00:11:37 +01:00
|
|
|
return TT_Err_Post_Table_Missing;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( post_fields, post ) )
|
|
|
|
return error;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* we don't load the glyph names, we do that in another */
|
|
|
|
/* module (ttpost). */
|
|
|
|
FT_TRACE2(( "loaded\n" ));
|
|
|
|
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-05-18 18:18:05 +02:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_PCLT */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the PCL 5 Table. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: A handle to the input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
2000-05-18 18:18:05 +02:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_PCLT( TT_Face face,
|
2000-05-18 18:18:05 +02:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-05 07:26:15 +02:00
|
|
|
static const FT_Frame_Field pclt_fields[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 20 ),
|
|
|
|
FT_FRAME_ULONG ( TT_PCLT, Version ),
|
|
|
|
FT_FRAME_ULONG ( TT_PCLT, FontNumber ),
|
|
|
|
FT_FRAME_USHORT( TT_PCLT, Pitch ),
|
|
|
|
FT_FRAME_USHORT( TT_PCLT, xHeight ),
|
|
|
|
FT_FRAME_USHORT( TT_PCLT, Style ),
|
|
|
|
FT_FRAME_USHORT( TT_PCLT, TypeFamily ),
|
|
|
|
FT_FRAME_USHORT( TT_PCLT, CapHeight ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
2000-06-05 16:32:32 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
static const FT_Frame_Field pclt_fields2[] =
|
|
|
|
{
|
|
|
|
FT_FRAME_START( 4 ),
|
|
|
|
FT_FRAME_CHAR( TT_PCLT, StrokeWeight ),
|
|
|
|
FT_FRAME_CHAR( TT_PCLT, WidthType ),
|
|
|
|
FT_FRAME_BYTE( TT_PCLT, SerifStyle ),
|
|
|
|
FT_FRAME_BYTE( TT_PCLT, Reserved ),
|
|
|
|
FT_FRAME_END
|
|
|
|
};
|
2000-06-05 16:32:32 +02:00
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
2000-06-05 07:26:15 +02:00
|
|
|
TT_PCLT* pclt = &face->pclt;
|
|
|
|
|
2000-06-05 16:32:32 +02:00
|
|
|
|
2000-05-18 18:18:05 +02:00
|
|
|
FT_TRACE2(( "PCLT " ));
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
/* optional table */
|
|
|
|
error = face->goto_table( face, TTAG_PCLT, stream, 0 );
|
|
|
|
if ( error )
|
|
|
|
{
|
|
|
|
FT_TRACE2(( "missing (optional)\n" ));
|
|
|
|
pclt->Version = 0;
|
|
|
|
return TT_Err_Ok;
|
|
|
|
}
|
2000-06-05 16:32:32 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( READ_Fields( pclt_fields, pclt ) ||
|
|
|
|
FILE_Read ( pclt->TypeFace, 16 ) ||
|
|
|
|
FILE_Read ( pclt->CharacterComplement, 8 ) ||
|
|
|
|
FILE_Read ( pclt->FileName, 6 ) ||
|
|
|
|
READ_Fields( pclt_fields2, pclt ) )
|
2000-05-18 18:18:05 +02:00
|
|
|
goto Exit;
|
2000-06-05 16:32:32 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_TRACE2(( "loaded\n" ));
|
|
|
|
|
2000-06-05 16:32:32 +02:00
|
|
|
Exit:
|
2000-06-05 07:26:15 +02:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2000-05-18 18:18:05 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Gasp */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
2000-07-02 02:27:53 +02:00
|
|
|
/* Loads the `gasp' table into a face object. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Gasp( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Memory memory = stream->memory;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt j,num_ranges;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_GaspRange* gaspranges;
|
|
|
|
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
FT_TRACE2(( "TT_Load_Gasp: %08p\n", face ));
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
/* the gasp table is optional */
|
|
|
|
error = face->goto_table( face, TTAG_gasp, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
|
|
|
return TT_Err_Ok;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
if ( ACCESS_Frame( 4L ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
face->gasp.version = GET_UShort();
|
|
|
|
face->gasp.numRanges = GET_UShort();
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
|
|
|
num_ranges = face->gasp.numRanges;
|
|
|
|
FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
|
|
|
|
|
|
|
|
if ( ALLOC_ARRAY( gaspranges, num_ranges, TT_GaspRange ) ||
|
2000-06-05 07:26:15 +02:00
|
|
|
ACCESS_Frame( num_ranges * 4L ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
face->gasp.gaspRanges = gaspranges;
|
|
|
|
|
|
|
|
for ( j = 0; j < num_ranges; j++ )
|
|
|
|
{
|
|
|
|
gaspranges[j].maxPPEM = GET_UShort();
|
|
|
|
gaspranges[j].gaspFlag = GET_UShort();
|
|
|
|
|
|
|
|
FT_TRACE3(( " [max:%d flag:%d]",
|
2000-06-05 07:26:15 +02:00
|
|
|
gaspranges[j].maxPPEM,
|
|
|
|
gaspranges[j].gaspFlag ));
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
FT_TRACE3(( "\n" ));
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
FT_TRACE2(( "GASP loaded\n" ));
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Kern */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the first kerning table with format 0 in the font. Only */
|
|
|
|
/* accepts the first horizontal kerning table. Developers should use */
|
|
|
|
/* the `ftxkern' extension to access other kerning tables in the font */
|
|
|
|
/* file, if they really want to. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: The input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Kern( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Memory memory = stream->memory;
|
|
|
|
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt n, num_tables, version;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
2000-07-02 02:27:53 +02:00
|
|
|
/* the kern table is optional; exit silently if it is missing */
|
1999-12-17 00:11:37 +01:00
|
|
|
error = face->goto_table( face, TTAG_kern, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
|
|
|
return TT_Err_Ok;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( ACCESS_Frame( 4L ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
version = GET_UShort();
|
|
|
|
num_tables = GET_UShort();
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
|
|
|
for ( n = 0; n < num_tables; n++ )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt coverage;
|
|
|
|
FT_UInt length;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
|
|
|
if ( ACCESS_Frame( 6L ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
version = GET_UShort(); /* version */
|
|
|
|
length = GET_UShort() - 6; /* substract header length */
|
|
|
|
coverage = GET_UShort();
|
|
|
|
|
|
|
|
FORGET_Frame();
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( coverage == 0x0001 )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_UInt num_pairs;
|
1999-12-17 00:11:37 +01:00
|
|
|
TT_Kern_0_Pair* pair;
|
|
|
|
TT_Kern_0_Pair* limit;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
|
|
|
/* found a horizontal format 0 kerning table! */
|
|
|
|
if ( ACCESS_Frame( 8L ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
num_pairs = GET_UShort();
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* skip the rest */
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
|
|
|
/* allocate array of kerning pairs */
|
|
|
|
if ( ALLOC_ARRAY( face->kern_pairs, num_pairs, TT_Kern_0_Pair ) ||
|
|
|
|
ACCESS_Frame( 6L * num_pairs ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
pair = face->kern_pairs;
|
|
|
|
limit = pair + num_pairs;
|
|
|
|
for ( ; pair < limit; pair++ )
|
|
|
|
{
|
|
|
|
pair->left = GET_UShort();
|
|
|
|
pair->right = GET_UShort();
|
|
|
|
pair->value = GET_UShort();
|
|
|
|
}
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
|
|
|
face->num_kern_pairs = num_pairs;
|
|
|
|
face->kern_table_index = n;
|
|
|
|
goto Exit;
|
|
|
|
}
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
if ( FILE_Skip( length ) )
|
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no kern table found -- doesn't matter */
|
|
|
|
face->kern_table_index = -1;
|
|
|
|
face->num_kern_pairs = 0;
|
|
|
|
face->kern_pairs = NULL;
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Load_Hdmx */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Loads the horizontal device metrics table. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* stream :: A handle to the input stream. */
|
|
|
|
/* */
|
|
|
|
/* <Return> */
|
2000-06-25 08:47:11 +02:00
|
|
|
/* FreeType error code. 0 means success. */
|
1999-12-17 00:11:37 +01:00
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error TT_Load_Hdmx( TT_Face face,
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Stream stream )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Error error;
|
1999-12-17 00:11:37 +01:00
|
|
|
FT_Memory memory = stream->memory;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
TT_Hdmx* hdmx = &face->hdmx;
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Long num_glyphs;
|
|
|
|
FT_Long record_size;
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
hdmx->version = 0;
|
|
|
|
hdmx->num_records = 0;
|
|
|
|
hdmx->records = 0;
|
|
|
|
|
|
|
|
/* this table is optional */
|
|
|
|
error = face->goto_table( face, TTAG_hdmx, stream, 0 );
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( error )
|
|
|
|
return TT_Err_Ok;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( ACCESS_Frame( 8L ) )
|
|
|
|
goto Exit;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
hdmx->version = GET_UShort();
|
|
|
|
hdmx->num_records = GET_Short();
|
|
|
|
record_size = GET_Long();
|
|
|
|
|
|
|
|
FORGET_Frame();
|
|
|
|
|
|
|
|
/* Only recognize format 0 */
|
|
|
|
if ( hdmx->version != 0 )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
if ( ALLOC_ARRAY( hdmx->records, hdmx->num_records, TT_HdmxRec ) )
|
|
|
|
goto Exit;
|
|
|
|
|
|
|
|
num_glyphs = face->root.num_glyphs;
|
|
|
|
record_size -= num_glyphs + 2;
|
|
|
|
|
|
|
|
{
|
|
|
|
TT_HdmxRec* cur = hdmx->records;
|
|
|
|
TT_HdmxRec* limit = cur + hdmx->num_records;
|
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( ; cur < limit; cur++ )
|
|
|
|
{
|
|
|
|
/* read record */
|
|
|
|
if ( READ_Byte( cur->ppem ) ||
|
|
|
|
READ_Byte( cur->max_width ) )
|
|
|
|
goto Exit;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( ALLOC( cur->widths, num_glyphs ) ||
|
1999-12-17 00:11:37 +01:00
|
|
|
FILE_Read( cur->widths, num_glyphs ) )
|
|
|
|
goto Exit;
|
2000-05-17 01:44:38 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* skip padding bytes */
|
2000-06-05 07:26:15 +02:00
|
|
|
if ( record_size > 0 && FILE_Skip( record_size ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Exit:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* <Function> */
|
|
|
|
/* TT_Free_Hdmx */
|
|
|
|
/* */
|
|
|
|
/* <Description> */
|
|
|
|
/* Frees the horizontal device metrics table. */
|
|
|
|
/* */
|
|
|
|
/* <Input> */
|
|
|
|
/* face :: A handle to the target face object. */
|
|
|
|
/* */
|
|
|
|
LOCAL_FUNC
|
|
|
|
void TT_Free_Hdmx( TT_Face face )
|
|
|
|
{
|
|
|
|
if ( face )
|
|
|
|
{
|
2000-06-16 21:34:52 +02:00
|
|
|
FT_Int n;
|
- MAJOR INTERNAL REDESIGN:
A lot of internal modifications have been performed lately on the
source in order to provide the following enhancements:
- more generic module support:
The FT_Module type is now defined to represent a handle to a given
module. The file <freetype/ftmodule.h> contains the FT_Module_Class
definition, as well as the module-loading public API
The FT_Driver type is still defined, and still represents a pointer
to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module,
FT_Get_Driver by FT_Get_Module, etc..
- support for generic glyph image types:
The FT_Renderer type is a pointer to a module used to perform various
operations on glyph image.
Each renderer is capable of handling images in a single format
(e.g. ft_glyph_format_outline). Its functions are used to:
- transform an glyph image
- render a glyph image into a bitmap
- return the control box (dimensions) of a given glyph image
The scan converters "ftraster.c" and "ftgrays.c" have been moved
to the new directory "src/renderer", and are used to provide two
default renderer modules.
One corresponds to the "standard" scan-converter, the other to the
"smooth" one.
The current renderer can be set through the new function
FT_Set_Renderer.
The old raster-related function FT_Set_Raster, FT_Get_Raster and
FT_Set_Raster_Mode have now disappeared, in favor of the new:
FT_Get_Renderer
FT_Set_Renderer
see the file <freetype/ftrender.h> for more details..
These changes were necessary to properly support different scalable
formats in the future, like bi-color glyphs, etc..
- glyph loader object:
A new internal object, called a 'glyph loader' has been introduced
in the base layer. It is used by all scalable format font drivers
to load glyphs and composites.
This object has been created to reduce the code size of each driver,
as each one of them basically re-implemented its functionality.
See <freetype/internal/ftobjs.h> and the FT_GlyphLoader type for
more information..
- FT_GlyphSlot had new fields:
In order to support extended features (see below), the FT_GlyphSlot
structure has a few new fields:
linearHoriAdvance: this field gives the linearly scaled (i.e.
scaled but unhinted) advance width for the glyph,
expressed as a 16.16 fixed pixel value. This
is useful to perform WYSIWYG text.
linearVertAdvance: this field gives the linearly scaled advance
height for the glyph (relevant in vertical glyph
layouts only). This is useful to perform
WYSIWYG text.
Note that the two above field replace the removed "metrics2" field
in the glyph slot.
advance: this field is a vector that gives the transformed
advance for the glyph. By default, it corresponds
to the advance width, unless FT_LOAD_VERTICAL_LAYOUT
was specified when calling FT_Load_Glyph or FT_Load_Char
bitmap_left: this field gives the distance in integer pixels from
the current pen position to the left-most pixel of
a glyph image WHEN IT IS A BITMAP. It is only valid
when the "format" field is set to
"ft_glyph_format_bitmap", for example, after calling
the new function FT_Render_Glyph.
bitmap_top: this field gives the distance in integer pixels from
the current pen position (located on the baseline) to
the top-most pixel of the glyph image WHEN IT IS A
BITMAP. Positive values correspond to upwards Y.
loader: this is a new private field for the glyph slot. Client
applications should not touch it..
- support for transforms and direct rendering in FT_Load_Glyph:
Most of the functionality found in <freetype/ftglyph.h> has been
moved to the core library. Hence, the following:
- a transform can be specified for a face through FT_Set_Transform.
this transform is applied by FT_Load_Glyph to scalable glyph images
(i.e. NOT TO BITMAPS) before the function returns, unless the
bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags..
- once a glyph image has been loaded, it can be directly converted to
a bitmap by using the new FT_Render_Glyph function. Note that this
function takes the glyph image from the glyph slot, and converts
it to a bitmap whose properties are returned in "face.glyph.bitmap",
"face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original
native image might be lost after the conversion.
- when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph
and FT_Load_Char functions will call FT_Render_Glyph automatically
when needed.
2000-06-22 02:17:42 +02:00
|
|
|
FT_Memory memory = face->root.driver->root.memory;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-06-05 07:26:15 +02:00
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
for ( n = 0; n < face->hdmx.num_records; n++ )
|
|
|
|
FREE( face->hdmx.records[n].widths );
|
|
|
|
|
|
|
|
FREE( face->hdmx.records );
|
|
|
|
face->hdmx.num_records = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* END */
|