www.xbdev.net
xbdev - software development
Saturday December 7, 2024
Home | Contact | Support | Image File Format... Storing Graphics using Bits and Bytes.. | TTF File Format... TTF Image Format.. ..
     
 

TTF File Format...

TTF Image Format.. ..

 

TTF File Format



The TrueType Font (TTF) format is a widely used font file format in digital typography, designed by Apple and Microsoft.

It utilizes quadratic Bézier curves to define glyph shapes, allowing for smooth rendering at various sizes.

TTF files contain data such as glyph outlines, metrics, and hinting instructions, ensuring consistent appearance across different devices and resolutions. Additionally, TrueType fonts support advanced typographic features like ligatures, kerning pairs, and stylistic alternates, making them versatile for various design needs.

TTF files are commonly used on both Windows and macOS platforms, as well as in web typography due to their widespread compatibility and compact file size.


/******************************************************************************/
/*                                                                            */
/*  File: ttf.h                                                               */
/*  Author: bkenwright@xbdev.net                                              */
/*  URL: www.xbdev.net                                                        */
/*                                                                            */
/******************************************************************************/
/*
    ttf font file format reader

    Desc? Well this whole file reads the ttf font file in, parses it and stores
    it in various structures.

    You pass it a stTTF structure, and it fills it in with all the information,
    such as supported characters, glyfs, etc

    File to use:

    void ReadTTF(const char* szFileName, stTTF* ttf)


*/
/******************************************************************************/

#pragma once

#include "dxdebug.h"

const int MAXFLAGS 1500;

typedef short int        int16;
typedef int                int32;
typedef unsigned int    uint32;
typedef unsigned short  uint16;
typedef unsigned char    uchar8;
typedef unsigned char   uint8;
typedef short            FWord// - 16-bit signed integer that describes a quantity in FUnits, 
                               //    the smallest measurable distance in em space. 
typedef unsigned int    Fixed;
typedef double            longDateTime;

#pragma pack(1)
struct stOffsetSubTable
{
    
uint32 scaler;            // type A tag to indicate the OFA scaler to be used to 
                            // rasterize this font; see the note on the scaler type below for more information. 
    
uint16 numTables;        // number of tables 
    
uint16 searchRange;        // (maximum power of 2 <= numTables)*16 
    
uint16 entrySelector;    // log2(maximum power of 2 <= numTables) 
    
uint16 rangeShift;        // numTables*16-searchRange 
};
#pragma pack()


struct stTableDirectory
{
    
uint32 tag;                // 4-byte identifier 
    
uint32 checkSum;        // checksum for this table 
    
uint32 offset;            // offset from beginning of sfnt 
    
uint32 length;            // length of this table in byte (actual length not padded length) 
};


struct stFontDirectory
{
    
stFontDirectory()  { m_tableDirectory=NULL;        }
    ~
stFontDirectory() { delete[] m_tableDirectory; }

    
stOffsetSubTable    m_offsetSubTable;
    
stTableDirectory*    m_tableDirectory;
};

struct stCMAPTable
{
    
uint16 format;        // hopefully 0 for easy fonts
    
uint16 length;        // 262 for format 0
    
uint16 language;    // language-independent
};

struct stCMAPSubTable
{
    
uint16 platformID;            // Platform identifier 
    
uint16 platformSpecificID;    // Platform-specific encoding identifier 
    
uint32 offset;                // Offset of the mapping table 

    
stCMAPTable table;            // Offset points to this
};

struct stCMAP
{
    
stCMAP()  
    { 
        
subTables=NULL

        
numGlyphIndexArray=0glyphIndexArray=NULL;
    }
    ~
stCMAP() 
    { 
        if (
subTablesdelete[] subTables
        
subTables=NULL

        if (
glyphIndexArraydelete[] glyphIndexArray
        
glyphIndexArray=NULL;
    }

    
uint16 version;            // Version number (Set to zero) 
    
uint16 numberSubtables;    // Number of encoding subtables 

    
stCMAPSubTablesubTables;

    
int     numGlyphIndexArray;
    
uint8*  glyphIndexArray;
};

struct stGlyfDescription
{
    
int16 numberOfContours;        // If the number of contours is positive or zero, it is a single glyph;
                                // If the number of contours is -1, the glyph is compound 
    
FWord xMin;                    // Minimum x for coordinate data 
    
FWord yMin;                    // Minimum y for coordinate data 
    
FWord xMax;                    // Maximum x for coordinate data 
    
FWord yMax;                    // Maximum y for coordinate data 


    // Zero or positive number of contours signals a simple glyph.
    // -1, the glyph is made up of components.
};

struct stGLYFSimple
{
    
stGLYFSimple()
    {
        
instructions        NULL;
        
endPtsOfContours    NULL;
        
flags                NULL;
        
xCoordinates        NULL;
        
yCoordinates        NULL;
    }
    ~
stGLYFSimple()
    {
        
delete[] instructions;            instructions=NULL;
        
delete[] endPtsOfContours;        endPtsOfContours=NULL;
        
delete[] flags;                    flags=NULL;
        
delete[] xCoordinates;            xCoordinates=NULL;
        
delete[] yCoordinates;            yCoordinates=NULL;
    }

    
uint16endPtsOfContours;    // [n] Array of last points of each contour; n is the number of contours; array entries are point indices 
    
uint16 instructionLength;    // Total number of bytes needed for instructions 
    
uint8instructions;        // [instructionLength] Array of instructions for this glyph 
    
int    numFlags;
    
uint8flags;                // [variable] Array of flags 
    
int16xCoordinates;        // uint8 or int16 - Array of x-coordinates; the first is relative to (0,0), others are relative to previous point 
    
int16yCoordinates;        // uint8 or int16 - Array of y-coordinates; the first is relative to (0,0), others are relative to previous point 
};

struct stGLYFCompound
{
    
union
    
{
        
uint16 flags// Component flag 
        
struct
        
{
            
uint16 ARG_1_AND_2_ARE_WORDS    1;    // 0 If set, the arguments are words; 
                                                    // If not set, they are bytes. 
            
uint16 ARGS_ARE_XY_VALUES        1;    // 1 If set, the arguments are xy values; 
                                                    // If not set, they are points. 
            
uint16 ROUND_XY_TO_GRID            1;    // 2 If set, round the xy values to grid; 
                                                    // if not set do not round xy values to grid (relevant only to bit 1 is set) 
            
uint16 WE_HAVE_A_SCALE            1;    // 3 If set, there is a simple scale for the component. 
                                                    // If not set, scale is 1.0. 
                                                    // (this bit is obsolete) 4 (obsolete; set to zero) 
            
uint16 MORE_COMPONENTS            1;    // 5 If set, at least one additional glyph follows this one. 
            
uint16 WE_HAVE_AN_X_AND_Y_SCALE 1;    // 6 If set the x direction will use a different scale than the y direction. 
            
uint16 WE_HAVE_A_TWO_BY_TWO        1;    // 7 If set there is a 2-by-2 transformation that will be used to scale the component. 
            
uint16 WE_HAVE_INSTRUCTIONS        1;    // 8 If set, instructions for the component character follow the last component. 
            
uint16 USE_MY_METRICS            1;    // 9 Use metrics from this component for the compound glyph. 
            
uint16 OVERLAP_COMPOUND            1;    // 10 If set, the components of this compound glyph overlap. 
        
}flagBits;
    };


    
uint16 glyphIndex// Glyph index of component 
    
int32  offset0;
    
int32  offset1;
//    int16, uint16, int8 or uint8 argument1 X-offset for component or point number; type depends on bits 0 and 1 in component flags 
//    int16, uint16, int8 or uint8 argument2 Y-offset for component or point number type depends on bits 0 and 1 in component flags 
//    transformation option One of the transformation options from Table 19 
};

struct stGLYFItem
{
    
stGLYFItem() { m_glyfSimple=NULLm_glyfCompound=NULL; }
    ~
stGLYFItem() 
    { 
        
delete m_glyfSimple;    m_glyfSimple=NULL;
        
delete m_glyfCompound;    m_glyfCompound=NULL
    }

    
stGlyfDescription    m_glyfDescription;
    
// (here follow the data for the simple or compound glyph)
    
stGLYFSimple*        m_glyfSimple;
    
stGLYFCompound*        m_glyfCompound;
};

struct stGLYF
{
    
stGLYF() { glyfItem=NULLnumGlyphs=0; }
    ~
stGLYF() { if (glyfItem) { delete[] glyfItemglyfItem=NULL; }; };

    
int            numGlyphs;        // Set from 'maxp' table
    
stGLYFItemglyfItem;        // Array
};

struct stHEAD
{
    
Fixed version;                // 0x00010000 if (version 1.0) 
    
Fixed fontRevision;            // set by font manufacturer 
    
uint32 checkSumAdjustment;    // To compute: set it to 0, calculate the checksum for the 'head' table and put it in the table directory, sum the entire font as uint32, then store B1B0AFBA - sum. The checksum for the 'head' table will not be wrong. That is OK. 
    
uint32 magicNumber;            // set to 0x5F0F3CF5 
    
uint16 flags;                // bit 0 - y value of 0 specifies baseline
                                //    bit 1 - x position of left most black bit is LSB
                                //    bit 2 - scaled point size and actual point size will differ (i.e. 24 point glyph differs from 12 point glyph scaled by factor of 2)
                                //    bit 3 - use integer scaling instead of fractional
                                //    bit 4 - (used by the Microsoft implementation of the TrueType scaler)
                                //    bit 5 - This bit should be set in fonts that are intended to e laid out vertically, and in which the glyphs have been drawn such that an x-coordinate of 0 corresponds to the desired vertical baseline.
                                //    bit 6 - This bit must be set to zero.
                                //    bit 7 - This bit should be set if the font requires layout for correct linguistic rendering (e.g. Arabic fonts).
                                //    bit 8 - This bit should be set for a GX font which has one or more metamorphosis effects designated as happening by default.
                                //    bit 9 - This bit should be set if the font contains any strong right-to-left glyphs.
                                //    bit 10 - This bit should be set if the font contains Indic-style rearrangement effects.
                                //    bits 11-12 - Defined by Adobe. 
    
uint16 unitsPerEm;            // range from 64 to 16384 
    
longDateTime created;        // international date 
    
longDateTime modified;        // international date 
    
FWord xMin;                 // for all glyph bounding boxes 
    
FWord yMin;                 // for all glyph bounding boxes 
    
FWord xMax;                 // for all glyph bounding boxes 
    
FWord yMax;                 // for all glyph bounding boxes 
    
uint16 macStyle;            // bit 0 bold
                                //    bit 1 italic
                                //    bit 2 underline
                                //    bit 3 outline
                                //    bit 4 shadow
                                //    bit 5 condensed (narrow)
                                //    bit 6 extended 
    
uint16 lowestRecPPEM;        // smallest readable size in pixels 
    
int16 fontDirectionHint;    // 0 Mixed directional glyphs
                                //    1 Only strongly left to right glyphs
                                //    2 Like 1 but also contains neutrals
                                //    -1 Only strongly right to left glyphs
                                //    -2 Like -1 but also contains neutrals 
    
int16 indexToLocFormat;        // 0 for short offsets, 1 for long 
    
int16 glyphDataFormat;        // 0 for current format 
};

struct stLOCA
{
    
stLOCA()  { glyphOffsets=NULL; }
    ~
stLOCA() { delete[] glyphOffsetsglyphOffsets=NULL; }

    
intglyphOffsets;
};

struct stMAXP
{
    
Fixed  version;                    // 0x00010000 (1.0) 
    
uint16 numGlyphs;                // the number of glyphs in the font 
    
uint16 maxPoints;                // points in non-compound glyph 
    
uint16 maxContours;                // contours in non-compound glyph 
    
uint16 maxComponentPoints;        // points in compound glyph 
    
uint16 maxComponentContours;    // contours in compound glyph 
    
uint16 maxZones;                // set to 2 
    
uint16 maxTwilightPoints;        // points used in Twilight Zone (Z0) 
    
uint16 maxStorage;                // number of Storage Area locations 
    
uint16 maxFunctionDefs;            // number of FDEFs 
    
uint16 maxInstructionDefs;        // number of IDEFs 
    
uint16 maxStackElements;        // maximum stack depth 
    
uint16 maxSizeOfInstructions;    // byte count for glyph instructions 
    
uint16 maxComponentElements;    // number of glyphs referenced at top level 
    
uint16 maxComponentDepth;        // levels of recursion, set to 0 if font has only simple glyphs 
};

struct stTTF
{
    
stFontDirectory        m_fontDirectory;
    
stCMAP                m_cmap;
    
stHEAD                m_head;
    
stGLYF                m_glyf;
    
stLOCA                m_loca;
    
stMAXP                m_maxp;
};

inline void SwapEndian(unsigned char *data)
{
    
//do nothing, just needed for completeness
}

inline void SwapEndian(char *data)
{
    
//do nothing, just needed for completeness
}

inline void SwapEndian(unsigned short *data)
{
    *
data=((*data&0x00ff)<<8)
        |((*
data&0xff00)>>8);
}

inline void SwapEndian(short *data)
{
    *
data=((*data&0x00ff)<<8)
        |((*
data&0xff00)>>8);
}

inline void SwapEndian(unsigned int *data)
{
    *
data=((*data&0x000000ff)<<24)
        |((*
data&0x0000ff00)<< 8)
        |((*
data&0x00ff0000)>> 8)
        |((*
data&0xff000000)>>24);
}

inline void SwapEndian(int *data)
{
    *
data=((*data&0x000000ff)<<24)
        |((*
data&0x0000ff00)<< 8)
        |((*
data&0x00ff0000)>> 8)
        |((*
data&0xff000000)>>24);
}

/******************************************************************************/

inline int FileSize(FILE *fp)
{
    
long pos;
    
fseek(fp0SEEK_END);
    
pos ftell(fp);
    
fseek(fp0SEEK_SET);
    return 
pos;
}

/******************************************************************************/

void ReadTableDirectory(FILEfpstTableDirectorytd)
{
    
fread(&td->tag,                sizeof(td->tag),        1fp);
    
fread(&td->checkSum,        sizeof(td->checkSum),    1fp);
    
fread(&td->offset,            sizeof(td->offset),        1fp);
    
fread(&td->length,            sizeof(td->length),        1fp);
    
//SwapEndian(&td->tag);    // Don't need to flip 4 seperate bytes
    
SwapEndian(&td->checkSum);
    
SwapEndian(&td->offset);
    
SwapEndian(&td->length);

    
char= (char*)&td->tag;
    
dprintf("\t [Tag: %c%c%c%c],"t[0], t[1], t[2], t[3] );
    
dprintf(" CheckSum 0x%08X,"td->checkSum);
    
dprintf(" Offset % 8d,"td->offset);
    
dprintf(" Length: % 6d\n"td->length);
}

void ReadFontDirectory(FILEfpstFontDirectoryfd)
{
    
dprintf("FontDirectory:\n");
    
stOffsetSubTableot = &fd->m_offsetSubTable;

    
fread(&ot->scalersizeof(ot->scaler), 1fp);
    
SwapEndian(&ot->scaler);
    
DBG_ASSERT(ot->scaler==0x00010000);

    
fread(&ot->numTables,        sizeof(ot->numTables),        1fp);
    
fread(&ot->searchRange,        sizeof(ot->searchRange),    1fp);
    
fread(&ot->entrySelector,    sizeof(ot->entrySelector),    1fp);
    
fread(&ot->rangeShift,        sizeof(ot->rangeShift),        1fp);
    
SwapEndian(&ot->numTables);    
    
SwapEndian(&ot->searchRange);        
    
SwapEndian(&ot->entrySelector);    
    
SwapEndian(&ot->rangeShift);

    
dprintf("\tOffsetSubTable\n");
    
dprintf("\t Scalar: 0x%08X\n",        ot->scaler);
    
dprintf("\t NumTables: %d\n",        ot->numTables);
    
dprintf("\t SearchRange: %d\n",        ot->searchRange);
    
dprintf("\t EntrySelector: %d\n",   ot->entrySelector);
    
dprintf("\t RangeShift: %d\n",        ot->rangeShift);
    

    
DBG_ASSERT(ot->numTables<MAXFLAGS); // Sanity check

    
fd->m_tableDirectory = new stTableDirectory[ot->numTables];

    
dprintf("\n\tTableDirectory\n");
    for (
int i=0i<ot->numTablesi++)
    {
        
ReadTableDirectory(fp, &fd->m_tableDirectory[i]);
    }
}

/******************************************************************************/

uchar8GetTableData(uchar8datastTTFttfcharname)
{
    
stFontDirectoryfd = &ttf->m_fontDirectory;
    
stOffsetSubTablesubTable = &fd->m_offsetSubTable;

    
stTableDirectorytableDirectory NULL;
    for (
int i=0i<subTable->numTablesi++)
    {
        
stTableDirectorytable = &fd->m_tableDirectory[i];
        
char= (char*)&table->tag;

        
char tname[32] = {0};
        
strncpy(tnamec4);

        if (
strcmp(tnamename)==0)
        {
            
tableDirectory table;
            break;
        }

    }
    
DBG_ASSERT(tableDirectory);

    
uchar8tableData = &data[tableDirectory->offset];

    return 
tableData;
}

/******************************************************************************/

void ReadCMAP(uchar8datastTTFttfstCMAPcmap)
{
    
uchar8cmapData GetTableData(datattf"cmap");
    
DBG_ASSERT(cmapData);
    
    
uchar8startCMAPData cmapData;

    
cmap->version            = *((uint16*)cmapData);        cmapData+=2;        SwapEndian(&cmap->version);
    
cmap->numberSubtables    = *((uint16*)cmapData);        cmapData+=2;        SwapEndian(&cmap->numberSubtables);


    
int numSubTables cmap->numberSubtables;
    
DBG_ASSERT(numSubTables>&& numSubTables<1000); // Sanity check
    
cmap->subTables = new stCMAPSubTable[numSubTables];
    
DBG_ASSERT(cmap->subTables);

    for (
int i=0i<numSubTablesi++)
    {
        
stCMAPSubTablesubTable = &cmap->subTables[i];

        
subTable->platformID            = *((uint16*)cmapData);        cmapData+=2;    SwapEndian(&subTable->platformID);
        
subTable->platformSpecificID    = *((uint16*)cmapData);        cmapData+=2;    SwapEndian(&subTable->platformSpecificID);
        
subTable->offset                = *((uint32*)cmapData);        cmapData+=4;    SwapEndian(&subTable->offset);


        
stCMAPTabletable = &subTable->table;
        
uchar8tableOffset startCMAPData subTable->offset;

        
table->format        = *((uint16*)tableOffset);        tableOffset+=2;    SwapEndian(&table->format);
        
table->length        = *((uint16*)tableOffset);        tableOffset+=2;    SwapEndian(&table->length);
        
table->language        = *((uint16*)tableOffset);        tableOffset+=2;    SwapEndian(&table->language);

        switch (
table->format)
        {
            case 
0// Table follows as 256 glyph indices
            
{        // Character codes and glyph indices that are restricted to a single byte
                
DBG_ASSERT(table->length == 262);

                
DBG_ASSERT(cmap->glyphIndexArray==NULL);
                if (
cmap->glyphIndexArray==NULL)
                {
                    
cmap->glyphIndexArray = new uint8[256];
                    
cmap->numGlyphIndexArray 256;
                    
                    
uint8glyphIndexArray cmap->glyphIndexArray;

                    for (
int k=0k<256k++)
                    {
                        
glyphIndexArray[k] = *((uint8*)tableOffset);    tableOffset+=1;
                    }
                }
            }
            break;

            default:
            {
                
//DBG_HALT;
            
}
        }
    }
}

/******************************************************************************/

int ReadCoords(uint8dataint numFlagsuint8flagsint16coordsbool isX)
{
    
uint8startAddr data;

    
int point 0;
    const 
int MAXPOINTS MAXFLAGS;
    
int points[MAXPOINTS];
    
int numPoints 0;
    for (
int i=0i<numFlagsi++)
    {
        
DBG_ASSERT(numPoints<MAXPOINTS);
        
uint8 flag flags[i];

        
bool isByte false;
        
bool isSame false;
        
        if (
isX)
        {
            
isByte = (flag&2)  > true false;
            
isSame = (flag&16) > true false;
        }
        else
        {
            
isByte = (flag&4)  > true false;
            
isSame = (flag&32) > true false;
        }

        if (
isByte)
        {
            
uint8 coord = *((uint8*)data);            data+=1;                    SwapEndian(&coord);
            
int16 scoord coord;
            if (!
isSame)
                
scoord = -scoord;
            
point += scoord;
        }
        else
        {
            if (
isSame)
            {
                
// same as last point
            
}
            else
            {
                
int16 coord = *((int16*)data);            data+=2;                    SwapEndian(&coord);
                
point += coord;
            }
        }
        
points[numPoints++] = point;
    }

    
DBG_ASSERT(numPoints == numFlags);
    for (
int i=0i<numPointsi++)
    {
        
coords[i] = points[i];
    }

    
int bytesRead = (int)(data startAddr);
    return 
bytesRead;
}

/******************************************************************************/

void ReadGLYFSimple(uchar8datastGLYFItemglyfItemint indx)
{
    
//int numPoints = indx;     // index refers to last point.

    
int numPoints = -1;

    
glyfItem->m_glyfSimple = new stGLYFSimple;
    
stGLYFSimpleglyfSimple glyfItem->m_glyfSimple;

    
int numberOfContours glyfItem->m_glyfDescription.numberOfContours;
    
DBG_ASSERT(numberOfContours>&& numberOfContours<10000);

    
glyfSimple->endPtsOfContours        = new uint16[numberOfContours];
    for (
int i=0i<numberOfContoursi++)
    {
        
glyfSimple->endPtsOfContours[i]    = *((uint16*)data);        data+=2;        SwapEndian(&glyfSimple->endPtsOfContours[i]);

        if (
glyfSimple->endPtsOfContours[i] > numPoints)
        {
            
numPoints glyfSimple->endPtsOfContours[i];
        }
    }

    
DBG_ASSERT(numPoints>=0);
    
DBG_ASSERT(numPoints<2000);


    
glyfSimple->instructionLength        = *((uint16*)data);        data+=2;        SwapEndian(&glyfSimple->instructionLength);
///    DBG_ASSERT(glyfSimple->instructionLength>0 && glyfSimple->instructionLength<10000);

    
glyfSimple->instructions = new uint8glyfSimple->instructionLength ];

    for (
int i=0i<glyfSimple->instructionLengthi++)
    {
        
glyfSimple->instructions[i]        = *((uint8*)data);        data+=1;        SwapEndian(&glyfSimple->instructions[i]);
    }



    
uint8 flags[MAXFLAGS];


    
numPoints++;
    
int numFlags 0;
    while (
numFlags numPoints)
    {
        
DBG_ASSERT(numFlags MAXFLAGS);

        
uint8 flag =  *((uint8*)data);            data+=1;                    SwapEndian(&flag);
        
        
flags[numFlags] = flag;
        
numFlags++;

        
uint8 repeat = (flag 0x8); // Get Repeat Flag

        
if (repeat)
        {
            
///????ERROR???...should repeat and call itself?
            
uint8 numRepeats = *((uint8*)data);        data+=1;                    SwapEndian(&numRepeats);
            for (
int i=0i<numRepeatsi++)
            {
                
flags[numFlags] =  flag;
                
numFlags++;
            }
        }
    }

    if (
indx==68)
    {
        
int check 0;
    }

    
glyfItem->m_glyfSimple->numFlags numFlags;
    
glyfItem->m_glyfSimple->flags = new uint8[numFlags];
    for (
int i=0i<numFlagsi++)
    {
        
glyfItem->m_glyfSimple->flags[i] = flags[i];
    }

    
glyfItem->m_glyfSimple->xCoordinates = new int16[numFlags];
    
glyfItem->m_glyfSimple->yCoordinates = new int16[numFlags];

    
data += ReadCoords(datanumFlagsflagsglyfItem->m_glyfSimple->xCoordinatestrue); // x coords


    
if (indx==68)
    {
        
int check 0;
    }


    
data += ReadCoords(datanumFlagsflagsglyfItem->m_glyfSimple->yCoordinatesfalse); // y coords

}

/******************************************************************************/

void ReadGLYFCompound(uchar8datastGLYFItemglyfItemint indx)
{

    const 
int ARG_1_AND_2_ARE_WORDS        1<<0;        // If set, the arguments are words; 
                                                    // If not set, they are bytes. 
    
const int ARGS_ARE_XY_VALUES        1<<1;        // If set, the arguments are xy values; 
                                                    // If not set, they are points. 
    
const int ROUND_XY_TO_GRID            1<<2;        // If set, round the xy values to grid; 
                                                    // if not set do not round xy values to grid (relevant only to bit 1 is set) 
    
const int WE_HAVE_A_SCALE            1<<3;        // If set, there is a simple scale for the component. 
                                                    // If not set, scale is 1.0. 
                                                    // (this bit is obsolete) 4 (obsolete; set to zero) 
    
const int MORE_COMPONENTS            1<<5;        // If set, at least one additional glyph follows this one. 
    
const int WE_HAVE_AN_X_AND_Y_SCALE    1<<6;     // If set the x direction will use a different scale than the y direction. 
    
const int WE_HAVE_A_TWO_BY_TWO        1<<7;        // If set there is a 2-by-2 transformation that will be used to scale the component. 
    
const int WE_HAVE_INSTRUCTIONS        1<<8;        // If set, instructions for the component character follow the last component. 
    
const int USE_MY_METRICS            1<<9;        // Use metrics from this component for the compound glyph. 
    
const int OVERLAP_COMPOUND            1<<10;    // If set, the components of this compound glyph overlap. 


    
glyfItem->m_glyfCompound = new stGLYFCompound;
    
stGLYFCompoundglyfCompound glyfItem->m_glyfCompound;


    
uint16 flagbyte 0;
    
uint16 glyphIndex 0;
    do 
    {
        
flagbyte    = *((uint16*)data);        data+=2;    SwapEndian(&flagbyte);
        
glyphIndex    = *((uint16*)data);        data+=2;    SwapEndian(&glyphIndex);

        if ( (
flagbyte ARGS_ARE_XY_VALUES) == )
        {
            
DBG_HALT// index
        
}
        else
        {
            if ( 
flagbyte ARG_1_AND_2_ARE_WORDS )
            {
                
uint16 arg0 = *((uint16*)data);            data+=2;                    SwapEndian(&arg0);
                
uint16 arg1 = *((uint16*)data);            data+=2;                    SwapEndian(&arg1);
            }
            else
            {
                
uint8 arg0 = *((uint8*)data);            data+=1;                    SwapEndian(&arg0);
                
uint8 arg1 = *((uint8*)data);            data+=1;                    SwapEndian(&arg1);
            }
        }

        if (
flagbyte WE_HAVE_A_TWO_BY_TWO)
        {
            
uint16 a = *((uint16*)data);                data+=2;                    SwapEndian(&a);
            
uint16 b = *((uint16*)data);                data+=2;                    SwapEndian(&b);
            
uint16 c = *((uint16*)data);                data+=2;                    SwapEndian(&c);
            
uint16 d = *((uint16*)data);                data+=2;                    SwapEndian(&d);
        }
        else if (
flagbyte WE_HAVE_AN_X_AND_Y_SCALE)
        {
            
uint16 a = *((uint16*)data);                data+=2;                    SwapEndian(&a);
            
0;
            
0;
            
uint16 d = *((uint16*)data);                data+=2;                    SwapEndian(&d);
        }
        else if ( 
flagbyte WE_HAVE_A_SCALE )
        {
            
uint16 s = *((uint16*)data);                data+=2;                    SwapEndian(&s);
            
s;
            
0;
            
0;
            
s;
        }
        else
        {
            
1;
            
0;
            
0;
            
1;
        }

    } while (
flagbyte MORE_COMPONENTS);

}

/******************************************************************************/

void ReadGLYF(uchar8datastTTFttfstGLYFglyf)
{
    
uchar8glyfData GetTableData(datattf"glyf");
    
DBG_ASSERT(glyfData);


    
int numGlyphs ttf->m_maxp.numGlyphs;
    
DBG_ASSERT(numGlyphs>&& numGlyphs<10000); // Sanity check

    
stLOCAloca = &ttf->m_loca;
    
intglyphOffsets loca->glyphOffsets;
    
DBG_ASSERT(glyphOffsets);

    
glyf->numGlyphs numGlyphs;
    
glyf->glyfItem = new stGLYFItem[numGlyphs];

    for (
int i=0i<numGlyphsi++)
    {
        
stGLYFItemglyfItem = &glyf->glyfItem[i];
        
int glyfOffset    glyphOffsets[i];
        
uchar8itemData = &glyfDataglyfOffset ];

        
stGlyfDescriptionglyfDesc = &glyfItem->m_glyfDescription;
        
glyfDesc->numberOfContours        = *((int16*)itemData);        itemData+=2;        SwapEndian(&glyfDesc->numberOfContours);
        
glyfDesc->xMin                    = *((FWord*)itemData);        itemData+=2;        SwapEndian(&glyfDesc->xMin);
        
glyfDesc->yMin                    = *((FWord*)itemData);        itemData+=2;        SwapEndian(&glyfDesc->yMin);
        
glyfDesc->xMax                    = *((FWord*)itemData);        itemData+=2;        SwapEndian(&glyfDesc->xMax);
        
glyfDesc->yMax                    = *((FWord*)itemData);        itemData+=2;        SwapEndian(&glyfDesc->yMax);


        
// Only Simple Glyphs at the moment
        
DBG_ASSERT(glyfDesc->numberOfContours!=0);

        if (
glyfDesc->numberOfContours>0)
        {
            
ReadGLYFSimple(itemDataglyfItemi);
        }
        
        if (
glyfDesc->numberOfContours<0)
        {
            
DBG_ASSERT(glyfDesc->numberOfContours==-1);
            
ReadGLYFCompound(itemDataglyfItemi);
        }
    }

    
int done 0;

}



/******************************************************************************/

void ReadLOCA(uchar8datastTTFttfstLOCAloca)
{
    
uchar8locaData GetTableData(datattf"loca");
    
DBG_ASSERT(locaData);

    
int numGlyphs ttf->m_maxp.numGlyphs;

    
DBG_ASSERT(numGlyphs>&& numGlyphs<5000); // Sanity Check
    
loca->glyphOffsets = new int[numGlyphs];

    
DBG_ASSERT(ttf->m_head.indexToLocFormat==|| ttf->m_head.indexToLocFormat==1);
    
bool shortOffsets ttf->m_head.indexToLocFormat==true false;


    for (
int i=0i<numGlyphsi++)
    {
        if (
shortOffsets)
        {
            
uint16 offset        = *((uint16*)locaData);        locaData+=2;    SwapEndian(&offset);
            
loca->glyphOffsets[i]    = offset;
        }
        else
        {
            
uint32 offset        = *((uint32*)locaData);        locaData+=4;    SwapEndian(&offset);
            
loca->glyphOffsets[i]    = offset;
        }
    }

}


/******************************************************************************/

void ReadMAXP(uchar8datastTTFttfstMAXPmaxp)
{
    
uchar8maxpData GetTableData(datattf"maxp");
    
DBG_ASSERT(maxpData);

    
maxp->version                = *((Fixed*)maxpData);        maxpData+=4;    SwapEndian(&maxp->version);
    
maxp->numGlyphs                = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->numGlyphs);
    
maxp->maxPoints                = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxPoints);
    
maxp->maxContours            = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxContours);

    
maxp->maxComponentPoints    = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxComponentPoints);
    
maxp->maxComponentContours    = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxComponentContours);
    
maxp->maxZones                = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxZones);
    
maxp->maxTwilightPoints        = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxTwilightPoints);
    
maxp->maxStorage            = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxStorage);

    
maxp->maxFunctionDefs        = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxFunctionDefs);
    
maxp->maxInstructionDefs    = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxInstructionDefs);
    
maxp->maxStackElements        = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxStackElements);

    
maxp->maxSizeOfInstructions    = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxSizeOfInstructions);
    
maxp->maxComponentElements    = *((uint16*)maxpData);        maxpData+=2;    SwapEndian(&maxp->maxComponentElements);

    
DBG_ASSERT(maxp->version == 0x00010000);                    // 0x00010000 if (version 1.0)
    
DBG_ASSERT(maxp->maxZones == 2);                            // set to 2
}

/******************************************************************************/

void ReadHEAD(uchar8datastTTFttfstHEADhead)
{
    
uchar8headData GetTableData(datattf"head");
    
DBG_ASSERT(headData);

    
head->version                = *((Fixed*)headData);        headData+=4;    SwapEndian(&head->version);
    
head->fontRevision            = *((Fixed*)headData);        headData+=4;    SwapEndian(&head->fontRevision);
    
head->checkSumAdjustment    = *((uint32*)headData);        headData+=4;    SwapEndian(&head->checkSumAdjustment);
    
head->magicNumber            = *((uint32*)headData);        headData+=4;    SwapEndian(&head->magicNumber);
    
head->flags                    = *((uint16*)headData);        headData+=2;    SwapEndian(&head->flags);
    
head->unitsPerEm            = *((uint16*)headData);        headData+=2;    SwapEndian(&head->unitsPerEm);

    
DBG_ASSERT(sizeof(longDateTime)==8);
    
head->created                = *((uint16*)headData);        headData+=8;    //SwapEndian(&head->created);
    
head->modified                = *((uint16*)headData);        headData+=8;    //SwapEndian(&head->modified);

    
head->xMin                    = *((FWord*)headData);        headData+=2;    SwapEndian(&head->xMin);
    
head->yMin                    = *((FWord*)headData);        headData+=2;    SwapEndian(&head->yMin);
    
head->xMax                    = *((FWord*)headData);        headData+=2;    SwapEndian(&head->xMax);
    
head->yMax                    = *((FWord*)headData);        headData+=2;    SwapEndian(&head->yMax);
    
head->macStyle                = *((uint16*)headData);        headData+=2;    SwapEndian(&head->macStyle);

    
head->lowestRecPPEM            = *((uint16*)headData);        headData+=2;    SwapEndian(&head->lowestRecPPEM);
    
head->fontDirectionHint        = *((int16*)headData);        headData+=2;    SwapEndian(&head->fontDirectionHint);

    
head->indexToLocFormat        = *((int16*)headData);        headData+=2;    SwapEndian(&head->indexToLocFormat);
    
head->glyphDataFormat        = *((int16*)headData);        headData+=2;    SwapEndian(&head->glyphDataFormat);

    
DBG_ASSERT(head->version == 0x00010000);                            // 0x00010000 if (version 1.0)
    
DBG_ASSERT(head->magicNumber == 0x5F0F3CF5);                        // set to 0x5F0F3CF5 
    
DBG_ASSERT(head->indexToLocFormat==|| head->indexToLocFormat==1);    // 0 for short offsets, 1 for long 
}

/******************************************************************************/

void ReadTTF(const charszFileNamestTTFttf)
{
    
dprintf("Reading TTF File :%s\n"szFileName);

    
FILE fp fopen(szFileName"rb");
    
DBG_ASSERT(fp);

    
int fileSize  FileSize(fp);
    
dprintf("FileSize: %d Bytes\n"fileSize);

    
ReadFontDirectory(fp, &ttf->m_fontDirectory);

    
uchar8data = new uchar8[fileSize 100]; //+100 is safetly buffer
    
DBG_ASSERT(data);
    
fseek(fp0SEEK_SET);
    
fread(datafileSize1fp);
    
fclose (fp);

    
ReadCMAP(datattf, &ttf->m_cmap);
    
ReadHEAD(datattf, &ttf->m_head);
    
ReadMAXP(datattf, &ttf->m_maxp);
    
ReadLOCA(datattf, &ttf->m_loca);
    
ReadGLYF(datattf, &ttf->m_glyf);


    
//DebugDrawGlyf(ttf);

    
delete[] data;
}

/******************************************************************************/

































 
Advert (Support Website)

 
 Visitor:
Copyright (c) 2002-2024 xbdev.net - All rights reserved.
Designated articles, tutorials and software are the property of their respective owners.