Files
freetype/lib/extend/ftxwidth.c
2023-08-27 18:03:45 +02:00

186 lines
6.2 KiB
C

/*******************************************************************
*
* ftxwidth.c 1.0
*
* Glyph Widths (and Heights) fast retrieval extension
*
* Copyright 1996-1999 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
* modified and distributed under the terms of the FreeType project
* license, LICENSE.TXT. By continuing to use, modify, or distribute
* this file you indicate that you have read the license and
* understand and accept it fully.
*
*
* This extension is used to parse the "glyf" table of a TrueType
* file in order to extract the bbox of a given range of glyphs.
*
* The bbox is then used to build font unit widths and height
* that are returned in two parallel arrays.
*
* This extension is needed by the FreeType/2 OS/2 Font Driver.
*
******************************************************************/
#include "ftxwidth.h"
#include "ttdebug.h"
#include "ttobjs.h"
#include "ttfile.h"
#include "tttags.h"
#include "ttload.h"
/* Required by the tracing mode */
#undef TT_COMPONENT
#define TT_COMPONENT trace_any
/******************************************************************/
/* */
/* Function: TT_Get_Face_Widths */
/* */
/* Description: Returns the widths and/or heights of a given */
/* range of glyphs for a face. */
/* */
/* Input: */
/* face :: face handle */
/* */
/* first_glyph :: first glyph in range */
/* */
/* last_glyph :: last glyph in range */
/* */
/* widths :: address of table receiving the widths */
/* expressed in font units (ushorts). Set */
/* this parameter to NULL if you're not */
/* interested by these values. */
/* */
/* heights :: address of table receiving the heights */
/* expressed in font units (ushorts). Set */
/* this parameter to NULL if you're not */
/* interested by these values. */
/* */
/* Returns: */
/* Error code */
/* */
/* */
/******************************************************************/
EXPORT_FUNC
TT_Error TT_Get_Face_Widths( TT_Face face,
TT_UShort first_glyph,
TT_UShort last_glyph,
TT_UShort* widths,
TT_UShort* heights )
{
DEFINE_ALL_LOCALS;
PFace faze = HANDLE_Face(face);
UShort n;
Long table;
ULong glyf_offset; /* offset of glyph table in file */
UShort zero_width = 0; /* width of glyph 0 */
UShort zero_height = 0; /* height of glyph 0 */
Bool zero_loaded = 0;
#ifndef TT_HUGE_PTR
PStorage locations;
#else
Storage TT_HUGE_PTR * locations;
#endif
TT_BBox bbox;
if ( !faze )
return TT_Err_Invalid_Face_Handle;
if ( last_glyph >= faze->numGlyphs ||
first_glyph > last_glyph )
return TT_Err_Invalid_Argument;
/* find "glyf" table */
table = TT_LookUp_Table( faze, TTAG_glyf );
if ( table < 0 )
{
PERROR(( "ERROR: there is no glyph table in this font file!\n" ));
return TT_Err_Glyf_Table_Missing;
}
glyf_offset = faze->dirTables[table].Offset;
/* now access stream */
if ( USE_Stream( faze->stream, stream ) )
return error;
locations = faze->glyphLocations + first_glyph;
/* loop to load each glyph in the range */
for ( n = first_glyph; n <= last_glyph; n++ )
{
if ( n + 1 < faze->numGlyphs &&
locations[0] == locations[1] )
{
/* Note : Glyph 0 is always used to indicate a missing glyph */
/* in a range. We must thus return its width and height */
/* where appropriate when we find an undefined glyph. */
if ( zero_loaded == 0 )
{
if ( FILE_Seek( glyf_offset + faze->glyphLocations[0] ) ||
ACCESS_Frame( 10L ) )
goto Fail;
(void)GET_Short(); /* skip number of contours */
bbox.xMin = GET_Short();
bbox.yMin = GET_Short();
bbox.xMax = GET_Short();
bbox.yMax = GET_Short();
FORGET_Frame();
zero_width = (UShort)(bbox.xMax - bbox.xMin);
zero_height = (UShort)(bbox.yMax - bbox.yMin);
zero_loaded = 1;
}
if ( widths )
*widths++ = zero_width;
if ( heights )
*heights++ = zero_height;
}
else
{
/* normal glyph, read header */
if ( FILE_Seek( glyf_offset + locations[0] ) ||
ACCESS_Frame( 10L ) )
goto Fail;
(void)GET_Short(); /* skip number of contours */
bbox.xMin = GET_Short();
bbox.yMin = GET_Short();
bbox.xMax = GET_Short();
bbox.yMax = GET_Short();
FORGET_Frame();
if ( widths )
*widths++ = (UShort)(bbox.xMax - bbox.xMin);
if ( heights )
*heights++ = (UShort)(bbox.yMax - bbox.yMin);
}
}
Fail:
DONE_Stream( stream );
return error;
}
/* END */