blob: 8a62259ab44d55bd2f68a5f8db1a5607b5ac9448 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Dmitriy S. Matveev
*/
#include <stdio.h>
#include <memory.h>
#include "Tables.h"
static inline uflong dwReverse(uflong data)
{
ufchar *dataElems = (ufchar *) &data;
return (uflong)((dataElems[0]<<24) | (dataElems[1]<<16) | (dataElems[2]<<8) | dataElems[3]);
}
/* Reverses WORD bytes order */
static inline ufshort wReverse(ufshort data)
{
return (ufshort)(((data<<8) & 0xFF00) | ((data>>8) & 0x00FF));
}
/* Reverses WORD bytes order */
static inline fshort wReverse(fshort data)
{
return (fshort)(((data<<8) & 0xFF00) | ((data>>8) & 0x00FF));
}
/* Searching of table,
return TRUE if table founded */
bool searchTable(uflong table, uflong* offset, FILE* tt_file)
{
Table_Offset tableOffset;
Table_Directory tableDirectory;
bool isFound = false;
fint size;
fint i;
/* Open font file stream */
// if( (tt_file = fopen( fPath,"rb")) == NULL ){
// printf("Error opening font file");
// return 0;
// }
size = (fint)fseek(tt_file,0,SEEK_SET);
if (size != 0)
{
#ifdef DEBUG
printf("Error seeking table\n");
#endif
return 0;
}
size = (fint)fread(&tableOffset, sizeof(Table_Offset), 1, tt_file);
if (size != 1){
#ifdef DEBUG
printf("Error reading font file\n");
#endif
return 0;
}
/* Reverse byte order */
tableOffset.version = dwReverse(tableOffset.version);
tableOffset.num_tables = wReverse(tableOffset.num_tables);
// tableOffset.search_range = wReverse(tableOffset.search_range);
// tableOffset.entry_selector = wReverse(tableOffset.entry_selector);
/* check whether the version is 1.0 */
if(tableOffset.version != 0x10000)
return 0;
/* look for 'head' table */
for(i=0; i< tableOffset.num_tables; i++)
{
size = (fint)fread(&tableDirectory, sizeof(Table_Directory), 1, tt_file);
if ( size != 1){
#ifdef DEBUG
printf("Error reading Table Directory from file.");
#endif
return 0;
}
if (* (uflong*)tableDirectory.tag == table){
isFound = true;
// tableDirectory.length = dwReverse(tableDirectory.length);
// tableDirectory.offset = dwReverse(tableDirectory.offset);
*offset = dwReverse(tableDirectory.offset);
break;
}
}
return isFound;
}
fint getTableEncode_4(FILE* tt_file, TableEncode* te, ufshort table_len)
{
ufshort* tableEncode;
ufshort length;
fint size, i;
length = (table_len - sizeof(Table_encode_header))/sizeof(ufshort); // in USHORTs
tableEncode = new ufshort[length];
/* reading tail of the table */
size = (fint)fread(tableEncode,sizeof(ufshort),length,tt_file);
if(size != length)
{
#ifdef DEBUG
printf("Error reading table encode format 4 from 'cmap' table");
#endif
delete[] tableEncode;
tableEncode = NULL;
return -1;
}
for(i=0;i<length;i++)
{
tableEncode[i]=wReverse(tableEncode[i]);
}
te->TableEncode = tableEncode; // pointer to tail of 'Table_encode' subtable (of 'cmap')
return 0;
}
//#ifndef WIN32
static inline bool compare(fwchar_t* wstr, fchar* str)
{
// fchar cstr[256];
// wcstombs(cstr,wstr,256);
// return !strcasecmp(cstr,str);
fchar tmpstr[256];
fwchar_t* tmpwstr = wstr;
fint i = 0;
for (; i<= fwcslen(tmpwstr); i++)
{
tmpstr[i] = (fchar)((*wstr) & 0xFF);
}
tmpstr[i]=0;
return !strcmp(tmpstr,str);
}
//#endif
fint parseNameTable(FILE* tt_file, fwchar_t** familyName, fwchar_t** psName, StyleName* fontStyle)
{
uflong dwTable = *(uflong*)NAME_TABLE;
uflong offset;
Table_name tableName;
Name_Entry nameRecord;
flong curPos;
ufshort *subFamilyName;
fint i, j;
fint size;
bool inFamilyNameCase = false, inSubfamilyNameCase = false, inPSNameCase = false;
if (searchTable(dwTable, &offset, tt_file))
{
/* move position to the 'name' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
#ifdef DEBUG
printf("Error executing fseek() for 'name' table.");
#endif
return -1;
}
/* read 'name' table header */
size = (fint)fread(&tableName, sizeof(Table_name) - sizeof(Name_Entry), 1, tt_file);
if (size != 1){
#ifdef DEBUG
printf("Error reading Table 'Name' from file.");
#endif
return -1;
}
tableName.num_name_records = wReverse(tableName.num_name_records);
tableName.storage_offset = wReverse(tableName.storage_offset);
/* enumerating NameRecords and finding Family Name value */
for(i=0; i < tableName.num_name_records; i++)
{
size = (fint)fread(&nameRecord, sizeof(Name_Entry), 1, tt_file);
if (size != 1)
{
#ifdef DEBUG
printf("Error reading Name Record from file.");
#endif
return -1;
}
nameRecord.nameID = wReverse(nameRecord.nameID);
nameRecord.platformID = wReverse(nameRecord.platformID);
if(nameRecord.platformID == WINDOWS_PLATFORM_ID)
switch (nameRecord.nameID)
{
case FAMILY_NAME_ID:
if (familyName != NULL && !inFamilyNameCase)
{
nameRecord.string_length = wReverse(nameRecord.string_length);
nameRecord.string_offset = wReverse(nameRecord.string_offset);
/* Save current position if someting wrong with family name */
curPos = ftell(tt_file);
size = fseek( tt_file,
offset + tableName.storage_offset + nameRecord.string_offset,
SEEK_SET);
if (size != 0){
#ifdef DEBUG
printf("Error executing fseek() for 'name' table.");
#endif
return -1;
}
// ZeroMemory(&fontFamilyName, nameRecord.string_length/2 + sizeof(ufshort));
ufshort *fontFamilyName = new ufshort[nameRecord.string_length/2+1];
// ZeroMemory(&(fontName[nameRecord.string_length]),1);
size = (fint)fread(fontFamilyName, sizeof(ufshort), nameRecord.string_length/2, tt_file);
if (size != nameRecord.string_length/2)
{
#ifdef DEBUG
printf("Error reading Family Name from file.");
#endif
delete[] fontFamilyName;
fontFamilyName = NULL;
return -1;
}
for(j=0; j < nameRecord.string_length/2; j++)
{
(fontFamilyName)[j] = wReverse((fontFamilyName)[j]);
//printf("%c",(fchar)(fontFamilyName)[j]);
}
//printf("\n");
(fontFamilyName)[j] = 0;
inFamilyNameCase = true;
//#ifdef WIN32
*familyName = (fwchar_t*)fontFamilyName;
/*#else
//TODO: To unify this cycle and previous
*familyName = new fwchar_t[nameRecord.string_length/2+1];
for(j=0; j < nameRecord.string_length/2+1; j++)
{
(*familyName)[j] = (fwchar_t)fontFamilyName[j];
}
delete fontFamilyName;
#endif*/
size = fseek( tt_file, curPos, SEEK_SET);
if (size != 0){
#ifdef DEBUG
printf("Error executing fseek() for 'name' table.");
#endif
return -1;
}
}
break;
case POSTSCRIPT_NAME_ID:
if (psName != NULL && !inPSNameCase)
{
nameRecord.string_length = wReverse(nameRecord.string_length);
nameRecord.string_offset = wReverse(nameRecord.string_offset);
/* Save current position if someting wrong with postscript name */
curPos = ftell(tt_file);
size = fseek( tt_file,
offset + tableName.storage_offset + nameRecord.string_offset,
SEEK_SET);
if (size != 0){
#ifdef DEBUG
printf("Error executing fseek() for 'name' table.");
#endif
return -1;
}
ufshort *fontPSName = new ufshort[nameRecord.string_length/2+1];
size = (fint)fread(fontPSName, sizeof(ufshort), nameRecord.string_length/2, tt_file);
if (size != nameRecord.string_length/2)
{
#ifdef DEBUG
printf("Error reading PostScript Name from file.");
#endif
delete[] fontPSName;
fontPSName = NULL;
return -1;
}
for(j=0; j < nameRecord.string_length/2; j++)
{
(fontPSName)[j] = wReverse((fontPSName)[j]);
}
(fontPSName)[j] = 0;
inPSNameCase = true;
//#ifdef WIN32
*psName = (fwchar_t*)fontPSName;
/*#else
*psName = new fwchar_t[nameRecord.string_length/2+1];
//TODO: To unify this cycle and previous
for(j=0; j < nameRecord.string_length/2+1; j++)
{
(*psName)[j] = (fwchar_t)fontPSName[j];
}
delete fontPSName;
#endif*/
size = fseek( tt_file, curPos, SEEK_SET);
if (size != 0){
#ifdef DEBUG
printf("Error executing fseek() for 'name' table.");
#endif
return -1;
}
}
break;
case SUBFAMILY_NAME_ID:
if(fontStyle != NULL && !inSubfamilyNameCase)
{
nameRecord.string_length = wReverse(nameRecord.string_length);
nameRecord.string_offset = wReverse(nameRecord.string_offset);
/* Save current position if someting wrong with subfamily name */
curPos = ftell(tt_file);
size = fseek( tt_file,
offset + tableName.storage_offset + nameRecord.string_offset,
SEEK_SET);
if (size != 0){
#ifdef DEBUG
printf("Error executing fseek() for 'name' table.");
#endif
return -1;
}
// ZeroMemory(&fontName, nameRecord.string_length + sizeof(ufshort));
subFamilyName = new ufshort[nameRecord.string_length/2+1];
// ZeroMemory(&(fontName[nameRecord.string_length]),1);
size = (fint)fread(subFamilyName, sizeof(ufshort), nameRecord.string_length/2, tt_file);
if (size != nameRecord.string_length/2)
{
#ifdef DEBUG
printf("Error reading SubFamily Name from file.");
#endif
delete[] subFamilyName;
subFamilyName = NULL;
return -1;
}
for(j=0; j < nameRecord.string_length/2; j++)
{
subFamilyName[j] = wReverse(subFamilyName[j]);
}
subFamilyName[j] = 0;
#define COMPARE_IT (!fwcscmp((ufshort *)subFamilyName,"Italic") || !fwcscmp((ufshort *)subFamilyName,"Oblique"))
#define COMPARE_BD (!fwcscmp((ufshort *)subFamilyName,"Bold"))
#define COMPARE_BDIT (!fwcscmp((ufshort *)subFamilyName,"Bold Italic") || !fwcscmp((ufshort *)subFamilyName,"Bold Oblique"))
#define COMPARE_REG (!fwcscmp((ufshort *)subFamilyName,"Regular") || !fwcscmp((fwchar_t *)subFamilyName,"Normal") || !fwcscmp((fwchar_t *)subFamilyName,"Book"))
if COMPARE_IT
{
*fontStyle = Italic;
inSubfamilyNameCase = true;
}
else if COMPARE_BD
{
*fontStyle = Bold;
inSubfamilyNameCase = true;
}
else if COMPARE_BDIT
{
*fontStyle = BoldItalic;
inSubfamilyNameCase = true;
}
else if COMPARE_REG
{
*fontStyle = Regular;
inSubfamilyNameCase = true;
}
delete[] subFamilyName;
subFamilyName = NULL;
size = fseek( tt_file, curPos, SEEK_SET);
if (size != 0){
#ifdef DEBUG
printf("Error executing fseek() for 'name' table.");
#endif
return -1;
}
}
}
}
}
/* Close font file stream */
/* if( fclose( tt_file ) ){
printf("Error closing TrueType font file.");
return 0;
}
*/
// fclose(tt_file);
if (!inSubfamilyNameCase)
fontStyle = NULL;
return 0;
}
fint parseHeadTable(FILE* tt_file, ffloat* bbox, fshort* format, ufshort* unitsPerEm)
{
uflong hTable = *(uflong*)HEAD_TABLE;
uflong offset;
Table_head tableHead;
fint size;
if (searchTable(hTable, &offset, tt_file))
{
/* move position to the 'head' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
#ifdef DEBUG
printf("Error executing fseek() for 'head' table.");
#endif
return -1;
}
/* read 'head' table header */
size = (fint)fread(&tableHead, sizeof(Table_head), 1, tt_file);
if (size != 1){
// printf("Error reading Table 'Head' from file.");
return -1;
}
bbox[0] = wReverse(tableHead.xMin);
bbox[1] = wReverse(tableHead.yMin);
bbox[2] = wReverse(tableHead.xMax);//for wingding must be -432(?)
bbox[3] = wReverse(tableHead.yMax);
tableHead.index_to_loc_format=wReverse(tableHead.index_to_loc_format);
if (wReverse(tableHead.glyph_data_format))
{
// if (tableHead.index_to_loc_format == 1 || tableHead.index_to_loc_format == 0)
*format = !tableHead.index_to_loc_format;
}
else
{
*format = tableHead.index_to_loc_format;
// printf("debug information: see 'loca' table format!!!\n");
}
*unitsPerEm = wReverse(tableHead.units_per_EM);
}
// ******* Validating data *********
// HDC hDC = GetDC(NULL);
// HDC hDC = GetDC(NULL);
// Table_head tableHead1;
// uflong tbl = (uflong)"head";
// fint m = GetFontData(hDC,tbl,(uflong)offset,&tableHead1,sizeof(Table_head));
// ******* Validating data *********
// return *bbox;
// fclose(tt_file);
return 0;
}
fint parseMaxpTable(FILE* tt_file, ufshort* numGlyphs)
{
uflong hTable = *(uflong*)MAXP_TABLE;
uflong offset;
Table_maxp tableMaxp;
fint size;
if (searchTable(hTable, &offset, tt_file))
{
/* move position to the 'maxp' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for 'maxp' table.");
return -1;
}
/* read 'maxp' table header */
size = (fint)fread(&tableMaxp, sizeof(Table_maxp), 1, tt_file);
if (size != 1){
// printf("Error reading Table 'maxp' from file.");
return -1;
}
}else
{
return -1;
}
*numGlyphs = wReverse(tableMaxp.numGlyphs);
tableMaxp.maxPoints = wReverse(tableMaxp.maxPoints);
tableMaxp.maxContours = wReverse(tableMaxp.maxContours);
tableMaxp.maxCompositePoints = wReverse(tableMaxp.maxCompositeContours); //must be 141 for wingding(?)
tableMaxp.maxCompositeContours = wReverse(tableMaxp.maxCompositeContours);
tableMaxp.maxStackElements = wReverse(tableMaxp.maxStackElements);
tableMaxp.maxSizeOfInstructions = wReverse(tableMaxp.maxSizeOfInstructions);
// fclose(tt_file);
return 0;
}
fint parseHheaTable(FILE* tt_file, ufshort* numOfHMetrics, ffloat* ascent, ffloat* descent, ffloat* lineGap)
{
uflong hTable = *(uflong*)HHEA_TABLE;
uflong offset;
Table_hhea tableHhea;
fint size;
if (searchTable(hTable, &offset, tt_file))
{
/* move position to the 'hhea' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for 'hhea' table.");
return -1;
}
/* read 'hhea' table header */
size = (fint)fread(&tableHhea, sizeof(Table_hhea), 1, tt_file);
if (size != 1){
// printf("Error reading Table 'hhea' from file.");
return -1;
}
}else
{
return -1;
}
*numOfHMetrics = wReverse(tableHhea.number_of_hMetrics);
*ascent = wReverse(tableHhea.ascender);
*descent = wReverse(tableHhea.descender);
*lineGap = wReverse(tableHhea.line_gap);
return 0;
}
fint parseOs2Table(FILE* tt_file, ffloat* strikeOutSize, ffloat* strikeOutOffset)
{
uflong hTable = *(uflong*)OS2_TABLE;
uflong offset;
Table_os2 tableOs2;
fint size;
if (searchTable(hTable, &offset, tt_file))
{
/* move position to the 'OS/2' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for 'OS/2' table.");
return -1;
}
/* read 'OS/2' table header */
size = (fint)fread(&tableOs2, sizeof(Table_os2), 1, tt_file);
if (size != 1){
// printf("Error reading Table 'OS/2' from file.");
return -1;
}
} else
{
return -1;
}
// tableOs2.usFirstCharIndex = wReverse(tableOs2.usFirstCharIndex);
// *ascent = wReverse(tableOs2.sTypoAscender);
// *descent = wReverse(tableOs2.sTypoDescender);
*strikeOutSize = wReverse(tableOs2.yStrikeoutSize);
*strikeOutOffset = wReverse(tableOs2.yStrikeoutPosition);
// fclose(tt_file);
return 0;
}
fint parsePostTable(FILE* tt_file, fshort* uOffset, fshort* uThickness)
{
uflong hTable = *(uflong*)POST_TABLE;
uflong offset;
Table_post tablePost;
fint size;
if (searchTable(hTable, &offset, tt_file))
{
/* move position to the 'post' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for 'post' table.");
return -1;
}
/* read 'post' table header */
size = (fint)fread(&tablePost, sizeof(Table_post), 1, tt_file);
if (size != 1){
// printf("Error reading Table 'post' from file.");
return -1;
}
} else
{
return -1;
}
*uOffset = wReverse(tablePost.underlineOffset);
*uThickness = wReverse(tablePost.underlineThickness);
return 0;
}
fint parseHmtxTable(FILE* tt_file, ufshort numOfHMetrics, HMetrics** hm)
{
uflong hTable = *(uflong*)HMTX_TABLE;
uflong offset;
fint size;
if (searchTable(hTable, &offset, tt_file))
{
/* move position to the 'hmtx' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for 'OS/2' table.");
return -1;
}
/* read 'hmtx' table */
*hm = new HMetrics[numOfHMetrics];
size = (fint)fread(*hm, sizeof(HMetrics), numOfHMetrics, tt_file);
if (size != numOfHMetrics){
delete[] *hm;
// printf("Error reading Table 'hmtx' from file.");
return -1;
}
for (fint i=0; i<numOfHMetrics;i++)
{
(*hm)[i].adwance_width = wReverse((*hm)[i].adwance_width);
}
} else
{
return -1;
}
return 0;
}
fint parseLocaTable(FILE* tt_file, GlyphOffsets* gOffsets, ufshort numGlyphs)
{
uflong hTable = *(uflong*)LOCA_TABLE;
uflong gTable = *(uflong*)GLYF_TABLE;
uflong offset,localGlyfOffset;
uflong *gLongOffsets = NULL;
ufshort *gShortOffsets = NULL;
fint size, i;
if (searchTable(hTable, &offset, tt_file) && searchTable(gTable,&localGlyfOffset,tt_file))
{
gLongOffsets = new uflong[numGlyphs+1];
if (!gOffsets->format)
gShortOffsets = new ufshort[numGlyphs+1];
/* move position to the 'loca' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0)
{
// printf("Error executing fseek() for 'loca' table.");
delete[] gLongOffsets;
gLongOffsets = NULL;
if (!gOffsets->format)
{
delete[] gShortOffsets;
}
return -1;
}
/* read 'loca' table */
if (gOffsets->format)
{
size = (fint)fread(gLongOffsets, sizeof(flong),numGlyphs+1, tt_file);
if (size != numGlyphs+1)
{
// printf("Error reading Table 'loca' from file.");
delete[] gLongOffsets;
gLongOffsets = NULL;
return -1;
}
for (i=0; i<=numGlyphs; i++)
gLongOffsets[i] = dwReverse(gLongOffsets[i])+localGlyfOffset;
}else
{
size = (fint)fread(gShortOffsets, sizeof(fshort), numGlyphs+1, tt_file);
if (size != numGlyphs+1)
{
// printf("Error reading Table 'loca' from file.");
delete[] gShortOffsets;
gShortOffsets = NULL;
delete[] gLongOffsets;
gLongOffsets = NULL;
return -1;
}
for (i=0;i<=numGlyphs;i++)
gLongOffsets[i] = wReverse(gShortOffsets[i])*2+localGlyfOffset;
}
gOffsets->offsets = gLongOffsets;
delete[] gShortOffsets;
}
// fclose(tt_file);
return 0;
};
fint parseCmapTable(FILE* tt_file, TableEncode* te)
{
uflong hTable = *(uflong*)CMAP_TABLE;
uflong offset;
Table_cmap tableCmap;
Cmap_Entry cmapRecord;
Table_encode_header tableEncodeHeader;
flong curPos;
fint i;
fint size;
if (searchTable(hTable, &offset, tt_file))
{
/* move position to the 'cmap' table */
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for 'cmap' table.");
return -1;
}
/* read 'cmap' table header */
size = (fint)fread(&tableCmap, sizeof(Table_cmap) - sizeof(Cmap_Entry), 1, tt_file);
if (size != 1){
// printf("Error reading Table 'cmap' from file.");
return -1;
}
tableCmap.numSubTables = wReverse(tableCmap.numSubTables);
for(i=0; i < tableCmap.numSubTables; i++)
{
size = (fint)fread(&cmapRecord, sizeof(Cmap_Entry), 1, tt_file);
if (size != 1)
{
// printf("Error reading cmap Record from file.");
return -1;
}
cmapRecord.encodingID = wReverse(cmapRecord.encodingID);
cmapRecord.platform = wReverse(cmapRecord.platform);
if(cmapRecord.platform == WINDOWS_PLATFORM_ID)
{
switch (cmapRecord.encodingID)
{
case UNICODE_ENCODING:
cmapRecord.table_offset = dwReverse(cmapRecord.table_offset);
/* Save current position if someting wrong with family name */
curPos = ftell(tt_file);
size = fseek( tt_file, offset + cmapRecord.table_offset, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for 'cmap' table.");
return -1;
}
size = (fint)fread(&tableEncodeHeader, sizeof(Table_encode_header), 1, tt_file);
if (size != 1)
{
// printf("Error reading Table Encode from file.");
return -1;
}
tableEncodeHeader.format = wReverse(tableEncodeHeader.format);
tableEncodeHeader.length = wReverse(tableEncodeHeader.length);
tableEncodeHeader.version = wReverse(tableEncodeHeader.version);
if (tableEncodeHeader.format == 0 && te->TableEncode == NULL)
{
ufchar *map = new ufchar[256];
te->format = 0;
size = (fint)fread(map, sizeof(ufchar), 256, tt_file);
if (size != 256)
{
// printf("Error reading map format 0");
delete[] map;
map = NULL;
} else
{
te->TableEncode = map;
}
}else if (tableEncodeHeader.format == 4 && te->TableEncode == NULL)
{
te->format = 4;
getTableEncode_4(tt_file, te, tableEncodeHeader.length);
}
size = fseek( tt_file, curPos, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for 'name' table.");
return -1;
}
break;
}
}
}
}
// fclose(tt_file);
return 0;
}
fint parseGlyphData(FILE* tt_file, const GlyphOffsets gO, ufshort numGlyphs, ufshort glyphIndex, TTCurve *curve, fshort* bRect, ffloat transform)
{
uflong offset;
Glyph_header glyphHeader;
fshort numOfContours;
ufshort *endPtsOfContours = NULL;
ufshort instructionLength;//instruction length in bytes
ufchar* instructions = NULL;
ufchar* flags = NULL;
ufchar* xCoord = NULL; //pointer to array of X coordinates
ufchar* yCoord = NULL; //pointer to array of Y coordinates
ufchar* tmp = NULL;
fint numPoints; // number of Points
fint size, i, j, curLen;
fint flagIndex = 0;
fint xCoordIndex = 0;
fint yCoordIndex = 0;
fint rep = 0;
fshort xLength = 0; //length of array of X coordinates
fshort yLength = 0; //length of array of Y coordinates
ufchar curFlag = 0;
if (glyphIndex >= numGlyphs)
{
// printf("debug info: glyphIndex out of range");
glyphIndex = 0;
}
offset = gO.offsets[glyphIndex];
if (offset == gO.offsets[glyphIndex+1])
{
curve->add(0,0, 1);
return 0;
}
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0){
// printf("Error executing fseek() for someone glyph.");
return -1;
}
/* read 'Glyph_header' table */
size = (fint)fread(&glyphHeader, sizeof(Glyph_header), 1, tt_file);
if (size != 1){
// printf("Error reading 'Glyph_header' table from file.");
return -1;
}
glyphHeader.number_of_contours = wReverse(glyphHeader.number_of_contours);
numOfContours = glyphHeader.number_of_contours;
bRect[0] = (short)(wReverse(glyphHeader.xMin)*transform);
bRect[1] = (short)(wReverse(glyphHeader.yMin)*transform);
bRect[2] = (short)(wReverse(glyphHeader.xMax)*transform);
bRect[3] = (short)(wReverse(glyphHeader.yMax)*transform);
if (numOfContours > 0)
{
endPtsOfContours = new ufshort[numOfContours];
size = (fint)fread(endPtsOfContours, sizeof(fshort),numOfContours,tt_file);
if (size != numOfContours)
{
// printf("Error reading endPtsOfContours for someone glyph.");
delete[] endPtsOfContours;
return -1;
}
for (i=0; i<numOfContours; i++)
{
endPtsOfContours[i] = wReverse(endPtsOfContours[i]);
}
numPoints = endPtsOfContours[i-1] + 1;
size = (fint)fread(&instructionLength,sizeof(fshort),1,tt_file);
if (size != 1)
{
// printf("Error reading length of instructions./n");
delete[] endPtsOfContours;
return -1;
}
instructionLength = wReverse(instructionLength);
instructions = new ufchar[instructionLength];
size = (fint)fread(instructions,sizeof(ufchar),instructionLength,tt_file);
if (size != instructionLength)
{
// printf("Error reading instructions./n");
delete[] instructions;
delete[] endPtsOfContours;
return -1;
}
curLen=0;
flags = NULL;
for (i=0; i<numPoints; i++)
{
fint x_repeat = 0;
fint y_repeat = 0;
tmp = flags;
curLen++;
flags = new ufchar[curLen];
memcpy(flags,tmp,curLen-1);
delete[] tmp;
size = (fint)fread(&(flags[curLen-1]),sizeof(ufchar),1,tt_file);
if (size != 1)
{
// printf("Error reading array of flags from font file.\n");
delete[] flags;
delete[] instructions;
delete[] endPtsOfContours;
return -1;
}
if ((flags[curLen-1] & X_POSITIVE) == X_POSITIVE ||
(flags[curLen-1] & X_POSITIVE) == X_NEGATIVE)
x_repeat = 1;
else if ((flags[curLen-1] & X_POSITIVE) == X_DWORD)
x_repeat = 2;
if ((flags[curLen-1] & Y_POSITIVE) == Y_POSITIVE ||
(flags[curLen-1] & Y_POSITIVE) == Y_NEGATIVE)
y_repeat = 1;
else if ((flags[curLen-1] & Y_POSITIVE) == Y_DWORD)
y_repeat = 2;
if(flags[curLen-1] & REPEAT)
{
tmp = flags;
curLen++;
flags = new ufchar[curLen];
memcpy(flags,tmp,curLen-1);
delete[] tmp;
size=(fint)fread(&(flags[curLen-1]),sizeof(ufchar),1,tt_file);
if (size != 1)
{
// printf("Error reading array of flags from font file.\n");
delete[] flags;
delete[] instructions;
delete[] endPtsOfContours;
return -1;
}
xLength += x_repeat*(flags[curLen-1] + 1);
yLength += y_repeat*(flags[curLen-1] + 1);
i += flags[curLen-1];
} else
xLength += x_repeat;
yLength += y_repeat;
}
xCoord = new ufchar[xLength];
yCoord = new ufchar[yLength];
size = (fint)fread(xCoord,sizeof(ufchar),xLength,tt_file);
if (size != xLength)
{
// printf("Error reading x-coordinate of glyph's point.\n");
delete[] flags;
delete[] instructions;
delete[] endPtsOfContours;
delete[] xCoord;
delete[] yCoord;
return -1;
}
size = (fint)fread(yCoord,sizeof(ufchar),yLength,tt_file);
if (size != yLength)
{
// printf("Error reading coordinates of glyph points.\n");
delete[] flags;
delete[] instructions;
delete[] endPtsOfContours;
delete[] xCoord;
delete[] yCoord;
return -1;
}
i=0;
rep=0;
fint x=0, y=0;
ffloat xFirstInContour,yFirstInContour;
bool contBegin;
for (j=0; j<numOfContours;j++)
{
fint repLim = endPtsOfContours[j];
contBegin = 1;
while(i<=repLim)
{
if (rep==0)
{
curFlag = flags[flagIndex];
flagIndex++;
rep = 1;
if (curFlag & REPEAT)
{
rep += flags[flagIndex];
flagIndex++;
}
}
fint xChange = 0, yChange = 0;
if ((curFlag & X_POSITIVE) == X_POSITIVE)
{
xChange = xCoord[xCoordIndex];
xCoordIndex++;
}else if ((curFlag & X_POSITIVE) == X_NEGATIVE)
{
xChange = -xCoord[xCoordIndex];
xCoordIndex++;
}else if ((curFlag & X_POSITIVE) == X_DWORD)
{
xChange = (fshort)((xCoord[xCoordIndex]<<8)+xCoord[xCoordIndex+1]);
xCoordIndex+=2;
}
if ((curFlag & Y_POSITIVE) == Y_POSITIVE)
{
yChange = yCoord[yCoordIndex];
yCoordIndex++;
}else if ((curFlag & Y_POSITIVE) == Y_NEGATIVE)
{
yChange = -yCoord[yCoordIndex];
yCoordIndex++;
}else if ((curFlag & Y_POSITIVE) == Y_DWORD)
{
yChange = (fshort)((yCoord[yCoordIndex]<<8)+yCoord[yCoordIndex+1]);
yCoordIndex+=2;
}
if((flagIndex >1) && !(curFlag & ON_CURVE ) &&
((rep == 1) ? (!(flags[flagIndex-2] & ON_CURVE)) : (!(flags[flagIndex-3] & ON_CURVE))))
curve->add((x+xChange/2)*transform,(y+yChange/2)*transform,FLAG_ONCURVE);
x+=xChange;
y+=yChange;
if (contBegin)
{
curve->add(x*transform,y*transform, 1);
xFirstInContour = x*transform;
yFirstInContour = y*transform;
contBegin = 0;
} else
curve->add(x*transform,y*transform, curFlag & ON_CURVE ? FLAG_ONCURVE : 0);
rep--;
i++;
}
curve->add(xFirstInContour,yFirstInContour,FLAG_ONCURVE);
}
}
delete[] xCoord;
delete[] yCoord;
delete[] flags;
delete[] endPtsOfContours;
delete[] instructions;
return 0;
}
/* Should be removed when the composite glyph parsing will be realized */
bool isCompositeGlyph(FILE* tt_file, const GlyphOffsets gO, ufshort numGlyphs, ufshort glyphIndex)
{
uflong offset;
Glyph_header glyphHeader;
fint size;
if (glyphIndex >= numGlyphs)
glyphIndex = 0;
offset = gO.offsets[glyphIndex];
if (offset == gO.offsets[glyphIndex+1])
return false;
/*printf("glyphIndex = %d\n",glyphIndex);
if (tt_file == NULL)
printf("file is NULL\n");
else
printf("file isn't NULL\n");*/
size = fseek(tt_file, offset, SEEK_SET);
if (size != 0)
{
//printf("return false\n");
return false;
}
//printf("second return\n");
/* read 'Glyph_header' table */
size = (fint)fread(&glyphHeader, sizeof(Glyph_header), 1, tt_file);
if (size != 1)
return false;
//printf("third return\n");
return wReverse(glyphHeader.number_of_contours) < 0;
}