Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2664 lines
60 KiB

//
// Copyright (c) 1997-1999 Microsoft Corporation.
//
#include "stdafx.h"
#include "eudcedit.h"
#include "util.h"
#pragma pack(2)
#include "vdata.h"
#include "ttfstruc.h"
#include "extfunc.h"
/*
* TrueType File I/F
*/
#define GLYPHBUFSIZ 0xFFFFL
#define RWBUFSIZ 16384
#define EUDCCODEBASE ((unsigned short)0xE000) /* 0xe000 uni-code */
#define NUMTABLES 15
#define NAMEBUFSIZ 1024
#define NUMOFNAMEREC 8
static void initDirEntry(struct TableEntry *e,int num);
static int setDirEntry(struct TableEntry *e,char *tag);
void smtoi(short *sval);
void lmtoi(long *lval);
void sitom(short *sval);
void litom(long *lval);
static int align32(int siz);
static unsigned long calchksum(char *buf,int siz);
static int copyblk(HDC hDC,char *tag,int ofHdl,long siz,char *buf,int bufsiz,unsigned long *cs);
static int mergeblock(HDC hDC,struct TableEntry *entry,int ofHdl);
static int tableChkSum(int fH,struct TableEntry *te);
static int codeToGID(unsigned short code);
int TTFReadHdr(HANDLE fHdl,struct TTFHeader *hdr);
int TTFWriteHdr(HANDLE fHdl,struct TTFHeader *hdr);
int TTFReadDirEntry(HANDLE fHdl,struct TableEntry *entry,int eCnt);
int TTFWriteDirEntry(HANDLE fHdl,struct TableEntry *entry,int eCnt);
static struct TableEntry *searchEntry(struct TableEntry *entry,int eCnt,char *tag);
int TTFGetTableEntry(HANDLE fH,struct TableEntry *entry,char *tag);
int TTFReadTable(HANDLE fH,struct TableEntry *entry,void *buf,int bufsiz);
int TTFReadFixedTable(HANDLE fH,char *buf,int bufsiz,char *tag);
int TTFReadVarTable(HANDLE fH,char * *buf,unsigned int *bufsiz,char *tag);
int TTFWriteTable(HANDLE fH,struct TableEntry *entry,void *buf,int bufsiz);
int TTFAppendTable(HANDLE fH,struct TableEntry *entry,void *buf,int siz);
static int TTFMergeTable(HDC hDC,HANDLE nfh,char *tag,struct TableEntry *nte);
#ifdef BUILD_ON_WINNT
static int __cdecl compentry(const void *e1,const void *e2);
#else
static int compentry(const void *e1,const void *e2);
#endif // BUILD_ON_WINNT
static void SortEntry(struct TableEntry *ebuf,int num);
static int fileChkSum(HANDLE fh,struct TableEntry *entry,int numEntry,struct TTFHeader *hdr,struct HeadTable *head);
static void makeTTFHeader(struct TTFHeader *hdr,int nTbl);
static int makeGlyphData(int lstH,struct BBX *bbx,char *glyphData,int bufsiz,int *gdatsiz);
static void initsetgbuf(char *b,int lim);
static int setgbuf(char *dat,int siz,char * *np);
static int termbuf(void);
static int strwlen(char *s);
static void strwcat(char *s1,char *s2);
static void setnamebuf(char *buf,int *siz, short EncodingID);
static void modifyOS2(char *buf);
static void modifyhead(struct HeadTable *head);
static void setVhea(struct VheaTable *vhea,struct HheaTable *hhea,struct BBX *bbx);
static int updateMaxp(struct MaxpTbl *maxp,int lstHdl);
static int TTFGetOrgTableEntry(HDC hDC,struct TableEntry *entry,char *tag);
int TTFReadOrgFixedTable(HDC hDC,char *buf,int bufsiz,char *tag);
int TTFReadOrgVarTable(HDC hDC,char * *buf,unsigned int *bufsiz,char *tag);
static void setCountryData(short EncodingID);
static int WIFEOS2(HDC hDC,char * *os2buf,int *os2TblSiz,struct BBX *bbx);
static void WIFEhhea(struct HheaTable *hhea,struct BBX *bbx);
static void WIFEhead(struct HeadTable *head,struct BBX *bbx);
static void WIFEpost(struct postTable *post);
int TTFCreate(HDC hDC,TCHAR *newf,struct BBX *bbx,int lstHdl,int fontType);
int TTFGetBBX(HDC hDC,struct BBX *bbx,short *uPEm);
int TTFTmpPath(TCHAR *path,TCHAR *tmpPath);
static int copyTable(HANDLE iFh,HANDLE oFh,struct TableEntry *te,int nEntry,char *tag);
static int copyfblock(HANDLE iFh,HANDLE oFh,unsigned long siz,unsigned long *cs);
static int mergeGlyph(HANDLE iFh,HANDLE oFh,struct TableEntry *tep,char *locabuf,int glyphID,char *glyphData,int glyphSiz);
static void frebuf(void);
int TTFOpen(TCHAR *path);
int TTFClose(void);
int TTFGetEUDCBBX(TCHAR *path,struct BBX *bbx,short *upem);
static void makeMetrics(int lsthdl,struct HMetrics *hM,struct VMetrics *vM,struct BBX *bbx);
int TTFAppend(unsigned short code,struct BBX *bbx,int lsthdl);
int TTFImpCopy(TCHAR *sPath,TCHAR *dPath);
int TTFImpGlyphCopy(HANDLE sFh,int glyphID);
int TTFImpGlyphWrite(int glyphID, char *buf, int siz);
int TTFLastError();
/**
* static variables
**/
static struct TableEntry *et;
static int entryNum;
static int entryCnt;
static int numOfGlyph=0;
static int lastErr = 0;
/**
* static table data
**/
static char cvtdata[] = {0, 0};
static char fpgmdata[]={ (char)0xb0, (char)0x00, (char)0x2c, (char)0x2d};
static char prepdata[]={(char)0xb8, 0x1, (char)0xff, (char)0x85,
(char)0xb0, (char)0x01, (char)0x8d};
static char maxpdata[]={ /* JPN */
0x00, 0x01, 0x00, 0x00,
(char)0x07, (char)0x5a, /* 1882 numGlyph of JPN */
0, 4, 0, 1 , /* maxP, maxC(nullGlyf value)*/
0, 0, 0, 0, /* maxCom*2*/
0, 1, 0, 0, /* maxZones, maxTw*/
0, 0, 0, 1, /* maxStorage, maxFunc*/
0, 0, 0, 1, /* maxI, maxStack */
0, 1, 0, 1, 0, 1
};
static char cmapdata[] = {
0, 0, 0, 1,
0, 3, 0, 1,
0, 0, 0, 12,
0, 4, 0, 32, 0, 0, 0, 4, 0, 4, 0, 1, 0, 0,
(char)0xe7, (char)0x57, (char) 0xff,(char) 0xff, /* last code */
0, 0,
(char)0xe0, (char)0x00, (char)0xff,(char) 0xff,
0x20, 0x02, 0x00, 0x01,
0, 0, 0, 0
};
static char namerecstr[NUMOFNAMEREC][16] ={
{ 0, '0', 0, '0', 0, 0},
{ 0,'E', 0,'U', 0, 'D',0,'C', 0,0},
{ 0,'R', 0, 'e', 0,'g', 0,'u', 0,'l', 0,'a', 0,'r',0,0},
{ 0, '0', 0,'0', 0, 0},
{ 0,'E', 0,'U', 0, 'D',0,'C', 0,0},
{ 0, '0', 0,'0', 0, 0},
{ 0, '0', 0,'0',0, 0},
{ 0, '0', 0,'0',0, 0}
};
static void
initDirEntry( struct TableEntry *e, int num)
{
et = e;
entryNum = num;
entryCnt = 0;
}
static int
setDirEntry(struct TableEntry *e, char *tag)
{
if ( entryCnt >= entryNum)
return -1;
memcpy( e->tagName, tag, TAGSIZ);
*(et+entryCnt) = *e;
entryCnt++;
return 0;
}
void
smtoi( short *sval)
{
short retval;
unsigned char *cp;
cp = (unsigned char *)sval;
retval = *cp++;
retval <<=8;
retval += *cp;
*sval = retval;
}
void
lmtoi( long *lval)
{
long retval;
unsigned char *cp;
int i;
cp = (unsigned char *)lval;
retval = (long)*cp++;
for(i=0; i<3; i++) {
retval <<=8;
retval |= (long)*cp++;
}
*lval = retval;
}
void
sitom( short *sval)
{
unsigned char *cp;
short setval;
setval = *sval;
cp = (unsigned char *)sval;
*cp++ = (unsigned char)((setval>>8)&0xff);
*cp++ = (unsigned char)(setval&0xff);
}
void
litom( long *lval)
{
long setval;
int i;
unsigned char *cp;
setval = *lval;
cp = (unsigned char *)lval;
cp += 3;
for ( i = 0; i<4; i++) {
*cp--=(char )(setval&0xff);
setval >>=8;
}
}
static int
align32( int siz)
{
siz = (siz + 3)/4 * 4;
return siz;
}
static unsigned long
calchksum( char *buf, int siz)
{
unsigned long *csp;
unsigned long chksum;
unsigned long lval;
unsigned char pad[4];
int i;
int padsiz;
unsigned char *cp;
int csc;
csp = (unsigned long *)buf;
csc = siz/4;
chksum = 0;
while ( csc-->0) {
lval = *csp++;
lmtoi( (long *)&lval);
chksum += lval;
}
padsiz = (siz+3)/4*4 - siz;
if ( padsiz) {
cp = (unsigned char *)csp;
i = 0;
while (padsiz++<4)
pad[i++]=*cp++;
csp = (unsigned long *)pad;
lval = *csp;
lmtoi( (long *)&lval);
chksum += lval;
}
return chksum;
}
static int
copyblk(HDC hDC, char *tag, HANDLE ofHdl, long siz, char *buf, int bufsiz, unsigned long *cs)
{
int rwsiz;
int filsiz;
int aligne;
unsigned long chksum;
long ofs;
DWORD dwTable, nByte;
dwTable = *(DWORD *)tag;
filsiz = (int)(siz % 4);
if ( filsiz) filsiz = 4-filsiz;
ofs = 0L;
aligne =0;
chksum = 0;
while ( siz > 0) {
if ( siz > bufsiz)
rwsiz = bufsiz;
else {
rwsiz = (int)siz;
if ( filsiz)
aligne =1;
}
if ( GetFontData(hDC, dwTable, (DWORD)ofs, buf,(DWORD)rwsiz )
!= (DWORD)rwsiz)
goto ERET;
if ( aligne ) {
memset( buf+siz, 0, filsiz);
rwsiz += filsiz;
}
chksum += calchksum( buf, rwsiz);
BOOL res = WriteFile( ofHdl, buf, (unsigned int)rwsiz, &nByte, NULL);
if (!res || nByte !=(unsigned int)rwsiz)
goto ERET;
siz -= rwsiz;
ofs += rwsiz;
}
*cs = chksum;
return 0;
ERET:
return -1;
}
static int
mergeblock( HDC hDC, struct TableEntry *entry, HANDLE ofHdl)
{
long ofs;
char *mem;
unsigned long cs; /* CheckSum value */
mem = (char *)malloc((size_t) RWBUFSIZ);
if ( mem==(char *)0)
return -1;
/* Obtain start offset of Output table */
ofs = SetFilePointer( ofHdl, 0L, NULL, FILE_CURRENT);
if (copyblk( hDC, entry->tagName, ofHdl, entry->siz, mem, RWBUFSIZ, &cs))
goto ERET;
entry->ofs = ofs;
entry->checkSum = cs;
free( mem);
return 0;
ERET:
free( mem);
return -1;
}
static int
tableChkSum( HANDLE fH, struct TableEntry *te)
{
char *rwbuf;
unsigned long cs;
long lsiz;
int rwsiz;
if ( te->siz==0)
return 0;
if ((rwbuf = (char *)malloc( (size_t)RWBUFSIZ))==(char *)0)
return -1;
if ( (long) SetFilePointer( fH, te->ofs, NULL, FILE_BEGIN)!=te->ofs)
goto ERET;
cs = 0;
lsiz = te->siz;
while ( lsiz > 0) {
if (lsiz > RWBUFSIZ)
rwsiz = RWBUFSIZ;
else rwsiz = (int)lsiz;
lsiz -= rwsiz;
cs += calchksum( rwbuf, rwsiz);
}
te->checkSum = cs;
free( rwbuf);
return 0;
ERET:
free( rwbuf);
return -1;
}
static int
codeToGID( unsigned short code)
{
return (int)( code - (unsigned short)EUDCCODEBASE +2);
}
int
TTFReadHdr ( HANDLE fHdl, struct TTFHeader *hdr)
{
DWORD nBytesRead;
SetFilePointer( fHdl, 0L, NULL, FILE_BEGIN);
BOOL res=ReadFile( fHdl, hdr, sizeof(struct TTFHeader),&nBytesRead, NULL);
if (!res || nBytesRead !=sizeof(struct TTFHeader)) {
return -1;
}
smtoi( &hdr->numTables);
smtoi( &hdr->searchRange);
smtoi( &hdr->entrySelector);
smtoi( &hdr->rangeShift);
return 0;
}
int
TTFWriteHdr ( HANDLE fHdl, struct TTFHeader *hdr)
{
struct TTFHeader whdr;
whdr = *hdr;
sitom( &whdr.numTables);
sitom( &whdr.searchRange);
sitom( &whdr.entrySelector);
sitom( &whdr.rangeShift);
if (SetFilePointer( fHdl, 0L, NULL, FILE_BEGIN)!=0L)
return -1;
DWORD nByte;
BOOL res = WriteFile( fHdl, (BYTE *) &whdr, sizeof(struct TTFHeader), &nByte, NULL);
if (!res || nByte !=sizeof(struct TTFHeader))
return -1;
return 0;
}
int
TTFReadDirEntry( HANDLE fHdl, struct TableEntry *entry, int eCnt)
{
long ofs;
DWORD nByte;
BOOL res;
ofs = sizeof (struct TTFHeader);
if ( (long) SetFilePointer( fHdl, ofs, NULL, FILE_BEGIN)!=ofs)
return -1;
res = ReadFile( fHdl, entry, (unsigned int)(sizeof(struct TableEntry)*eCnt), &nByte, NULL);
if (!res || nByte !=(unsigned int)sizeof(struct TableEntry)*eCnt)
return -1;
while ( eCnt-->0) {
lmtoi((long *)&entry->checkSum);
lmtoi(&entry->ofs);
lmtoi(&entry->siz);
entry++;
}
return 0;
}
int
TTFWriteDirEntry( HANDLE fHdl, struct TableEntry *entry, int eCnt)
{
long ofs;
struct TableEntry wentry;
DWORD nByte;
BOOL res;
ofs = sizeof (struct TTFHeader);
if ( (long) SetFilePointer( fHdl, ofs, NULL, FILE_BEGIN)!=ofs)
return -1;
/* Write Entries */
while ( eCnt-->0) {
wentry = *entry++;
litom((long *)&wentry.checkSum);
litom(&wentry.ofs);
litom(&wentry.siz);
res = WriteFile( fHdl,(char *) &wentry, sizeof wentry, &nByte, NULL);
if (!res || nByte !=sizeof wentry) {
return -1;
}
}
return 0;
}
static struct TableEntry *
searchEntry(struct TableEntry *entry, int eCnt, char *tag)
{
while ( eCnt-->0) {
if (memcmp( entry->tagName, tag, TAGSIZ)==0)
return entry;
entry++;
}
return (struct TableEntry *)0;
}
int
TTFGetTableEntry( HANDLE fH, struct TableEntry *entry, char *tag)
{
struct TTFHeader hdr;
struct TableEntry *te, *rte;
int msiz;
te = 0;
/* Read TTF Header to get numTables */
if (TTFReadHdr( fH, &hdr))
goto ERET;
msiz = sizeof(struct TableEntry)*hdr.numTables;
if ( (te = (struct TableEntry *)malloc((size_t)msiz))==(struct TableEntry *)0)
goto ERET;
/* Read entry whole */
if ( TTFReadDirEntry( fH, te, hdr.numTables))
goto ERET;
/* Search for entry with tag */
if ((rte = searchEntry(te, (int)hdr.numTables, tag))==0)
goto ERET;
*entry = *rte;
free(te);
return 0;
ERET:
if (te) free(te);
return -1;
}
/***********************************************************************
* Read Table at once with entry data
*/
/* */ int
/* */ TTFReadTable(
/* */ HANDLE fH,
/* */ struct TableEntry *entry,
/* */ void *buf,
/* */ int bufsiz)
/*
* returns : read size
***********************************************************************/
{
unsigned int rdsiz;
DWORD nByte;
BOOL res;
if ((long) SetFilePointer( fH, entry->ofs, NULL, FILE_BEGIN)!=entry->ofs)
goto ERET;
rdsiz = bufsiz >= (int)entry->siz ? (unsigned int)entry->siz
: (unsigned int)bufsiz;
res = ReadFile( fH, buf, rdsiz, &nByte, NULL);
if (!res || nByte!=rdsiz)
goto ERET;
if ( rdsiz < (unsigned int)bufsiz)
memset((unsigned char *)buf + rdsiz, 0, bufsiz - rdsiz);
return (int)rdsiz;
ERET:
return -1;
}
/***********************************************************************
* Read Fixed Size Table at onece with tag
*/
/* */ int
/* */ TTFReadFixedTable(
/* */ HANDLE fH,
/* */ char *buf,
/* */ int bufsiz,
/* */ char *tag)
/*
* returns : 0, -1
***********************************************************************/
{
struct TableEntry te;
if (TTFGetTableEntry( fH, &te, tag))
goto ERET;
if ( TTFReadTable( fH, &te, buf, bufsiz )!=bufsiz)
goto ERET;
return 0;
ERET:
return -1;
}
/***********************************************************************
* Read Variable Size Table at onece with tag
*/
/* */ int
/* */ TTFReadVarTable(
/* */ HANDLE fH,
/* */ char **buf, /* Buffer pointer (be set) */
/* */ unsigned int *bufsiz, /* Buffer Size ( be set) */
/* */ char *tag) /* Tag name */
/*
* returns : 0, -1
* remarks : allocated memory must be free by caller
***********************************************************************/
{
struct TableEntry te;
char *mem;
if (TTFGetTableEntry( fH, &te, tag))
goto ERET;
if ((mem = (char *)malloc( (size_t)te.siz))==(char *)0)
goto ERET;
if ( TTFReadTable( fH, &te, mem, (int)te.siz )!=(int)te.siz)
goto ERET;
*buf = mem;
*bufsiz = (unsigned int)te.siz;
return 0;
ERET:
return -1;
}
/***********************************************************************
* Write Table
*/
/* */ int
/* */ TTFWriteTable(
/* */ HANDLE fH,
/* */ struct TableEntry *entry,
/* */ void *buf,
/* */ int bufsiz)
/*
* returns : written size
* remarks : update checksum
***********************************************************************/
{
int wsiz;
DWORD nByte;
BOOL res;
if ((long) SetFilePointer( fH, entry->ofs, NULL, FILE_BEGIN)!=entry->ofs)
goto ERET;
wsiz = bufsiz >= (int)entry->siz ? (int)entry->siz : bufsiz;
res = WriteFile( fH, (char *)buf, (unsigned int)wsiz, &nByte, NULL);
if (!res || nByte !=(unsigned int)wsiz)
goto ERET;
entry->checkSum = calchksum( (char *)buf, bufsiz);
return wsiz;
ERET:
return -1;
}
/***********************************************************************
* Write Table
*/
/* */ int
/* */ TTFAppendTable(
/* */ HANDLE fH,
/* */ struct TableEntry *entry, /* value be set */
/* */ void *buf,
/* */ int siz)
/*
* returns : 0, -1
* remarks : enttry->siz not aligned 32bit
***********************************************************************/
{
long ofs;
BYTE pad[4];
int padsiz;
DWORD nByte;
BOOL res;
if ( (ofs=(long) SetFilePointer( fH, 0L, NULL, FILE_CURRENT))<0L)
goto ERET;
res = WriteFile( fH, buf, (unsigned int)siz, &nByte, NULL);
if (!res || nByte !=(unsigned int)siz)
goto ERET;
/* 32 bit Word aligne */
if ( siz % 4) {
padsiz = 4 - siz%4;
memset(pad,0,4);
res = WriteFile(fH,pad, (unsigned int)padsiz, &nByte, NULL);
if (!res || nByte !=(unsigned int)padsiz)
goto ERET;
}
entry->ofs = ofs;
entry->siz = siz;
entry->checkSum = calchksum((char *) buf, siz);
return 0;
ERET:
return -1;
}
/***********************************************************************
* Merge Table
*/
/* */ static int
/* */ TTFMergeTable(
/* */ HDC hDC,
/* */ HANDLE nfh,
/* */ char tag[4],
/* */ struct TableEntry *nte)
/*
* returns : 0
***********************************************************************/
{
if (TTFGetOrgTableEntry( hDC, nte, tag))
return -1;
if (mergeblock( hDC, nte, nfh))
return -1;
return 0;
}
int
#ifdef BUILD_ON_WINNT
__cdecl
#endif // BUILD_ON_WINNT
compentry( const void *e1, const void *e2)
{
struct TableEntry *te1, *te2;
te1 = (struct TableEntry *)e1;
te2 = (struct TableEntry *)e2;
return memcmp(te1->tagName, te2->tagName,4);
}
static void
SortEntry(struct TableEntry *ebuf, int num)
{
if ( num <=0) return;
qsort( ebuf, num, sizeof(struct TableEntry), compentry);
}
static int
fileChkSum(
HANDLE fh,
struct TableEntry *entry,
int numEntry,
struct TTFHeader *hdr,
struct HeadTable *head)
{
unsigned long lval, cs;
unsigned long *lp;
struct TableEntry *e;
int n;
struct TableEntry *headp;
DWORD nByte;
BOOL res;
e = entry;
n = numEntry;
cs = 0;
head->chkSum = 0;
headp = 0;
while ( n-->0) {
lp = (unsigned long *)e->tagName;
if (memcmp( e->tagName,"head", 4)==0)
headp = e;
lval = *lp;
lmtoi( (long *)&lval);
cs += lval;
cs += e->checkSum;
cs += e->checkSum;
cs += e->ofs;
cs += e->siz;
e++;
}
if (headp==0)
return -1;
cs += calchksum( (char *)hdr, sizeof(struct TTFHeader) );
if ((long) SetFilePointer( fh, headp->ofs, NULL, FILE_BEGIN)!=headp->ofs)
goto ERET;
head->chkSum = (unsigned long)0xb1b0afbaL - cs;
litom( (long *)&head->chkSum);
res = WriteFile(fh,(char *)head,sizeof(struct HeadTable), &nByte, NULL);
if (!res || nByte !=sizeof(struct HeadTable))
goto ERET;
return 0;
ERET:
return -1;
}
static void
makeTTFHeader( struct TTFHeader *hdr, int nTbl)
{
int po;
int n;
int ponum;
po = 0;
n = nTbl;
ponum = 1;
while ( n>=2) {
n /= 2;
po++;
ponum*=2;
}
hdr->sfnt_version[0]= hdr->sfnt_version[2]= hdr->sfnt_version[3]= 0;
hdr->sfnt_version[1]= 0x01;
hdr->numTables = (short)nTbl;
hdr->searchRange = (short)ponum*16;
hdr->entrySelector = (short)po;
hdr->rangeShift = (short)( nTbl*16)-hdr->searchRange;
return ;
}
/***********************************************************************
* make GlyphData from lst
*/
/* */ static int
/* */ makeGlyphData(
/* */ int lstH,
/* */ struct BBX *bbx, /* Set value to header */
/* */ char *glyphData,
/* */ int bufsiz,
/* */ int *gdatsiz)
/*
* returns : 0, -1
***********************************************************************/
{
char *flgp, *sflgp;
char flag;
char *dummyp;
struct VHEAD *vhd,
*svhd;
struct glyfHead ghdr;
int nCnt;
struct VDATA *vp;
int nPnt;
int pntSum;
int cnt;
short sval;
short px, py;
short relx, rely;
char cval;
initsetgbuf ( glyphData, bufsiz);
if( ( nCnt = VDGetNCont( lstH))<0)
goto ERET;
else if (nCnt == 0) { /* Space Character */
*gdatsiz = 0;
return 0;
}
ghdr.numberOfContour = (short)nCnt;
sitom( &ghdr.numberOfContour );
ghdr.xMin = (short)bbx->xMin;
sitom( &ghdr.xMin);
ghdr.yMin = (short)bbx->yMin;
sitom( &ghdr.yMin);
ghdr.xMax = (short)bbx->xMax;
sitom( &ghdr.xMax);
ghdr.yMax = (short)bbx->yMax;
sitom( &ghdr.yMax);
if (setgbuf( (char *)&ghdr, sizeof ghdr, &flgp))
goto ERET2;
if (VDGetHead( lstH, &vhd))
goto ERET;
pntSum = 0;
svhd = vhd;
/* Set each Contour Last point number */
for ( cnt = 0; cnt < nCnt; cnt++) {
pntSum += vhd->nPoints;
sval = pntSum-1;
sitom( &sval);
if ( setgbuf((char *)&sval, sizeof( short), &flgp))
goto ERET2;
vhd = vhd->next;
}
/* Toatal number of instructions */
sval = 0;
if ( setgbuf((char *)&sval, sizeof( short), &flgp))
goto ERET2;
/* Set flags */
vhd = svhd;
px = py = 0;
for ( cnt = 0; cnt < nCnt; cnt++) {
vp = vhd->headp;
nPnt = vhd->nPoints;
while ( nPnt-->0) {
flag = (vp->vd.atr&1)==0 ? (char)GLYF_ON_CURVE :(char)0;
relx = vp->vd.x - px;
rely = vp->vd.y - py;
if ( relx == 0)
flag |= GLYF_X_SAME;
else if ( relx > 0 && relx < 256)
flag |= GLYF_X_SHORT_P;
else if ( relx < 0 && relx > -256)
flag |= GLYF_X_SHORT_N;
if ( rely == 0)
flag |= GLYF_Y_SAME;
else if ( rely > 0 && rely < 256)
flag |= GLYF_Y_SHORT_P;
else if ( rely < 0 && rely > -256)
flag |= GLYF_Y_SHORT_N;
if (setgbuf((char *) &flag, 1, &dummyp))
goto ERET2;
px = vp->vd.x;
py = vp->vd.y;
vp = vp->next;
}
vhd = vhd->next;
}
/* set X */
vhd = svhd;
sflgp = flgp;
px = 0;
for ( cnt = 0; cnt < nCnt; cnt++) {
vp = vhd->headp;
nPnt = vhd->nPoints;
while ( nPnt-->0) {
relx = vp->vd.x - px;
if ( *flgp & GLYF_X_SHORT) {
if ( (*flgp & GLYF_X_SAME)==0)
relx = -relx;
cval = (char)relx;
if ( setgbuf( &cval, 1, &dummyp))
goto ERET2;
}
else if ( *flgp & GLYF_X_SAME)
;
else {
sitom( &relx);
if ( setgbuf( (char *)&relx, 2, &dummyp))
goto ERET2;
}
flgp++;
px = vp->vd.x;
vp = vp->next;
}
vhd = vhd->next;
}
/* set Y */
vhd = svhd;
flgp = sflgp;
py = 0;
for ( cnt = 0; cnt < nCnt; cnt++) {
vp = vhd->headp;
nPnt = vhd->nPoints;
while ( nPnt-->0) {
rely = vp->vd.y - py;
if ( *flgp & GLYF_Y_SHORT) {
if ( (*flgp & GLYF_Y_SAME)==0)
rely = -rely;
cval = (char)rely;
if ( setgbuf( &cval, 1, &dummyp))
goto ERET2;
}
else if ( *flgp & GLYF_Y_SAME)
;
else {
sitom( &rely);
if ( setgbuf((char *)&rely, 2, &dummyp))
goto ERET2;
}
flgp++;
py = vp->vd.y;
vp = vp->next;
}
vhd = vhd->next;
}
*gdatsiz = termbuf();
return 0;
ERET:
return -1;
ERET2:
return -2;
}
static char *sbuf;
static int limcnt;
static char *setp;
static int bcnt;
static void
initsetgbuf( char *b, int lim)
{
setp = sbuf = b;
limcnt = lim;
bcnt = lim; /* decremental counter */
return;
}
static int
setgbuf( char *dat, int siz, char **np)
{
if ( siz > bcnt) return -1;
memcpy( setp, dat, siz);
setp += siz;
bcnt -= siz;
*np = setp;
return 0;
}
static int
termbuf( )
{
int siz;
siz = limcnt - bcnt;
siz = siz % 4;
if ( siz) {
while ( siz++<4) {
*setp++=0;
bcnt--;
}
}
return limcnt - bcnt;
}
static int
strwlen( char *s)
{
int len;
len = 0;
while (*s || *(s+1)) {
s+=2;
len++;
}
return len*2;
}
static void
strwcat( char *s1, char *s2)
{
while (*s1 || *(s1+1))
s1+=2;
while ( *s2 || *(s2+1)) {
*s1++ = *s2++;
*s1++ = *s2++;
}
*s1++ = 0;
*s1++ = 0;
return;
}
static void
setnamebuf( char *buf, int *siz, short EncodingID)
{
int strsiz;
short strofs;
char *strp;
struct NamingTable *nt;
struct NameRecord *nr;
int rec;
int slen;
strofs = sizeof(struct NamingTable)
+ sizeof(struct NameRecord)*NUMOFNAMEREC;
strsiz = 0;
strp = buf +strofs;
*strp=(char)0;
*(strp+1)=(char)0;
nt = (struct NamingTable *)buf;
nt->OfsToStr = strofs;
sitom( &nt->OfsToStr);
nr = (struct NameRecord *)(buf + sizeof(struct NamingTable));
/* Set name record */
strofs = 0;
for ( rec = 0; rec<NUMOFNAMEREC; rec++, nr++) {
nr ->PlatformID = 3;
sitom(&nr ->PlatformID);
nr ->PlatformSpecEncID = EncodingID;
sitom(&nr ->PlatformSpecEncID);
nr ->LanguageID = (short)CountryInfo.LangID;
sitom(&nr ->LanguageID);
nr ->NameID = (short)rec;
sitom(&nr ->NameID);
strwcat( strp,namerecstr[rec]);
slen = strwlen(namerecstr[rec]);
nr -> StringLength = (short)slen;
sitom(&nr -> StringLength );
strsiz += slen;
nr -> StringOfs = strofs;
sitom(&nr -> StringOfs);
strofs += (short)slen;
}
nt->FormSel = 0;
nt->NRecs = NUMOFNAMEREC;
sitom( &nt->NRecs);
*siz = strsiz+ sizeof(struct NamingTable)
+ sizeof(struct NameRecord)*NUMOFNAMEREC;
}
static void
modifyOS2( char *buf)
{
/* Allow all license */
*(buf+9) = (char)0x00;
/* Set aulUnicodeRange Privete Use Area bit*/
*(buf+0x31) |= 0x31;
}
static void
modifyhead( struct HeadTable *head)
{
head->chkSum=0L;
memset( head->createdDate, 0, 8);
memset( head->updatedDate, 0, 8);
head->indexToLocFormat = 1;
head->glyphDataFormat = 0;
sitom( &head->indexToLocFormat );
sitom( &head->glyphDataFormat);
}
/*
* Set Vertical Header with Horizontal Header and Bounding Box
*/
static void
setVhea( struct VheaTable *vhea, struct HheaTable *hhea, struct BBX *bbx)
{
memcpy( vhea, hhea, sizeof(struct HheaTable));
vhea->minTopSideBearing = 0;
vhea->minBottomSideBearing = 0;
vhea->caretSlopeRise = 0;
vhea->caretSlopeRun = 1;
sitom( &vhea->caretSlopeRun );
vhea->numOfLongVerMetrics = (short)numOfGlyph;
sitom( &vhea->numOfLongVerMetrics );
}
static int
updateMaxp( struct MaxpTbl *maxp, int lstHdl)
{
struct VHEAD *vhd;
short sval;
int nCnt;
int ttlPnt;
int updflg;
updflg = 0;
if ( (nCnt = VDGetNCont( lstHdl))<0)
goto ERET;
else if ( nCnt ==0)
goto RET;
sval = maxp->maxContours;
smtoi( &sval);
if ( sval < nCnt) {
sval = (short)nCnt;
sitom(&sval);
maxp->maxContours = sval;
updflg = 1;
}
if (VDGetHead( lstHdl, &vhd))
goto ERET;
ttlPnt = 0;
while ( nCnt-->0) {
ttlPnt += vhd->nPoints;
vhd = vhd->next;
}
sval = maxp->maxPoints;
smtoi( &sval);
if ( sval < ttlPnt) {
sval = (short)ttlPnt;
sitom(&sval);
maxp->maxPoints = sval;
updflg = 1;
}
RET:
return updflg;
ERET:
return -1;
}
/***********************************************************************
* Obtain Original TTF Table Size
*/
/* */ static int
/* */ TTFGetOrgTableEntry(
/* */ HDC hDC,
/* */ struct TableEntry *entry,
/* */ char *tag)
/*
* returns : 0, -1
***********************************************************************/
{
DWORD dwTable; /* Metric Table to request */
DWORD siz;
dwTable = *(DWORD *)tag;
siz = GetFontData(hDC, dwTable, (DWORD)0, (char *)0, (DWORD)0);
if ( siz == GDI_ERROR) return -1;
else {
memcpy( entry->tagName, tag, TAGSIZ);
entry->siz = (long)siz;
return 0;
}
}
/***********************************************************************
* Read Original TTF Table
*/
/* */ int
/* */ TTFReadOrgFixedTable (
/* */ HDC hDC, /* Handle to DC */
/* */ char *buf, /* Read Buffer */
/* */ int bufsiz, /* Buffer Siz */
/* */ char *tag) /* TagName */
/*
* returns : 0, -1
***********************************************************************/
{
DWORD dwTable; /* Metric Table to request */
DWORD siz;
dwTable = *(DWORD *)tag;
siz = GetFontData(hDC, dwTable, (DWORD)0, buf,(DWORD)bufsiz );
if ( (int)siz != bufsiz)
return -1;
else return 0;
}
/***********************************************************************
* Read Variable Size Table at onece with tag
*/
/* */ int
/* */ TTFReadOrgVarTable(
/* */ HDC hDC,
/* */ char **buf, /* Buffer pointer (be set) */
/* */ unsigned int *bufsiz, /* Buffer Size ( be set) */
/* */ char *tag) /* Tag name */
/*
* returns : 0, -1
* remarks : allocated memory must be free by caller
***********************************************************************/
{
struct TableEntry te;
char *mem;
if (TTFGetOrgTableEntry( hDC, &te, tag))
goto ERET;
if ((mem = (char *)malloc( (size_t)te.siz))==(char *)0)
goto ERET;
if ( TTFReadOrgFixedTable ( hDC, mem,(int)te.siz , tag))
goto ERET;
*buf = mem;
*bufsiz = (unsigned int)te.siz;
return 0;
ERET:
return -1;
}
static void
setCountryData(short EncodingID)
{
unsigned short lastCode;
makeUniCodeTbl();
lastCode = getMaxUniCode();
numOfGlyph = lastCode - EUDCCODEBASE +1 + 2; /* +null, +missing */
cmapdata[6] = (char)((EncodingID>>8)&(unsigned short)0xff);
cmapdata[7] = (char)(EncodingID&(unsigned short)0xff);
cmapdata[26] = (char)((lastCode>>8)&(unsigned short)0xff);
cmapdata[27] = (char)(lastCode&(unsigned short)0xff);
maxpdata[4] = (char)((numOfGlyph>>8)&(unsigned short)0xff);
maxpdata[5] = (char)(numOfGlyph&(unsigned short)0xff);
}
static int
WIFEOS2( HDC hDC, char **os2buf, int *os2TblSiz, struct BBX *bbx)
{
struct OS2Table *os2tbl;
int siz;
TEXTMETRIC tm;
static PANOSE msminPanose= { (char)2, (char)2, (char)6, (char)9, (char)4,
(char)2, (char)5, (char)8, (char)3, (char)4};
if ( GetTextMetrics( hDC, &tm)==0)
goto ERET;
siz = sizeof( struct OS2Table);
if ((os2tbl = (struct OS2Table *)malloc(sizeof(struct OS2Table)))==0)
goto ERET;
memset( os2tbl, 0, sizeof(struct OS2Table));
os2tbl->version = 1;
sitom( (short *)&os2tbl->version);
os2tbl->xAvgCharWidth = bbx->xMax+1;
sitom( &os2tbl->xAvgCharWidth );
os2tbl->usWeightClass = tm.tmWeight? (unsigned short)tm.tmWeight : 500;
sitom( (short *)&os2tbl->usWeightClass );
os2tbl->usWidthClass = 5; /* Medium */
sitom( (short *)&os2tbl->usWidthClass );
os2tbl->fsType = 0x0000; /* Allow all liscence */
sitom( &os2tbl->fsType );
os2tbl->ySubscriptXSize = (bbx->xMax+1)/2; /* 1/4kaku */
sitom( &os2tbl->ySubscriptXSize );
os2tbl->ySubscriptYSize = (bbx->yMax+1)/2; /* 1/4kaku */
sitom( &os2tbl->ySubscriptYSize );
os2tbl->ySubscriptXOffset = 0; /* 1/4kaku */
sitom( &os2tbl->ySubscriptXOffset );
os2tbl->ySubscriptYOffset = 0; /* 1/4kaku */
sitom( &os2tbl->ySubscriptYOffset );
os2tbl->ySuperscriptXSize = (bbx->xMax+1)/2; /* 1/4kaku */
sitom( &os2tbl->ySuperscriptXSize );
os2tbl->ySuperscriptYSize = (bbx->yMax+1)/2; /* 1/4kaku */
sitom( &os2tbl->ySuperscriptYSize );
os2tbl->ySuperscriptXOffset = (bbx->xMax+1)/2; /* 1/4kaku */
sitom( &os2tbl->ySuperscriptXOffset );
os2tbl->ySuperscriptYOffset = (bbx->yMax+1)/2; /* 1/4kaku */
sitom( &os2tbl->ySuperscriptYOffset );
os2tbl->yStrikeoutSize = bbx->yMax/20; /* 5% */
sitom( &os2tbl->yStrikeoutSize );
os2tbl->yStrikeoutPosition = bbx->yMax/4; /* 25% */
sitom( &os2tbl->yStrikeoutPosition );
os2tbl->sFamilyClass = 0; /* no classification */
sitom( &os2tbl->sFamilyClass );
os2tbl->panose = msminPanose;
os2tbl->fsSelection = 0x40;
sitom( (short *)&os2tbl->fsSelection );
os2tbl->usFirstCharIndex = 0x20;
sitom( (short *)&os2tbl->usFirstCharIndex );
os2tbl->usLastCharIndex = 0xffe5;
sitom( (short *)&os2tbl->usLastCharIndex );
os2tbl->sTypoAscender = bbx->yMax+1;
sitom( &os2tbl->sTypoAscender );
os2tbl->sTypoDescender = -(bbx->yMax/8);
sitom( &os2tbl->sTypoDescender );
os2tbl->sTypoLineGap = 0;
sitom( &os2tbl->sTypoLineGap );
os2tbl->usWinAscent = bbx->yMax+1;
sitom( (short *)&os2tbl->usWinAscent );
os2tbl->usWinDescent = bbx->yMax/8;
sitom( (short *)&os2tbl->usWinDescent );
*os2TblSiz = sizeof( struct OS2Table);
*os2buf = (char *)os2tbl;
return 0;
ERET:
return -1;
}
static void
WIFEhhea( struct HheaTable *hhea, struct BBX *bbx)
{
memset( hhea, 0, sizeof(struct HheaTable));
hhea->version[1] = (char)1;
hhea->Ascender = bbx->yMax+1;
sitom( &hhea->Ascender);
hhea->Descender = -(bbx->yMax/8);
sitom( &hhea->Descender);
hhea->LineGap = 0;
sitom( &hhea->LineGap);
hhea->advanceWidthMax = bbx->xMax+1;
sitom( &hhea->advanceWidthMax);
hhea->minLeftSideBearing = 0;
sitom( &hhea->minLeftSideBearing);
hhea->minRightSideBearing = 0;
sitom( &hhea->minRightSideBearing);
hhea->xMaxExtent = bbx->xMax+1;
sitom( &hhea->xMaxExtent);
hhea->caretSlopeRise = 1;
sitom( &hhea->caretSlopeRise);
hhea->caretSlopeRun = 0;
sitom( &hhea->caretSlopeRun);
hhea->numberOfHMetrics = (short)numOfGlyph;
sitom( &hhea->numberOfHMetrics);
}
static void
WIFEhead( struct HeadTable *head, struct BBX *bbx)
{
memset( head, 0, sizeof( struct HeadTable));
head->version[1] = 0x1;
head->magicNumber=0x5f0F3CF5L;
litom((long *)&head->magicNumber);
head->flags = 0;
sitom( &head->flags);
head->unitsPerEm = bbx->xMax - bbx->xMin+1;
head->unitsPerEm = ((bbx->xMax - bbx->xMin+1)*9+4)/8;
sitom( &head->unitsPerEm);
head->xMin = (short)bbx->xMin;
sitom( &head->xMin);
head->xMax = (short)bbx->xMax;
sitom( &head->xMax);
// head->yMin = (short)bbx->yMin;
head->yMin = -(bbx->yMax/8);
sitom( &head->yMin);
head->yMax = (short)bbx->yMax;
sitom( &head->yMax);
head->lowestRecPPEM = 25;
sitom( &head->lowestRecPPEM);
head->fontDirectionHint = 1;
sitom( &head->fontDirectionHint);
head->indexToLocFormat = 1;
sitom( &head->indexToLocFormat);
}
static void
WIFEpost( struct postTable *post)
{
memset( post, 0, sizeof( struct postTable));
post->FormatType[1]=0x3;
post->underlineThickness = 12;
sitom( &post->underlineThickness);
post->isFixedPitch = 1;
litom( (long *)&post->isFixedPitch);
}
static short
getEncID( HDC hDC, int fontType)
{
if ( CountryInfo.LangID==EUDC_KRW)
return (short)1;
else return (short)1;
}
/***********************************************************************
* Create TTF
*/
/* */ int
/* */ TTFCreate(
/* */ HDC hDC, /* Handle to DC */
/* */ TCHAR *newf, /* Create TTF Path */
/* */ struct BBX *bbx, /* the same as original 'head'*/
/* */ /* but minX should be 0 */
/* */ int lstHdl, /* missing glyf list */
/* */ /* bbx, hM, LstHdl is for Missing Glyf*/
/* */ int fontType) /* 0:TrueType, 1:WIFE */
/*
* returns : 0, -1
***********************************************************************/
{
HANDLE nfh;
struct TTFHeader hdr;
struct TableEntry *te, /* Directory Entry */
nte;
char *nameBuf;
int nameBufSiz;
struct HheaTable hhea;
struct VheaTable vhea;
struct HeadTable head;
struct HMetrics *hmet;
struct VMetrics *vmet;
long *loca;
long ofs;
char *glyphData;
int gdatsiz;
int i;
char *os2buf;
int os2siz;
struct BBX cbbx; /* bounding box for each glyph*/
struct HMetrics hM; /* horizontal metrics for each glyph */
struct VMetrics vM; /* Vertical one */
struct postTable postTbl; /* post table */
short EncodingID;
DWORD nByte;
BOOL res;
// nfh = -1;
te = 0;
nameBuf = 0;
hmet = 0;
loca = 0;
glyphData = 0;
os2buf = 0;
/* Determin PlatformSpcificEncodingID */
if ((EncodingID = getEncID( hDC, fontType))<(short)0)
goto ERET;
/* Set cmapdata,maxpdata,numOfGlyph,lastCode */
setCountryData(EncodingID);
/* Open files */
nfh = CreateFile(newf,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( nfh == INVALID_HANDLE_VALUE)
goto ERET;
/* Write header */
makeTTFHeader( &hdr, NUMTABLES);
if ( TTFWriteHdr( nfh, &hdr))
goto ERET;
/* Allocate dir entry area */
if ( (te =(struct TableEntry *)malloc((size_t)sizeof(struct TableEntry)*NUMTABLES))==0)
goto ERET;
/*
* DirEntry Dummy Write
*/
memset( te, 0, sizeof(struct TableEntry)*NUMTABLES);
res = WriteFile( nfh, te, sizeof(struct TableEntry)*NUMTABLES, &nByte, NULL);
if (!res || nByte != sizeof(struct TableEntry)*NUMTABLES)
goto ERET;
initDirEntry(te, NUMTABLES );
/*
* 'cvt ' Write
*/
if (TTFAppendTable( nfh, &nte, cvtdata, sizeof cvtdata))
goto ERET;
if ( setDirEntry( &nte, "cvt "))
goto ERET;
/*
* 'fpgm' Write
*/
if (TTFAppendTable( nfh, &nte, fpgmdata, sizeof fpgmdata))
goto ERET;
if ( setDirEntry( &nte, "fpgm"))
goto ERET;
/*
* 'prep' write
*/
if (TTFAppendTable( nfh, &nte, prepdata, sizeof prepdata))
goto ERET;
if ( setDirEntry( &nte, "prep"))
goto ERET;
/*
* 'name' write
*/
if ( (nameBuf = (char *)malloc((size_t)NAMEBUFSIZ))==0)
goto ERET;
setnamebuf(nameBuf, &nameBufSiz, EncodingID);
if (TTFAppendTable( nfh, &nte, nameBuf, nameBufSiz))
goto ERET;
free( nameBuf);
nameBuf = 0;
if ( setDirEntry( &nte, "name"))
goto ERET;
/*
* 'cmap' Write
*/
if (TTFAppendTable( nfh, &nte, cmapdata, sizeof cmapdata))
goto ERET;
if ( setDirEntry( &nte, "cmap"))
goto ERET;
/*
* 'OS/2' Copy -> modify
*/
if ( fontType==0) {
if ( TTFReadOrgVarTable( hDC, &os2buf, (unsigned int *)&os2siz,
"OS/2"))
goto ERET;
modifyOS2( os2buf);
}
else {
if (WIFEOS2( hDC, &os2buf, &os2siz, bbx))
goto ERET;
}
if (TTFAppendTable( nfh, &nte, os2buf, os2siz))
goto ERET;
if ( setDirEntry( &nte, "OS/2"))
goto ERET;
free( os2buf);
/*
* 'post' Copy
*/
if ( fontType==0) {
if ( TTFMergeTable( hDC, nfh, "post", &nte))
goto ERET;
}
else {
WIFEpost( &postTbl);
if (TTFAppendTable( nfh,&nte, (char *)&postTbl,sizeof(struct postTable)))
goto ERET;
}
if ( setDirEntry( &nte, "post"))
goto ERET;
/*
* 'hhea' Read,modify and write
*/
if ( fontType==0) {
if (TTFReadOrgFixedTable( hDC, (char *)&hhea, sizeof hhea,"hhea"))
goto ERET;
hhea.metricDataFormat = 0;
hhea.numberOfHMetrics = (short)numOfGlyph;
sitom( &hhea.numberOfHMetrics );
}
else {
WIFEhhea( &hhea, bbx);
}
if (TTFAppendTable( nfh, &nte, &hhea, sizeof hhea))
goto ERET;
if ( setDirEntry( &nte, "hhea"))
goto ERET;
/*
* 'vhea'
*/
setVhea( &vhea, &hhea, bbx);
if (TTFAppendTable( nfh, &nte, &vhea, sizeof vhea))
goto ERET;
if ( setDirEntry( &nte, "vhea"))
goto ERET;
/* Make metrics for missing Glyph */
cbbx = *bbx;
makeMetrics( lstHdl, &hM, &vM, &cbbx);
/*
* 'vmtx'
*/
if ((vmet=(struct VMetrics *)malloc( (size_t)sizeof(struct VMetrics)*numOfGlyph))==0)
goto ERET;
memset(vmet, 0, sizeof(struct VMetrics)*numOfGlyph);
/* for missing Glyph */
*vmet = vM;
sitom(&vmet->advanceHeight );
sitom(&vmet->topSideBearing );
/* for null Glyph */
(vmet+1)->advanceHeight = 0;
(vmet+1)->topSideBearing = 0;
if (TTFAppendTable( nfh,&nte,vmet,sizeof(struct VMetrics)*numOfGlyph))
goto ERET;
if ( setDirEntry( &nte, "vmtx"))
goto ERET;
free( vmet);
vmet = 0;
/*
* head Read,modify and write
*/
if ( fontType==0) {
if (TTFReadOrgFixedTable( hDC,(char *)&head, sizeof head,"head"))
goto ERET;
modifyhead( &head);
}
else {
WIFEhead( &head, bbx);
}
if (TTFAppendTable( nfh, &nte, &head, sizeof head))
goto ERET;
if ( setDirEntry( &nte, "head"))
goto ERET;
/*
* make hmtx
*/
if ((hmet=(struct HMetrics *)malloc( (size_t)sizeof(struct HMetrics)*numOfGlyph))==0)
goto ERET;
memset(hmet, 0, sizeof(struct HMetrics)*numOfGlyph);
/* for missing Glyph */
*hmet = hM;
sitom(&hmet->advanceWidth );
sitom(&hmet->leftSideBearing);
/* for null Glyph */
(hmet+1)->advanceWidth = 0;
(hmet+1)->leftSideBearing = 0;
if (TTFAppendTable( nfh,&nte,hmet,sizeof(struct HMetrics)*numOfGlyph))
goto ERET;
if ( setDirEntry( &nte, "hmtx"))
goto ERET;
free( hmet);
hmet = 0;
if ((glyphData = (char *)malloc((size_t)GLYPHBUFSIZ))==0)
goto ERET;
if (makeGlyphData( lstHdl, &cbbx, glyphData, GLYPHBUFSIZ, &gdatsiz ))
goto ERET;
/*
* 'loca' make
*/
if ((loca = (long *)malloc( (size_t)sizeof(unsigned long)*(numOfGlyph+1)))==(long *)0)
goto ERET;
*loca = 0;
ofs = gdatsiz;
litom(&ofs);
for ( i = 1; i< numOfGlyph+1; i++)
*(loca + i)=ofs;
if (TTFAppendTable( nfh,&nte,loca,sizeof( long)*(numOfGlyph+1)))
goto ERET;
if ( setDirEntry( &nte, "loca"))
goto ERET;
free( loca);
loca = 0;
/*
* 'maxp' write
*/
if (TTFAppendTable( nfh,&nte,maxpdata,sizeof(maxpdata)))
goto ERET;
if ( setDirEntry( &nte, "maxp"))
goto ERET;
/*
* 'glyf' Write (missing glyph )
*/
if (TTFAppendTable( nfh, &nte, glyphData, gdatsiz))
goto ERET;
if ( setDirEntry( &nte, "glyf"))
goto ERET;
free( glyphData);
glyphData = 0;
/* Sort dir entry table */
SortEntry( te, NUMTABLES);
/* Write dir entry */
if (TTFWriteDirEntry( nfh, te, NUMTABLES))
goto ERET;
/* Set Check sum of file whole to head */
if (fileChkSum( nfh, te, NUMTABLES, &hdr, &head))
goto ERET;
CloseHandle( nfh);
if ( te) free( te);
return 0;
ERET:
if ( nfh != INVALID_HANDLE_VALUE) CloseHandle( nfh);
if ( te) free( te);
if ( nameBuf) free( nameBuf);
if ( hmet) free( hmet);
if ( loca) free( loca);
if ( os2buf) free( os2buf);
if ( glyphData) free( glyphData);
return -1;
}
/***********************************************************************
* Obtain BoundingBox ( from 'head' xMin, xMax, yMin, yMax)
*/
/* */ int
/* */ TTFGetBBX(
/* */ HDC hDC,
/* */ struct BBX *bbx,
/* */ short *uPEm)
/*
* returns : 0, -1
***********************************************************************/
{
struct HeadTable head;
DWORD dwTable; /* tagName to request */
DWORD siz, s;
memcpy( &dwTable, "head", TAGSIZ);
siz = (DWORD)sizeof( struct HeadTable);
if ((s=GetFontData(hDC, dwTable, (DWORD)0, &head,(DWORD)siz))!=siz){
DWORD err = GetLastError();
return -1;
}
smtoi( &head.xMin);
smtoi( &head.xMax);
smtoi( &head.yMin);
smtoi( &head.yMax);
smtoi( &head.unitsPerEm);
bbx->xMin = head.xMin;
bbx->xMax = head.xMax;
bbx->yMin = head.yMin;
bbx->yMax = head.yMax;
*uPEm = head.unitsPerEm;
if ( bbx->xMin < 0 )
bbx->xMin = 0;
return 0;
}
int
TTFTmpPath( TCHAR *path, TCHAR *tmpPath)
{
TCHAR *p1;
TCHAR dirPath[MAX_PATH];
lstrcpy( dirPath, path);
p1 = Mytcsrchr( dirPath, '\\');
if ( p1==(TCHAR *)0) {
p1 = Mytcsrchr( dirPath, ':');
if (p1==(TCHAR *)0)
*dirPath=(TCHAR)0;
else
*(p1+1)=0;
}
else
*p1=0;
if (GetTempFileName( dirPath, TEXT("TTE"), 0, tmpPath)==0)
return -1;
else
return 0;
}
static int
copyTable( HANDLE iFh,HANDLE oFh, struct TableEntry *te, int nEntry, char *tag)
{
struct TableEntry *tep;
char *buf = NULL;
if ((tep = searchEntry(te, nEntry, tag))==(struct TableEntry *)0)
goto ERET;
if ((buf = (char *)malloc((size_t)tep->siz))==(char *)0)
goto ERET;
if ( (TTFReadTable( iFh,tep, buf, (int)tep->siz)!=(int)tep->siz) )
goto ERET;
if ( (TTFWriteTable( oFh,tep, buf, (int)tep->siz)!=(int)tep->siz) )
goto ERET;
free(buf);
return 0;
ERET:
if (buf) free(buf);
return -1;
}
static int
copyfblock( HANDLE iFh, HANDLE oFh, unsigned long siz, unsigned long *cs)
{
int rwsiz;
int filsiz;
int aligne;
unsigned long chksum;
char *buf;
if ((buf = (char *)malloc((size_t) RWBUFSIZ))==(char *)0)
goto ERET;
filsiz = (int)(siz % 4);
if ( filsiz) filsiz = 4-filsiz;
aligne =0;
chksum = 0;
while ( siz > 0) {
if ( siz > RWBUFSIZ)
rwsiz = RWBUFSIZ;
else {
rwsiz = (int)siz;
if ( filsiz)
aligne =1;
}
DWORD nByte;
BOOL res = ReadFile(iFh, buf,(unsigned int)rwsiz, &nByte, NULL );
if (!res || nByte != (unsigned int)rwsiz)
goto ERET;
if ( aligne ) {
memset( buf+siz, 0, filsiz);
rwsiz += filsiz;
}
chksum += calchksum( buf, rwsiz);
res = WriteFile ( oFh, buf, (unsigned int)rwsiz, &nByte, NULL);
if (!res || nByte !=(unsigned int)rwsiz)
goto ERET;
siz -= rwsiz;
}
*cs = chksum;
free(buf);
return 0;
ERET:
if(buf) free(buf);
return -1;
}
static int
mergeGlyph(
HANDLE iFh,
HANDLE oFh,
struct TableEntry *tep,
char *locabuf,
int glyphID,
char *glyphData,
int glyphSiz)
{
long *locp;
long nloc, cloc;
long iofs;
long tail;
long siz;
int gid;
long delta;
unsigned long cs;
int filsiz;
long lval;
locp = (long *)locabuf;
cs = 0;
/* copy leading */
cloc = *locp;
lmtoi( &cloc);
iofs = (unsigned long)tep->ofs+cloc;
if ((long) SetFilePointer( iFh, iofs, NULL, FILE_BEGIN) != iofs)
goto ERET;
if ((long) SetFilePointer( oFh, iofs, NULL, FILE_BEGIN) != iofs)
goto ERET;
cloc = *(locp + glyphID);
lmtoi( &cloc);
nloc = *(locp + glyphID+1);
lmtoi( &nloc);
siz = nloc - cloc;
if (copyfblock( iFh, oFh, cloc, &cs))
goto ERET;
/* write glyphData */
if ( glyphSiz>0L) {
filsiz = glyphSiz % 4;
if ( filsiz) {
filsiz = 4 - filsiz;
memset( glyphData+glyphSiz, 0, filsiz);
glyphSiz += filsiz;
}
DWORD nByte;
BOOL res = WriteFile( oFh, glyphData, (unsigned int)glyphSiz, &nByte, NULL);
if (!res || nByte !=(unsigned int)glyphSiz)
goto ERET;
cs += calchksum( glyphData, glyphSiz);
}
iofs = nloc + tep->ofs;
/* copy trailer */
if ((long) SetFilePointer( iFh, iofs, NULL, FILE_BEGIN) != iofs)
goto ERET;
tail = *(locp+numOfGlyph);
lmtoi(&tail);
siz = tail - nloc;
if (copyfblock( iFh, oFh, siz, &cs))
goto ERET;
/* update loca */
delta = glyphSiz - (nloc - cloc);
for ( gid = glyphID+1; gid<=numOfGlyph; gid++) {
lval = *(locp+gid);
lmtoi(&lval);
lval += delta;
litom(&lval);
*(locp+gid)=lval;
}
tep->siz = tail+delta;
return 0;
ERET:
return -1;
}
/***********************************************************************
* Add EUDC Font
*/
/* */ int
/* */ TTFAddEUDCChar(
/* */ TCHAR *path, /* EUDC FontFile path */
/* */ unsigned short code, /* Charcode */
/* */ struct BBX *bbx, /* Bounding Box */
/* */ int lstH) /* List Handle for glyph */
/*
* returns :0, -1
***********************************************************************/
{
struct TTFHeader hdr;
struct HeadTable head;
struct MaxpTbl maxp;
HANDLE fH;
HANDLE tmpFh = INVALID_HANDLE_VALUE;
struct TableEntry *te;
struct TableEntry *tep;
struct TableEntry *maxpTep;
struct TableEntry *locaTep;
int glyphID;
struct HMetrics hmet;
struct VMetrics vmet;
int nEntry;
char *updbuf;
char *glyphData;
int bufsiz;
int gdatsiz;
short sval;
struct BBX cbbx;
TCHAR tmpPath[MAX_PATH];
TCHAR savPath[MAX_PATH];
int sts;
HINSTANCE hInst = AfxGetInstanceHandle();
TCHAR szMessage[256];
lastErr = 0;
te = ( struct TableEntry *)0;
updbuf = (char *)0;
glyphData = (char *)0;
fH = CreateFile(path,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( fH == INVALID_HANDLE_VALUE)
goto ERET;
TTFTmpPath( path, tmpPath);
if ( tmpPath[0] == NULL )
goto ERET;
tmpFh = CreateFile(tmpPath,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( tmpFh == INVALID_HANDLE_VALUE)
goto ERET;
if ( TTFReadHdr( fH, &hdr))
goto ERET;
if ( TTFWriteHdr( tmpFh, &hdr))
goto ERET;
nEntry = hdr.numTables;
glyphID = codeToGID( code);
/* Read Table entries */
if ( (te = (struct TableEntry *)malloc((size_t)sizeof(struct TableEntry)*NUMTABLES))==0)
goto ERET;
if (TTFReadDirEntry( fH, te, nEntry))
goto ERET;
if (TTFWriteDirEntry( tmpFh, te, nEntry))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "cvt "))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "fpgm"))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "prep"))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "name"))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "cmap"))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "OS/2"))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "post"))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "hhea"))
goto ERET;
if (copyTable( fH, tmpFh, te, nEntry, "vhea"))
goto ERET;
/* Read maxp Table */
if ((maxpTep = searchEntry(te, nEntry, "maxp"))==0)
goto ERET;
if ( TTFReadTable( fH, maxpTep, &maxp, sizeof maxp)!=(sizeof maxp) )
goto ERET;
sval = maxp.numGlyph;
smtoi( &sval);
numOfGlyph = sval;
// Glyph is out of TTE file range, Win9x upgrade
if (glyphID >= numOfGlyph)
goto ERET;
bufsiz = sizeof(struct HMetrics)*(numOfGlyph);
bufsiz = align32( bufsiz);
if ( (updbuf = (char *)malloc( (size_t)bufsiz))==0)
goto ERET;
/* make metrics for the glyph */
cbbx = *bbx;
makeMetrics( lstH, &hmet, &vmet, &cbbx);
/* make glyph data */
if ((glyphData = (char *)malloc((size_t)GLYPHBUFSIZ))==0)
goto ERET;
if (sts=makeGlyphData(lstH, &cbbx, glyphData, GLYPHBUFSIZ, &gdatsiz)) {
lastErr = sts;
goto ERET;
}
/* set hmetrics */
sitom( &hmet.advanceWidth);
sitom( &hmet.leftSideBearing);
if ((tep = searchEntry(te, nEntry, "hmtx"))==0)
goto ERET;
if ( TTFReadTable( fH, tep, updbuf, bufsiz)<=0)
goto ERET;
*((struct HMetrics *)updbuf + glyphID) = hmet;
if ( TTFWriteTable( tmpFh, tep, updbuf, bufsiz)<=0)
goto ERET;
free( updbuf);
updbuf = 0;
/* Update 'vmtx' */
bufsiz = sizeof(struct VMetrics)*(numOfGlyph);
bufsiz = align32( bufsiz);
if ( (updbuf = (char *)malloc( (size_t)bufsiz))==0)
goto ERET;
/* set vmetrics */
sitom( &vmet.advanceHeight);
sitom( &vmet.topSideBearing);
if ((tep = searchEntry(te, nEntry, "vmtx"))==0)
goto ERET;
if ( TTFReadTable( fH, tep, updbuf, bufsiz)<=0)
goto ERET;
*((struct VMetrics *)updbuf + glyphID) = vmet;
if ( TTFWriteTable( tmpFh, tep, updbuf, bufsiz)<=0)
goto ERET;
free( updbuf);
updbuf = 0;
/* Read loca */
bufsiz = sizeof(long )*(numOfGlyph+1);
bufsiz = align32( bufsiz);
if ( (updbuf = (char *)malloc((size_t)bufsiz)) ==(char *)0)
goto ERET;
if ((locaTep = searchEntry(te, nEntry, "loca"))==0)
goto ERET;
if ( TTFReadTable( fH, locaTep, updbuf, bufsiz)<=0)
goto ERET;
/* move glyf data */
if ((tep = searchEntry(te, nEntry, "glyf"))==0)
goto ERET;
if (mergeGlyph( fH, tmpFh, tep, updbuf, glyphID, glyphData, gdatsiz ))
goto ERET;
/* read and cal checkSum of 'glyf' */
if (tableChkSum( tmpFh, tep))
goto ERET;
free( glyphData);
glyphData =(char *)0;
/* write loca */
if ( TTFWriteTable( tmpFh, locaTep, updbuf, bufsiz)<=0)
goto ERET;
/* update maxp */
if ( updateMaxp( &maxp, lstH) < 0)
goto ERET;
if (TTFWriteTable(tmpFh, maxpTep, &maxp, sizeof maxp)!=(sizeof maxp))
goto ERET;
/* update directory entry */
if (TTFWriteDirEntry( tmpFh, te, nEntry))
goto ERET;
/* Set Check sum of file whole to head */
if ((tep = searchEntry(te, nEntry, "head"))==0)
goto ERET;
if ( TTFReadTable( fH, tep, &head, sizeof head)<=0)
goto ERET;
tep->checkSum = 0L;
if ( TTFWriteTable( tmpFh, tep, &head, sizeof head)<=0)
goto ERET;
if (fileChkSum(tmpFh , te, nEntry, &hdr, &head))
goto ERET;
if ( TTFWriteTable( tmpFh, tep, &head, sizeof head)<=0)
goto ERET;
CloseHandle( fH);
CloseHandle( tmpFh);
// fH = tmpFh = -1;
TTFTmpPath( path, savPath);
if( DeleteFile( savPath)==0) {
TCHAR szTitle[256];
LoadString(hInst, IDS_MAINFRAMETITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
LoadString(hInst, IDS_NOMEM_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
MessageBox( AfxGetMainWnd()->GetSafeHwnd(), szMessage, szTitle, MB_OK);
goto ERET2;
}
if( MoveFile( path, savPath)==0) {
TCHAR szTitle[256];
LoadString(hInst, IDS_MAINFRAMETITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
LoadString(hInst, IDS_NOMEM_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
MessageBox( AfxGetMainWnd()->GetSafeHwnd(), szMessage, szTitle, MB_OK);
goto ERET2;
}
if( MoveFile( tmpPath, path)==0) {
TCHAR szTitle[256];
LoadString(hInst, IDS_MAINFRAMETITLE, szTitle, sizeof(szTitle) / sizeof(TCHAR));
LoadString(hInst, IDS_NOMEM_MSG, szMessage, sizeof(szMessage) / sizeof(TCHAR));
MessageBox( AfxGetMainWnd()->GetSafeHwnd(), szMessage, szTitle, MB_OK);
goto ERET2;
}
if ( DeleteFile( savPath) ==0) {
DeleteFile(path);
MoveFile(savPath, path);
if ( te) free(te);
if ( updbuf) free(updbuf);
if ( glyphData) free(glyphData);
return -3; //tte file is being used by another process
}
free( te);
free( updbuf);
return 0;
ERET:
if ( fH != INVALID_HANDLE_VALUE) CloseHandle(fH);
if ( tmpFh != INVALID_HANDLE_VALUE) CloseHandle(tmpFh);
if ( te) free(te);
if ( updbuf) free(updbuf);
if ( glyphData) free(glyphData);
return -1;
ERET2:
if ( fH != INVALID_HANDLE_VALUE) CloseHandle(fH);
if ( tmpFh != INVALID_HANDLE_VALUE) CloseHandle(tmpFh);
if ( te) free(te);
if ( updbuf) free(updbuf);
if ( glyphData) free(glyphData);
if ( tmpPath) DeleteFile( tmpPath);
return -1;
}
/***********************************************************************
* For Import
*/
static HANDLE eudcFh;
static char *locaBuf = 0;
static char *maxpBuf = 0;
static char *hmtxBuf = 0;
static char *vmtxBuf = 0;
static char *glyphBuf = 0;
static void
frebuf()
{
if ( locaBuf) {
free( locaBuf);
locaBuf = 0;
}
if ( maxpBuf) {
free( maxpBuf);
maxpBuf = 0;
}
if ( vmtxBuf) {
free( vmtxBuf);
vmtxBuf = 0;
}
if ( hmtxBuf) {
free( hmtxBuf);
hmtxBuf = 0;
}
if ( glyphBuf) {
free( glyphBuf);
glyphBuf = 0;
}
if ( et) {
free( et);
glyphBuf = 0;
}
return;
}
int
TTFOpen( TCHAR *path)
{
struct TTFHeader hdr;
unsigned int bufsiz;
unsigned short sval;
et = 0;
eudcFh = CreateFile(path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( eudcFh == INVALID_HANDLE_VALUE)
goto ERET;
if (TTFReadHdr(eudcFh,&hdr))
goto ERET;
if ((et = (struct TableEntry *)malloc( sizeof (struct TableEntry)*hdr.numTables))
==0)
goto ERET;
entryNum = hdr.numTables;
if (TTFReadDirEntry(eudcFh, et, hdr.numTables))
goto ERET;
if (TTFReadVarTable( eudcFh, &maxpBuf, &bufsiz, "maxp"))
goto ERET;
sval = ((struct MaxpTbl *)maxpBuf) ->numGlyph;
smtoi( (short *)&sval);
numOfGlyph = sval;
if (TTFReadVarTable( eudcFh, &locaBuf, &bufsiz, "loca"))
goto ERET;
if (TTFReadVarTable( eudcFh, &hmtxBuf, &bufsiz, "hmtx"))
goto ERET;
if (TTFReadVarTable( eudcFh, &vmtxBuf, &bufsiz, "vmtx"))
goto ERET;
if ((glyphBuf = (char *)malloc( GLYPHBUFSIZ))==0)
goto ERET;
return 0;
ERET:
if ( eudcFh != INVALID_HANDLE_VALUE) {
CloseHandle( eudcFh);
eudcFh = INVALID_HANDLE_VALUE;
}
frebuf();
return -1;
}
int
TTFClose()
{
struct TableEntry *tep;
struct HeadTable head;
struct TTFHeader hdr;
long ofs;
if ( eudcFh == INVALID_HANDLE_VALUE)
return -1;
if (TTFReadHdr( eudcFh, &hdr))
goto ERET;
/* obtain glyph table size */
ofs = SetFilePointer( eudcFh, 0L, NULL, FILE_END);
/* Update Glyph checkSum */
if ((tep = searchEntry(et, entryNum, "glyf"))==0)
goto ERET;
tep->siz = ofs - tep->ofs;
/* read and cal checkSum of 'glyf' */
if (tableChkSum( eudcFh, tep))
goto ERET;
if ((tep = searchEntry(et, entryNum, "maxp"))==0)
goto ERET;
if (TTFWriteTable( eudcFh, tep, maxpBuf, (int)tep->siz)!=(int)tep->siz)
goto ERET;
if ((tep = searchEntry(et, entryNum, "loca"))==0)
goto ERET;
if (TTFWriteTable( eudcFh, tep, locaBuf, (int)tep->siz)!=(int)tep->siz)
goto ERET;
if ((tep = searchEntry(et, entryNum, "hmtx"))==0)
goto ERET;
if (TTFWriteTable( eudcFh, tep, hmtxBuf, (int)tep->siz)!=(int)tep->siz)
goto ERET;
if ((tep = searchEntry(et, entryNum, "vmtx"))==0)
goto ERET;
if (TTFWriteTable( eudcFh, tep, vmtxBuf, (int)tep->siz)!=(int)tep->siz)
goto ERET;
if ((tep = searchEntry(et, entryNum, "head"))==0)
goto ERET;
if ( TTFReadTable(eudcFh, tep, &head, sizeof(head))!=sizeof(head))
goto ERET;
if ( fileChkSum(eudcFh, et, entryNum, &hdr, &head))
goto ERET;
if ( TTFWriteDirEntry( eudcFh, et, entryNum))
goto ERET;
CloseHandle( eudcFh);
frebuf();
return 0;
ERET:
CloseHandle( eudcFh);
frebuf();
return -1;
}
int
TTFGetEUDCBBX(TCHAR *path, struct BBX *bbx, short *upem)
{
struct HeadTable head;
HANDLE fH;
fH = CreateFile(path,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( fH == INVALID_HANDLE_VALUE)
goto ERET;
if ( TTFReadFixedTable(fH, (char *)&head,sizeof head,"head"))
goto ERET;
smtoi( &head.xMin);
smtoi( &head.xMax);
smtoi( &head.yMin);
smtoi( &head.yMax);
smtoi( &head.unitsPerEm);
bbx->xMin = head.xMin;
bbx->xMax = head.xMax;
bbx->yMin = head.yMin;
bbx->yMax = head.yMax;
*upem = head.unitsPerEm;
if ( bbx->xMin < 0 )
bbx->xMin = 0;
CloseHandle( fH);
return 0;
ERET:
if (fH!=INVALID_HANDLE_VALUE)
CloseHandle( fH);
return -1;
}
static void
makeMetrics(int lsthdl, struct HMetrics *hM, struct VMetrics *vM, struct BBX *bbx)
{
struct VHEAD *vhd;
struct VDATA *vp;
int np;
int sts;
int xmin, ymin, xmax, ymax;
if ( (sts = VDGetHead( lsthdl, &vhd))!=0)
goto RET;
if ( (sts = VDGetNCont( lsthdl))<=0)
goto SPACE_CHAR;
xmin = xmax = vhd->headp->vd.x;
ymin = ymax = vhd->headp->vd.y;
while ( vhd->next != NIL) {
vp = vhd->headp;
np = vhd->nPoints;
while ( np-->0) {
if (vp->vd.x > xmax)
xmax = vp->vd.x;
else if(vp->vd.x < xmin)
xmin = vp->vd.x;
if (vp->vd.y > ymax)
ymax = vp->vd.y;
else if(vp->vd.y < ymin)
ymin = vp->vd.y;
vp = vp->next;
}
vhd = vhd->next;
}
// if ( xmin < 0)
// xmin = 0;
hM->leftSideBearing = (short)xmin;
hM->advanceWidth = bbx->xMax - bbx->xMin;
{
int hmw = hM->advanceWidth + 1;
int ii = 0;
while (hmw >> 1)
{
hmw >>= 1;
ii++;
}
hmw = 1;
while (ii--) hmw *= 2;
int gap1 = hM->advanceWidth - hmw;
int gap2 = hmw*2 - hM->advanceWidth;
hmw = gap1 > gap2 ? hmw * 2 : hmw;
hM->advanceWidth = (short)hmw;
}
vM->topSideBearing = bbx->yMax - ymax;
if (vM->topSideBearing < 0)
vM->topSideBearing = 0;
vM->advanceHeight = bbx->yMax - bbx->yMin;
bbx->xMin = xmin;
bbx->yMin = ymin;
bbx->xMax = xmax;
bbx->yMax = ymax;
return;
RET:
SPACE_CHAR:
hM->leftSideBearing = (short)bbx->xMax;
hM->advanceWidth = bbx->xMax - bbx->xMin;
vM->topSideBearing = bbx->yMax - bbx->yMin;
vM->advanceHeight = bbx->yMax - bbx->yMin;
bbx->xMin = bbx->xMax;
bbx->yMax = bbx->yMin;
return;
}
int
TTFAppend( unsigned short code, struct BBX *bbx, int lsthdl)
{
int glyphID;
struct HMetrics hmet;
struct VMetrics vmet;
int updflg;
int gdatsiz;
struct BBX cbbx;
int sts;
glyphID = codeToGID( code);
lastErr = 0;
/* make metrics */
cbbx = *bbx;
makeMetrics( lsthdl, &hmet, &vmet, &cbbx);
/* make glyph data */
if (sts =makeGlyphData(lsthdl, &cbbx, glyphBuf, GLYPHBUFSIZ, &gdatsiz)) {
lastErr = sts;
goto ERET;
}
/* set hmetrics */
sitom( &hmet.advanceWidth);
sitom( &hmet.leftSideBearing);
*((struct HMetrics *)hmtxBuf + glyphID) = hmet;
/* Update 'vmtx' */
sitom( &vmet.advanceHeight);
sitom( &vmet.topSideBearing);
*((struct VMetrics *)vmtxBuf + glyphID) = vmet;
/* write glyf data */
if (TTFImpGlyphWrite( glyphID, glyphBuf, gdatsiz))
goto ERET;
/* update maxp */
if ((updflg = updateMaxp( (struct MaxpTbl *)maxpBuf, lsthdl)) < 0)
goto ERET;
return 0;
ERET:
return -1;
}
/*
* Copy
*/
int
TTFImpCopy( TCHAR *sPath, TCHAR *dPath)
{
HANDLE sFh, dFh;
struct TTFHeader hdr;
struct TableEntry *te;
int tblSiz;
int ntbl;
int tcnt;
char *buf;
int bufsiz;
sFh = dFh = 0;
te = 0;
buf = 0;
/* Open src */
sFh = CreateFile(sPath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (sFh == INVALID_HANDLE_VALUE)
goto ERET;
/* create open destination*/
dFh = CreateFile(dPath,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (dFh == INVALID_HANDLE_VALUE)
goto ERET;
/* read header */
if ( TTFReadHdr( sFh, &hdr))
goto ERET;
ntbl = (int)hdr.numTables;
/* write header */
if ( TTFWriteHdr( dFh, &hdr))
goto ERET;
/* read directory entry */
tblSiz = sizeof( struct TableEntry)*ntbl;
if ((te = (struct TableEntry *)malloc(tblSiz))==(struct TableEntry *)0)
goto ERET;
if ( TTFReadDirEntry(sFh, te, ntbl))
goto ERET;
/* write directory entry */
if ( TTFWriteDirEntry(dFh, te, ntbl))
goto ERET;
/* copy each table (except glyph)*/
for ( tcnt = 0; tcnt < ntbl; tcnt++) {
if ( memcmp((te+tcnt)->tagName,"glyf", 4)) {
bufsiz = (int)(te+tcnt)->siz;
buf = (char *)malloc((int)(te+tcnt)->siz);
if (TTFReadTable( sFh, te+tcnt, buf, bufsiz)!=bufsiz)
goto ERET;
if (TTFWriteTable( dFh, te+tcnt, buf, bufsiz)!=bufsiz)
goto ERET;
free( buf);
buf = 0;
}
}
/* close */
CloseHandle( sFh);
CloseHandle( dFh);
free( te);
return 0;
ERET:
if (sFh != INVALID_HANDLE_VALUE) CloseHandle(sFh);
if (dFh != INVALID_HANDLE_VALUE) CloseHandle(dFh);
if (te)
free( te);
if ( buf) free( buf);
return -1;
}
int
TTFImpGlyphCopy(
HANDLE sFh,
int glyphID)
{
struct TableEntry *tep;
long *locap;
long cloc, nloc;
long siz;
long ofs;
long wofs;
char *buf;
DWORD nByte;
buf = 0;
if ((tep = searchEntry( et, entryNum, "glyf"))==0)
goto ERET;
locap = (long *)locaBuf;
cloc = *(locap+glyphID);
lmtoi( &cloc);
nloc = *(locap+glyphID+1);
lmtoi( &nloc);
siz = nloc - cloc;
ofs = tep->ofs + cloc;
if ( (long) SetFilePointer( sFh, ofs, NULL, FILE_BEGIN) != ofs)
goto ERET;
wofs = SetFilePointer( eudcFh, 0L, NULL, FILE_END);
wofs -= tep->ofs;
litom( &wofs);
*(locap+glyphID) = wofs;
if ( siz) {
if ( (buf = (char *)malloc((int)siz))==(char *)0)
goto ERET;
BOOL res = ReadFile( sFh, buf, (unsigned int)siz, &nByte, NULL);
if (!res || nByte !=(unsigned int)siz)
goto ERET;
res = WriteFile( eudcFh, buf,(unsigned int)siz, &nByte, NULL);
if (!res || nByte !=(unsigned int)siz)
goto ERET;
}
free( buf);
return 0;
ERET:
if ( buf) free( buf);
return -1;
}
int
TTFImpGlyphWrite(
int glyphID, char *glyph, int siz)
{
struct TableEntry *tep;
long ofs;
long wofs;
long *locap;
DWORD nByte;
if ( glyphID >= numOfGlyph)
return -1;
if ((tep = searchEntry( et, entryNum, "glyf"))==0)
goto ERET;
wofs = SetFilePointer( eudcFh, 0L, NULL, FILE_END);
ofs = wofs - tep->ofs;
litom( &ofs);
locap = (long *)locaBuf;
*(locap+glyphID) = ofs;
if ( siz) {
BOOL res = WriteFile(eudcFh, glyph, (unsigned int)siz, &nByte, NULL);
if (!res || nByte !=(unsigned int)siz)
goto ERET;
}
return 0;
ERET:
return -1;
}
int
TTFImpTerm(HANDLE orgFh, int glyphID)
{
struct TableEntry *tep;
long ofs;
long wofs;
long *locap;
int gid;
//
// copy the rest of the glyph data over.
//
for ( gid = glyphID; gid < numOfGlyph; gid++)
{
if (TTFImpGlyphCopy(orgFh, gid))
return -1;
}
if ((tep = searchEntry( et, entryNum, "glyf"))==0)
return -1;
locap = (long *)locaBuf;
wofs = SetFilePointer( eudcFh, 0L,NULL, FILE_END);
ofs = wofs - tep->ofs;
litom( &ofs);
*(locap + numOfGlyph) = ofs;
tep->siz = wofs - tep->ofs;
return 0;
}
int
TTFLastError()
{
return lastErr;
}
/* EOF */