Example #1
0
/*-----------------------------------------------------------------------
** Load a TrueType font table into memory and return a pointer to it.
** The font's "file" and "offset_table" fields must be set before this
** routine is called.
**
** This first argument is a TrueType font structure, the second
** argument is the name of the table to retrieve.  A table name
** is always 4 characters, though the last characters may be
** padding spaces.
-----------------------------------------------------------------------*/
BYTE *GetTable(struct TTFONT *font, const char *name)
{
    BYTE *ptr;
    ULONG x;

#ifdef DEBUG_TRUETYPE
    debug("GetTable(file,font,\"%s\")",name);
#endif

    /* We must search the table directory. */
    ptr = font->offset_table + 12;
    x=0;
    while (TRUE)
    {
        if ( strncmp((const char*)ptr,name,4) == 0 )
        {
            ULONG offset,length;
            BYTE *table;

            offset = getULONG( ptr + 8 );
            length = getULONG( ptr + 12 );
            table = (BYTE*)calloc( sizeof(BYTE), length );

            try
            {
#ifdef DEBUG_TRUETYPE
                debug("Loading table \"%s\" from offset %d, %d bytes",name,offset,length);
#endif

                if ( fseek( font->file, (long)offset, SEEK_SET ) )
                {
                    throw TTException("TrueType font may be corrupt (reason 3)");
                }

                if ( fread(table,sizeof(BYTE),length,font->file) != (sizeof(BYTE) * length))
                {
                    throw TTException("TrueType font may be corrupt (reason 4)");
                }
            }
            catch (TTException& )
            {
                free(table);
                throw;
            }
            return table;
        }

        x++;
        ptr += 16;
        if (x == font->numTables)
        {
            throw TTException("TrueType font is missing table");
        }
    }

} /* end of GetTable() */
Example #2
0
/*
** This is the central routine of this section.
*/
void ttfont_CharStrings(TTStreamWriter& stream, struct TTFONT *font, std::vector<int>& glyph_ids)
    {
    Fixed post_format;

    /* The 'post' table format number. */
    post_format = getFixed( font->post_table );

    if( post_format.whole != 2 || post_format.fraction != 0 )
        throw TTException("TrueType fontdoes not have a format 2.0 'post' table");

    /* Emmit the start of the PostScript code to define the dictionary. */
    stream.printf("/CharStrings %d dict dup begin\n", glyph_ids.size());

    /* Emmit one key-value pair for each glyph. */
    for(std::vector<int>::const_iterator i = glyph_ids.begin();
        i != glyph_ids.end(); ++i)
        {
        if(font->target_type == PS_TYPE_42)     /* type 42 */
            {
            stream.printf("/%s %d def\n",ttfont_CharStrings_getname(font, *i), *i);
            }
        else                            /* type 3 */
            {
            stream.printf("/%s{",ttfont_CharStrings_getname(font, *i));

            tt_type3_charproc(stream, font, *i);

            stream.putline("}_d");      /* "} bind def" */
            }
        }

    stream.putline("end readonly def");
    } /* end of ttfont_CharStrings() */
Example #3
0
TTObject::TTObject(const TTSymbol aClassName) :
mObjectInstance(NULL)
{
	TTErr err = ttEnvironment->createInstance(aClassName, &mObjectInstance, TTValue());
	
	if (err) {
		TTLogError("TTObject -- error %i instantiating %s\n", err, aClassName.c_str());
		throw TTException("object instantiation failed");
	}
}
Example #4
0
/*
** This routine is called by the one below.
** It is also called from pprdrv_tt2.c
*/
const char *ttfont_CharStrings_getname(struct TTFONT *font, int charindex)
{
    int GlyphIndex;
    static char temp[80];
    char *ptr;
    ULONG len;

    GlyphIndex = (int)getUSHORT( font->post_table + 34 + (charindex * 2) );

    if ( GlyphIndex <= 257 )            /* If a standard Apple name, */
    {
        return Apple_CharStrings[GlyphIndex];
    }
    else                                /* Otherwise, use one */
    {
        /* of the pascal strings. */
        GlyphIndex -= 258;

        /* Set pointer to start of Pascal strings. */
        ptr = (char*)(font->post_table + 34 + (font->numGlyphs * 2));

        len = (ULONG)*(ptr++);  /* Step thru the strings */
        while (GlyphIndex--)            /* until we get to the one */
        {
            /* that we want. */
            ptr += len;
            len = (ULONG)*(ptr++);
        }

        if ( len >= sizeof(temp) )
        {
            throw TTException("TrueType font file contains a very long PostScript name");
        }

        strncpy(temp,ptr,len);  /* Copy the pascal string into */
        temp[len]=(char)NULL;   /* a buffer and make it ASCIIz. */

        return temp;
    }
} /* end of ttfont_CharStrings_getname() */
Example #5
0
/*
** Load the simple glyph data pointed to by glyph.
** The pointer "glyph" should point 10 bytes into
** the glyph data.
*/
void GlyphToType3::load_char(TTFONT* font, BYTE *glyph)
{
    int x;
    BYTE c, ct;

    /* Read the contour endpoints list. */
    epts_ctr = (int *)calloc(num_ctr,sizeof(int));
    for (x = 0; x < num_ctr; x++)
    {
        epts_ctr[x] = getUSHORT(glyph);
        glyph += 2;
    }

    /* From the endpoint of the last contour, we can */
    /* determine the number of points. */
    num_pts = epts_ctr[num_ctr-1]+1;
#ifdef DEBUG_TRUETYPE
    debug("num_pts=%d",num_pts);
    stream.printf("%% num_pts=%d\n",num_pts);
#endif

    /* Skip the instructions. */
    x = getUSHORT(glyph);
    glyph += 2;
    glyph += x;

    /* Allocate space to hold the data. */
    tt_flags = (BYTE *)calloc(num_pts,sizeof(BYTE));
    xcoor = (FWord *)calloc(num_pts,sizeof(FWord));
    ycoor = (FWord *)calloc(num_pts,sizeof(FWord));

    /* Read the flags array, uncompressing it as we go. */
    /* There is danger of overflow here. */
    for (x = 0; x < num_pts; )
    {
        tt_flags[x++] = c = *(glyph++);

        if (c&8)                /* If next byte is repeat count, */
        {
            ct = *(glyph++);

            if ( (x + ct) > num_pts )
            {
                throw TTException("Error in TT flags");
            }

            while (ct--)
            {
                tt_flags[x++] = c;
            }
        }
    }

    /* Read the x coordinates */
    for (x = 0; x < num_pts; x++)
    {
        if (tt_flags[x] & 2)            /* one byte value with */
        {
            /* external sign */
            c = *(glyph++);
            xcoor[x] = (tt_flags[x] & 0x10) ? c : (-1 * (int)c);
        }
        else if (tt_flags[x] & 0x10)    /* repeat last */
        {
            xcoor[x] = 0;
        }
        else                            /* two byte signed value */
        {
            xcoor[x] = getFWord(glyph);
            glyph+=2;
        }
    }

    /* Read the y coordinates */
    for (x = 0; x < num_pts; x++)
    {
        if (tt_flags[x] & 4)            /* one byte value with */
        {
            /* external sign */
            c = *(glyph++);
            ycoor[x] = (tt_flags[x] & 0x20) ? c : (-1 * (int)c);
        }
        else if (tt_flags[x] & 0x20)    /* repeat last value */
        {
            ycoor[x] = 0;
        }
        else                            /* two byte signed value */
        {
            ycoor[x] = getUSHORT(glyph);
            glyph+=2;
        }
    }

    /* Convert delta values to absolute values. */
    for (x = 1; x < num_pts; x++)
    {
        xcoor[x] += xcoor[x-1];
        ycoor[x] += ycoor[x-1];
    }

    for (x=0; x < num_pts; x++)
    {
        xcoor[x] = topost(xcoor[x]);
        ycoor[x] = topost(ycoor[x]);
    }

} /* end of load_char() */
Example #6
0
/*
** Here is the routine which ties it all together.
**
** Create the array called "sfnts" which
** holds the actual TrueType data.
*/
void ttfont_sfnts(TTStreamWriter& stream, struct TTFONT *font)
{
    static const char *table_names[] =  /* The names of all tables */
    {
        /* which it is worth while */
        "cvt ",                         /* to include in a Type 42 */
        "fpgm",                         /* PostScript font. */
        "glyf",
        "head",
        "hhea",
        "hmtx",
        "loca",
        "maxp",
        "prep"
    } ;

    struct                      /* The location of each of */
    {
        ULONG oldoffset;        /* the above tables. */
        ULONG newoffset;
        ULONG length;
        ULONG checksum;
    } tables[9];

    BYTE *ptr;                  /* A pointer into the origional table directory. */
    ULONG x,y;                  /* General use loop countes. */
    int c;                      /* Input character. */
    int diff;
    ULONG nextoffset;
    int count;                  /* How many `important' tables did we find? */

    ptr = font->offset_table + 12;
    nextoffset=0;
    count=0;

    /*
    ** Find the tables we want and store there vital
    ** statistics in tables[].
    */
    for (x=0; x < 9; x++ )
    {
        do
        {
            diff = strncmp( (char*)ptr, table_names[x], 4 );

            if ( diff > 0 )             /* If we are past it. */
            {
                tables[x].length = 0;
                diff = 0;
            }
            else if ( diff < 0 )        /* If we haven't hit it yet. */
            {
                ptr += 16;
            }
            else if ( diff == 0 )       /* Here it is! */
            {
                tables[x].newoffset = nextoffset;
                tables[x].checksum = getULONG( ptr + 4 );
                tables[x].oldoffset = getULONG( ptr + 8 );
                tables[x].length = getULONG( ptr + 12 );
                nextoffset += ( ((tables[x].length + 3) / 4) * 4 );
                count++;
                ptr += 16;
            }
        }
        while (diff != 0);

    } /* end of for loop which passes over the table directory */

    /* Begin the sfnts array. */
    sfnts_start(stream);

    /* Generate the offset table header */
    /* Start by copying the TrueType version number. */
    ptr = font->offset_table;
    for (x=0; x < 4; x++)
    {
        sfnts_pputBYTE( stream,  *(ptr++) );
    }

    /* Now, generate those silly numTables numbers. */
    sfnts_pputUSHORT(stream, count);            /* number of tables */
    if ( count == 9 )
    {
        sfnts_pputUSHORT(stream, 7);          /* searchRange */
        sfnts_pputUSHORT(stream, 3);          /* entrySelector */
        sfnts_pputUSHORT(stream, 81);         /* rangeShift */
    }
#ifdef DEBUG_TRUETYPE
    else
    {
        debug("only %d tables selected",count);
    }
#endif

    /* Now, emmit the table directory. */
    for (x=0; x < 9; x++)
    {
        if ( tables[x].length == 0 )    /* Skip missing tables */
        {
            continue;
        }

        /* Name */
        sfnts_pputBYTE( stream, table_names[x][0] );
        sfnts_pputBYTE( stream, table_names[x][1] );
        sfnts_pputBYTE( stream, table_names[x][2] );
        sfnts_pputBYTE( stream, table_names[x][3] );

        /* Checksum */
        sfnts_pputULONG( stream, tables[x].checksum );

        /* Offset */
        sfnts_pputULONG( stream, tables[x].newoffset + 12 + (count * 16) );

        /* Length */
        sfnts_pputULONG( stream, tables[x].length );
    }

    /* Now, send the tables */
    for (x=0; x < 9; x++)
    {
        if ( tables[x].length == 0 )    /* skip tables that aren't there */
        {
            continue;
        }

#ifdef DEBUG_TRUETYPE
        debug("emmiting table '%s'",table_names[x]);
#endif

        /* 'glyf' table gets special treatment */
        if ( strcmp(table_names[x],"glyf")==0 )
        {
            sfnts_glyf_table(stream,font,tables[x].oldoffset,tables[x].length);
        }
        else                    /* Other tables may not exceed */
        {
            /* 65535 bytes in length. */
            if ( tables[x].length > 65535 )
            {
                throw TTException("TrueType font has a table which is too long");
            }

            /* Start new string if necessary. */
            sfnts_new_table(stream, tables[x].length);

            /* Seek to proper position in the file. */
            fseek( font->file, tables[x].oldoffset, SEEK_SET );

            /* Copy the bytes of the table. */
            for ( y=0; y < tables[x].length; y++ )
            {
                if ( (c = fgetc(font->file)) == EOF )
                {
                    throw TTException("TrueType font may be corrupt (reason 7)");
                }

                sfnts_pputBYTE(stream, c);
            }
        }

        /* Padd it out to a four byte boundary. */
        y=tables[x].length;
        while ( (y % 4) != 0 )
        {
            sfnts_pputBYTE(stream, 0);
            y++;
#ifdef DEBUG_TRUETYPE_INLINE
            puts("\n% pad byte:\n");
#endif
        }

    } /* End of loop for all tables */

    /* Close the array. */
    sfnts_end_string(stream);
    stream.putline("]def");
} /* end of ttfont_sfnts() */
Example #7
0
/*
** We may have to break up the 'glyf' table.  That is the reason
** why we provide this special routine to copy it into the sfnts
** array.
*/
void sfnts_glyf_table(TTStreamWriter& stream, struct TTFONT *font, ULONG oldoffset, ULONG correct_total_length)
{
    ULONG off;
    ULONG length;
    int c;
    ULONG total=0;              /* running total of bytes written to table */
    int x;
    bool loca_is_local=false;

#ifdef DEBUG_TRUETYPE
    debug("sfnts_glyf_table(font,%d)", (int)correct_total_length);
#endif

    if (font->loca_table == NULL)
    {
        font->loca_table = GetTable(font,"loca");
        loca_is_local = true;
    }

    /* Seek to proper position in the file. */
    fseek( font->file, oldoffset, SEEK_SET );

    /* Copy the glyphs one by one */
    for (x=0; x < font->numGlyphs; x++)
    {
        /* Read the glyph offset from the index-to-location table. */
        if (font->indexToLocFormat == 0)
        {
            off = getUSHORT( font->loca_table + (x * 2) );
            off *= 2;
            length = getUSHORT( font->loca_table + ((x+1) * 2) );
            length *= 2;
            length -= off;
        }
        else
        {
            off = getULONG( font->loca_table + (x * 4) );
            length = getULONG( font->loca_table + ((x+1) * 4) );
            length -= off;
        }

#ifdef DEBUG_TRUETYPE
        debug("glyph length=%d",(int)length);
#endif

        /* Start new string if necessary. */
        sfnts_new_table( stream, (int)length );

        /*
        ** Make sure the glyph is padded out to a
        ** two byte boundary.
        */
        if ( length % 2 ) {
            throw TTException("TrueType font contains a 'glyf' table without 2 byte padding");
        }

        /* Copy the bytes of the glyph. */
        while ( length-- )
        {
            if ( (c = fgetc(font->file)) == EOF ) {
                throw TTException("TrueType font may be corrupt (reason 6)");
            }

            sfnts_pputBYTE(stream, c);
            total++;            /* add to running total */
        }

    }

    if (loca_is_local)
    {
        free(font->loca_table);
        font->loca_table = NULL;
    }

    /* Pad out to full length from table directory */
    while ( total < correct_total_length )
    {
        sfnts_pputBYTE(stream, 0);
        total++;
    }

} /* end of sfnts_glyf_table() */
Example #8
0
void read_font(const char *filename, font_type_enum target_type, std::vector<int>& glyph_ids, TTFONT& font)
{
    BYTE *ptr;

    /* Decide what type of PostScript font we will be generating. */
    font.target_type = target_type;

    if (font.target_type == PS_TYPE_42)
    {
        bool has_low = false;
        bool has_high = false;

        for (std::vector<int>::const_iterator i = glyph_ids.begin();
                i != glyph_ids.end(); ++i)
        {
            if (*i > 255)
            {
                has_high = true;
                if (has_low) break;
            }
            else
            {
                has_low = true;
                if (has_high) break;
            }
        }

        if (has_high && has_low)
        {
            font.target_type = PS_TYPE_42_3_HYBRID;
        }
        else if (has_high && !has_low)
        {
            font.target_type = PS_TYPE_3;
        }
    }

    /* Save the file name for error messages. */
    font.filename=filename;

    /* Open the font file */
    if ( (font.file = fopen(filename,"rb")) == (FILE*)NULL )
    {
        throw TTException("Failed to open TrueType font");
    }

    /* Allocate space for the unvarying part of the offset table. */
    assert(font.offset_table == NULL);
    font.offset_table = (BYTE*)calloc( 12, sizeof(BYTE) );

    /* Read the first part of the offset table. */
    if ( fread( font.offset_table, sizeof(BYTE), 12, font.file ) != 12 )
    {
        throw TTException("TrueType font may be corrupt (reason 1)");
    }

    /* Determine how many directory entries there are. */
    font.numTables = getUSHORT( font.offset_table + 4 );
#ifdef DEBUG_TRUETYPE
    debug("numTables=%d",(int)font.numTables);
#endif

    /* Expand the memory block to hold the whole thing. */
    font.offset_table = (BYTE*)realloc( font.offset_table, sizeof(BYTE) * (12 + font.numTables * 16) );

    /* Read the rest of the table directory. */
    if ( fread( font.offset_table + 12, sizeof(BYTE), (font.numTables*16), font.file ) != (font.numTables*16) )
    {
        throw TTException("TrueType font may be corrupt (reason 2)");
    }

    /* Extract information from the "Offset" table. */
    font.TTVersion = getFixed( font.offset_table );

    /* Load the "head" table and extract information from it. */
    ptr = GetTable(&font, "head");
    try
    {
        font.MfrRevision = getFixed( ptr + 4 );           /* font revision number */
        font.unitsPerEm = getUSHORT( ptr + 18 );
        font.HUPM = font.unitsPerEm / 2;
#ifdef DEBUG_TRUETYPE
        debug("unitsPerEm=%d",(int)font.unitsPerEm);
#endif
        font.llx = topost2( getFWord( ptr + 36 ) );               /* bounding box info */
        font.lly = topost2( getFWord( ptr + 38 ) );
        font.urx = topost2( getFWord( ptr + 40 ) );
        font.ury = topost2( getFWord( ptr + 42 ) );
        font.indexToLocFormat = getSHORT( ptr + 50 );     /* size of 'loca' data */
        if (font.indexToLocFormat != 0 && font.indexToLocFormat != 1)
        {
            throw TTException("TrueType font is unusable because indexToLocFormat != 0");
        }
        if ( getSHORT(ptr+52) != 0 )
        {
            throw TTException("TrueType font is unusable because glyphDataFormat != 0");
        }
    }
    catch (TTException& )
    {
        free(ptr);
        throw;
    }
    free(ptr);

    /* Load information from the "name" table. */
    Read_name(&font);

    /* We need to have the PostScript table around. */
    assert(font.post_table == NULL);
    font.post_table = GetTable(&font, "post");
    font.numGlyphs = getUSHORT( font.post_table + 32 );

    /* If we are generating a Type 3 font, we will need to */
    /* have the 'loca' and 'glyf' tables arround while */
    /* we are generating the CharStrings. */
    if (font.target_type == PS_TYPE_3 || font.target_type == PDF_TYPE_3 ||
            font.target_type == PS_TYPE_42_3_HYBRID)
    {
        BYTE *ptr;                      /* We need only one value */
        ptr = GetTable(&font, "hhea");
        font.numberOfHMetrics = getUSHORT(ptr + 34);
        free(ptr);

        assert(font.loca_table == NULL);
        font.loca_table = GetTable(&font,"loca");
        assert(font.glyf_table == NULL);
        font.glyf_table = GetTable(&font,"glyf");
        assert(font.hmtx_table == NULL);
        font.hmtx_table = GetTable(&font,"hmtx");
    }

    if (glyph_ids.size() == 0)
    {
        glyph_ids.clear();
        glyph_ids.reserve(font.numGlyphs);
        for (int x = 0; x < font.numGlyphs; ++x)
        {
            glyph_ids.push_back(x);
        }
    }
    else if (font.target_type == PS_TYPE_3 ||
             font.target_type == PS_TYPE_42_3_HYBRID)
    {
        ttfont_add_glyph_dependencies(&font, glyph_ids);
    }

} /* end of insert_ttfont() */