Commit d896f09f authored by Oleg.Korshul's avatar Oleg.Korshul Committed by Alexander Trofimov

полная реализация FontConverter

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@63607 954022d7-b5bf-4e40-9824-e11837661b57
parent 284e46d4
......@@ -6,8 +6,8 @@
class CFontConverter
{
public:
int ToOTF(std::wstring sFontIn, std::wstring sFontOut, unsigned int* pSymbols, int nCount, std::wstring sName, long nFlag);
int ToOTF2(std::wstring sFontIn, unsigned int* pSymbols, int nCount, std::wstring sName, long nFlag, long lFaceIndex, unsigned char*& pDstData, int& nDstLen);
bool ToOTF(std::wstring sFontIn, std::wstring sFontOut, unsigned int* pSymbols, int nCount, std::wstring sName, long nFlag);
bool ToOTF2(std::wstring sFontIn, unsigned int* pSymbols, int nCount, std::wstring sName, long nFlag, long lFaceIndex, unsigned char*& pDstData, int& nDstLen);
};
#endif /* _BUILD_FONT_CONVERTER_H */
// FontConverter.cpp : Implementation of CFontConverter
#include "FontConverter.h"
#include "../FontConverter.h"
#include "Consts.h"
#include "Utils.h"
#include FT_XFREE86_H
#include FT_TRUETYPE_TABLES_H
#include "FontFileTrueType.h"
#include "FontFileType1C.h"
#include "FontFileType1.h"
bool CFontConverter::ToOTF(std::wstring sFontIn, std::wstring sFontOut, unsigned int* pSymbols, int nCount, std::wstring sNameW, long nFlag)
{
FT_Library pLibrary = NULL;
if ( FT_Init_FreeType( &pLibrary ) )
return false;
FT_Face pFace = NULL;
NSFile::CFileBinary oFileBinary;
if (!oFileBinary.OpenFile(sFontIn))
return false;
FT_Long nFileSize = (FT_Long)oFileBinary.GetFileSize();
BYTE* pBaseAddress = new BYTE[nFileSize];
DWORD dwRead = 0;
oFileBinary.ReadFile(pBaseAddress, (DWORD)nFileSize, dwRead);
FT_Open_Args oOpenArgs;
oOpenArgs.flags = FT_OPEN_MEMORY;
oOpenArgs.memory_base = (BYTE*)pBaseAddress;
oOpenArgs.memory_size = nFileSize;
NSFontConverter::CFontFileTrueType* pTTF = NSFontConverter::CFontFileTrueType::LoadFromFile( sFontIn.c_str() );
FT_Error oerrr;
if ( oerrr = FT_Open_Face( pLibrary, &oOpenArgs, 0, &pFace ) )
{
FT_Done_FreeType( pLibrary );
RELEASEARRAYOBJECTS(pBaseAddress);
return false;
}
std::string sFontFormat( FT_Get_X11_Font_Format( pFace ) );
// Проверим флаг конвертации и исходный формат шрифта
bool bNeedConvert = false;
if ( nFlag == NSFontConverter::c_lFromAll ||
( "TrueType" == sFontFormat && nFlag & NSFontConverter::c_lFromTT ) ||
( "CFF" == sFontFormat && nFlag & NSFontConverter::c_lFromCFF ) ||
( "Type 1" == sFontFormat && nFlag & NSFontConverter::c_lFromT1 ) )
bNeedConvert = true;
bool bIsGids = (NSFontConverter::c_lFlagsGids & nFlag);
if ( bNeedConvert )
{
if ( "CFF" == sFontFormat || "Type 1" == sFontFormat )
{
NSFontConverter::TCharBuffer oCFF;
NSFontConverter::CFontFileType1C *pT1C = NULL;
if ( "Type 1" == sFontFormat )
{
// Сначала сконвертируем Type1 в CFF
NSFontConverter::CFontFileType1* pT1 = NSFontConverter::CFontFileType1::LoadFromFile( sFontIn.c_str() );
pT1->ToCFF( &NSFontConverter::CharBufferWrite, &oCFF );
delete pT1;
// Конвертируем CFF в OpenTypeCFF
pT1C = NSFontConverter::CFontFileType1C::LoadFromBuffer( oCFF.sBuffer, oCFF.nLen );
}
else
{
// FreeType отдает тип шрифта CFF, в случаях когда файл имеет тип OpenType(CFF).
// Если так оно и есть, тогда нам с файлом ничего делать на надо.
pT1C = NSFontConverter::CFontFileType1C::LoadFromFile( sFontIn.c_str() );
}
if ( pT1C )
{
NSFile::CFileBinary oWriteFile;
oWriteFile.CreateFileW(sFontOut);
pT1C->ToOpenTypeCFF( &NSFontConverter::FileWrite, oWriteFile.GetFileNative(), pFace );
oWriteFile.CloseFile();
}
delete pT1C;
}
else if ( "TrueType" == sFontFormat && ( pSymbols != NULL || !sNameW.empty() ) )
{
NSFontConverter::CFontFileTrueType* pTTF = NSFontConverter::CFontFileTrueType::LoadFromFile( sFontIn.c_str() );
if ( pTTF )
{
std::string sName = U_TO_UTF8(sNameW);
unsigned char *pUseGlyfs = NULL;
long lGlyfsCount = pFace->num_glyphs;
if ( pSymbols )
{
// Сначала составим список нужных нами GID
unsigned int* pUnicode = pSymbols;
unsigned short* pGIDs = new unsigned short[nCount];
int nCMapIndex = 0;
int nSymbolicIndex = NSFontConverter::GetSymbolicCmapIndex(pFace);
if (!bIsGids)
{
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
pGIDs[nIndex] = NSFontConverter::SetCMapForCharCode( pFace, pUnicode[nIndex], &nCMapIndex );
if ((pGIDs[nIndex] == 0) && (-1 != nSymbolicIndex) && (pUnicode[nIndex] < 0xF000))
{
pGIDs[nIndex] = NSFontConverter::SetCMapForCharCode( pFace, pUnicode[nIndex] + 0xF000, &nCMapIndex );
}
}
}
else
{
for (int i = 0; i < nCount; ++i)
pGIDs[i] = (unsigned short)pUnicode[i];
}
pUseGlyfs = new unsigned char[lGlyfsCount];
::memset( pUseGlyfs, 0x00, lGlyfsCount * sizeof(unsigned char) );
pUseGlyfs[0] = 1; // нулевой гид всегда записываем
for ( int nGID = 1; nGID < lGlyfsCount; nGID++ )
{
if ( 1 != pUseGlyfs[nGID] )
{
bool bFound = false;
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
if ( nGID == pGIDs[nIndex] )
{
bFound = true;
break;
}
}
// Если данный символ составной (CompositeGlyf), тогда мы должны учесть все его дочерные символы (subglyfs)
if ( bFound && 0 == FT_Load_Glyph( pFace, nGID, FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE ) )
{
for ( int nSubIndex = 0; nSubIndex < pFace->glyph->num_subglyphs; nSubIndex++ )
{
FT_Int nSubGID;
FT_UInt unFlags;
FT_Int nArg1;
FT_Int nArg2;
FT_Matrix oMatrix;
FT_Get_SubGlyph_Info( pFace->glyph, nSubIndex, &nSubGID, &unFlags, &nArg1, &nArg2, &oMatrix );
if ( nSubGID < lGlyfsCount )
pUseGlyfs[nSubGID] = 1;
}
}
if ( bFound )
pUseGlyfs[nGID] = 1;
}
}
}
NSFile::CFileBinary oWriteFile;
oWriteFile.CreateFileW(sFontOut);
pTTF->WriteTTF( &NSFontConverter::FileWrite, oWriteFile.GetFileNative(), sName.c_str(), NULL, pUseGlyfs, lGlyfsCount );
oWriteFile.CloseFile();
}
else
{
// error parse font
// Просто копируем файл
NSFile::CFileBinary::Copy(sFontIn, sFontOut);
}
}
}
else
{
// Просто копируем файл
NSFile::CFileBinary::Copy(sFontIn, sFontOut);
}
FT_Done_Face( pFace );
FT_Done_FreeType( pLibrary );
RELEASEARRAYOBJECTS(pBaseAddress);
return true;
}
bool CFontConverter::ToOTF2(std::wstring sFontIn, unsigned int* pSymbols, int nCount, std::wstring sNameW, long nFlag, long lFaceIndex, unsigned char*& pDstData, int& nDstLen)
{
// функция просто скопирована и немного доработана. это все из-за нехватки времени.
FT_Library pLibrary = NULL;
if ( FT_Init_FreeType( &pLibrary ) )
return false;
FT_Face pFace = NULL;
NSFile::CFileBinary oFileBinary;
if (!oFileBinary.OpenFile(sFontIn))
return false;
FT_Long nFileSize = (FT_Long)oFileBinary.GetFileSize();
BYTE* pBaseAddress = new BYTE[nFileSize];
DWORD dwRead = 0;
oFileBinary.ReadFile(pBaseAddress, (DWORD)nFileSize, dwRead);
FT_Open_Args oOpenArgs;
oOpenArgs.flags = FT_OPEN_MEMORY;
oOpenArgs.memory_base = (BYTE*)pBaseAddress;
oOpenArgs.memory_size = (FT_Long)nFileSize;
NSFontConverter::CFontFileTrueType* pTTF = NSFontConverter::CFontFileTrueType::LoadFromFile( sFontIn.c_str() );
FT_Error oerrr;
if ( oerrr = FT_Open_Face( pLibrary, &oOpenArgs, lFaceIndex, &pFace ) )
{
FT_Done_FreeType( pLibrary );
RELEASEARRAYOBJECTS(pBaseAddress);
return false;
}
std::string sFontFormat( FT_Get_X11_Font_Format( pFace ) );
// Проверим флаг конвертации и исходный формат шрифта
bool bNeedConvert = false;
if ( nFlag == NSFontConverter::c_lFromAll ||
( "TrueType" == sFontFormat && nFlag & NSFontConverter::c_lFromTT ) ||
( "CFF" == sFontFormat && nFlag & NSFontConverter::c_lFromCFF ) ||
( "Type 1" == sFontFormat && nFlag & NSFontConverter::c_lFromT1 ) )
bNeedConvert = true;
bool bIsGids = (NSFontConverter::c_lFlagsGids & nFlag);
NSFontConverter::TCharBuffer* pCharBuffer = NULL;
if ( bNeedConvert )
{
pCharBuffer = new NSFontConverter::TCharBuffer(100000); // ~100Kb
if ( "CFF" == sFontFormat || "Type 1" == sFontFormat )
{
NSFontConverter::TCharBuffer oCFF;
NSFontConverter::CFontFileType1C *pT1C = NULL;
if ( "Type 1" == sFontFormat )
{
// Сначала сконвертируем Type1 в CFF
NSFontConverter::CFontFileType1* pT1 = NSFontConverter::CFontFileType1::LoadFromFile( sFontIn.c_str() );
pT1->ToCFF( &NSFontConverter::CharBufferWrite, &oCFF );
delete pT1;
// Конвертируем CFF в OpenTypeCFF
pT1C = NSFontConverter::CFontFileType1C::LoadFromBuffer( oCFF.sBuffer, oCFF.nLen );
}
else
{
// FreeType отдает тип шрифта CFF, в случаях когда файл имеет тип OpenType(CFF).
// Если так оно и есть, тогда нам с файлом ничего делать на надо.
pT1C = NSFontConverter::CFontFileType1C::LoadFromFile( sFontIn.c_str() );
}
if ( pT1C )
{
pT1C->ToOpenTypeCFF( &NSFontConverter::CharBufferWrite, pCharBuffer, pFace );
}
delete pT1C;
}
else if ( "TrueType" == sFontFormat && ( pSymbols != NULL || !sNameW.empty() ) )
{
NSFontConverter::CFontFileTrueType* pTTF = NSFontConverter::CFontFileTrueType::LoadFromFile( sFontIn.c_str() );
if ( pTTF )
{
std::string sName = U_TO_UTF8(sNameW);
unsigned char *pUseGlyfs = NULL;
long lGlyfsCount = pFace->num_glyphs;
if ( pSymbols )
{
// Сначала составим список нужных нами GID
unsigned int* pUnicode = (unsigned int*)pSymbols;
unsigned short* pGIDs = new unsigned short[nCount];
int nCMapIndex = 0;
int nSymbolicIndex = NSFontConverter::GetSymbolicCmapIndex(pFace);
if (!bIsGids)
{
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
pGIDs[nIndex] = NSFontConverter::SetCMapForCharCode( pFace, pUnicode[nIndex], &nCMapIndex );
if ((pGIDs[nIndex] == 0) && (-1 != nSymbolicIndex) && (pUnicode[nIndex] < 0xF000))
{
pGIDs[nIndex] = NSFontConverter::SetCMapForCharCode( pFace, pUnicode[nIndex] + 0xF000, &nCMapIndex );
}
}
}
else
{
for (int i = 0; i < nCount; ++i)
pGIDs[i] = (unsigned short)pUnicode[i];
}
pUseGlyfs = new unsigned char[lGlyfsCount];
::memset( pUseGlyfs, 0x00, lGlyfsCount * sizeof(unsigned char) );
pUseGlyfs[0] = 1; // нулевой гид всегда записываем
for ( int nGID = 1; nGID < lGlyfsCount; nGID++ )
{
if ( 1 != pUseGlyfs[nGID] )
{
bool bFound = false;
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
if ( nGID == pGIDs[nIndex] )
{
bFound = true;
break;
}
}
// Если данный символ составной (CompositeGlyf), тогда мы должны учесть все его дочерные символы (subglyfs)
if ( bFound && 0 == FT_Load_Glyph( pFace, nGID, FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE ) )
{
for ( int nSubIndex = 0; nSubIndex < pFace->glyph->num_subglyphs; nSubIndex++ )
{
FT_Int nSubGID;
FT_UInt unFlags;
FT_Int nArg1;
FT_Int nArg2;
FT_Matrix oMatrix;
FT_Get_SubGlyph_Info( pFace->glyph, nSubIndex, &nSubGID, &unFlags, &nArg1, &nArg2, &oMatrix );
if ( nSubGID < lGlyfsCount )
pUseGlyfs[nSubGID] = 1;
}
}
if ( bFound )
pUseGlyfs[nGID] = 1;
}
}
}
pTTF->WriteTTF( &NSFontConverter::CharBufferWrite, pCharBuffer, sName.c_str(), NULL, pUseGlyfs, lGlyfsCount );
}
}
LONG nSizeFont = pCharBuffer->nLen;
nDstLen = (int)nSizeFont;
pDstData = new BYTE[nDstLen];
memcpy(pDstData, pCharBuffer->sBuffer, nDstLen);
RELEASEOBJECT(pCharBuffer);
}
else
{
nDstLen = (int)nFileSize;
pDstData = new BYTE[nDstLen];
memcpy(pDstData, pBaseAddress, nDstLen);
}
FT_Done_Face( pFace );
FT_Done_FreeType( pLibrary );
RELEASEARRAYOBJECTS(pBaseAddress);
return true;
}
// CFontConverter12
......@@ -9,7 +9,7 @@ namespace NSFontConverter
{
//------------------------------------------------------------------------
typedef void (*FontFileOutputFunc)(void *pStream, char *sData, int nLen);
typedef void (*FontFileOutputFunc)(void *pStream, const char *sData, int nLen);
//------------------------------------------------------------------------
// CFontFileBase
......@@ -39,7 +39,7 @@ namespace NSFontConverter
{
m_nPos = 0;
}
static char *ReadFile(wchar_t *wsFileName, int *pnFileLen)
static char *ReadFile(const wchar_t *wsFileName, int *pnFileLen)
{
NSFile::CFileBinary oFile;
if ( !oFile.OpenFile(wsFileName) )
......
#include "FontFileEncodings.h"
#include "../../common/File.h"
namespace NSFontConverter
{
......@@ -5741,6 +5742,7 @@ namespace NSFontConverter
int Type1NameToUnicodeA(const char *sName)
{
return Type1NameToUnicodeW( A2W( sName ) );
std::wstring sUnicode = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)sName, (LONG)strlen(sName));
return Type1NameToUnicodeW( sUnicode.c_str() );
}
}
#ifndef _ASC_FONTCONVERTER_FONNT_FILE_ENCODINGS_H
#define _ASC_FONTCONVERTER_FONNT_FILE_ENCODINGS_H
#include "../../common/Types.h"
#include <string>
namespace NSFontConverter
{
class CWCharWrapper
......
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef _FONT_FILE_TRUETYPE_H
#define _FONT_FILE_TRUETYPE_H
#ifndef _ASC_FONTCONVERTER_FONT_FILE_TRUETYPE_H
#define _ASC_FONTCONVERTER_FONT_FILE_TRUETYPE_H
#include "FontFileBase.h"
class StringExt;
class CHash;
//------------------------------------------------------------------------
#define ttcfTag 0x74746366
//------------------------------------------------------------------------
struct TrueTypeTable
{
unsigned int unTag;
unsigned int unChecksum;
int nOffset;
int nOrigOffset;
int nLen;
};
struct TrueTypeCmap
{
int nPlatform;
int nEncoding;
int nOffset;
int nLen;
int nFormat;
};
struct TrueTypeLoca
namespace NSFontConverter
{
int nIndex;
int nOrigOffset;
int nNewOffset;
int nLen;
};
#define cffTag 0x43464620
#define maxpTag 0x6d617870
#define cmapTag 0x636d6170
#define glyfTag 0x676c7966
#define headTag 0x68656164
#define hheaTag 0x68686561
#define hmtxTag 0x686d7478
#define locaTag 0x6c6f6361
#define nameTag 0x6e616d65
#define os2Tag 0x4f532f32
#define postTag 0x706f7374
#define cvtTag 0x63767420
#define fpgmTag 0x6670676d
#define prepTag 0x70726570
static int CompareTrueTypeLocaOffset(const void *pL1, const void *pL2)
{
TrueTypeLoca *pLoca1 = (TrueTypeLoca *)pL1;
TrueTypeLoca *pLoca2 = (TrueTypeLoca *)pL2;
if ( pLoca1->nOrigOffset == pLoca2->nOrigOffset )
return pLoca1->nIndex - pLoca2->nIndex;
return pLoca1->nOrigOffset - pLoca2->nOrigOffset;
class StringExt;
class CHash;
//------------------------------------------------------------------------
#define ttcfTag 0x74746366
//------------------------------------------------------------------------
struct TrueTypeTable
{
unsigned int unTag;
unsigned int unChecksum;
int nOffset;
int nOrigOffset;
int nLen;
};
struct TrueTypeCmap
{
int nPlatform;
int nEncoding;
int nOffset;
int nLen;
int nFormat;
};
struct TrueTypeLoca
{
int nIndex;
int nOrigOffset;
int nNewOffset;
int nLen;
};
#define cffTag 0x43464620
#define maxpTag 0x6d617870
#define cmapTag 0x636d6170
#define glyfTag 0x676c7966
#define headTag 0x68656164
#define hheaTag 0x68686561
#define hmtxTag 0x686d7478
#define locaTag 0x6c6f6361
#define nameTag 0x6e616d65
#define os2Tag 0x4f532f32
#define postTag 0x706f7374
#define cvtTag 0x63767420
#define fpgmTag 0x6670676d
#define prepTag 0x70726570
static int CompareTrueTypeLocaOffset(const void *pL1, const void *pL2)
{
TrueTypeLoca *pLoca1 = (TrueTypeLoca *)pL1;
TrueTypeLoca *pLoca2 = (TrueTypeLoca *)pL2;
if ( pLoca1->nOrigOffset == pLoca2->nOrigOffset )
return pLoca1->nIndex - pLoca2->nIndex;
return pLoca1->nOrigOffset - pLoca2->nOrigOffset;
}
static int CompareTrueTypeLocaIndex(const void *pL1, const void *pL2)
{
TrueTypeLoca *pLoca1 = (TrueTypeLoca *)pL1;
TrueTypeLoca *pLoca2 = (TrueTypeLoca *)pL2;
return pLoca1->nIndex - pLoca2->nIndex;
}
static int CompareTrueTypeTableTag(const void *pTab1, const void *pTab2)
{
TrueTypeTable *pTable1 = (TrueTypeTable *)pTab1;
TrueTypeTable *pTable2 = (TrueTypeTable *)pTab2;
return (int)pTable1->unTag - (int)pTable2->unTag;
}
//------------------------------------------------------------------------
struct T42Table
{
char *sTag; // 4-байтовое название
bool bRequired; // Требуется ли по спецификации TrueType?
};
// TrueType tables to be embedded in Type 42 fonts.
// NB: the table names must be in alphabetical order here.
#define nT42Tables 11
static T42Table t42Tables[nT42Tables] =
{
{ "cvt ", true },
{ "fpgm", true },
{ "glyf", true },
{ "head", true },
{ "hhea", true },
{ "hmtx", true },
{ "loca", true },
{ "maxp", true },
{ "prep", true },
{ "vhea", false },
{ "vmtx", false }
};
#define t42HeadTable 3
#define t42LocaTable 6
#define t42GlyfTable 2
#define t42VheaTable 9
#define t42VmtxTable 10
//------------------------------------------------------------------------
// CFontFileTrueType
//------------------------------------------------------------------------
class CFontFileTrueType: public CFontFileBase
{
public:
// Создаем объект TTF из буфера.
static CFontFileTrueType *LoadFromBuffer(char *sBuffer, int lenA);
// Создаем объект TTF из файла.
static CFontFileTrueType *LoadFromFile(const wchar_t *wsFileName);
virtual ~CFontFileTrueType();
// TRUE, если данный OpenType фонт содержите данные формата CFF.
// FALSE,если это TrueType фонт ( или OpenType фонт с данными в формате TrueType).
bool IsOpenTypeCFF()
{
return m_bOpenTypeCFF;
}
int GetCmapsCount();
int GetCmapPlatform(int nIndex);
int GetCmapEncoding(int nIndex);
int FindCmap(int nPlatform, int nEncoding);
// Возвращает GID, соответствующий символу <nChar> в <nIndex>ной CMap.
unsigned short MapCodeToGID(int nCMapIndex, int nChar);
// Возвращает GID, соответствующий <sName> в таблице post. Возвращает 0,
// если символа с таким именем не нашли, или таблицы post нет.
int MapNameToGID(char *sName);
// Возвращает карту CIDs в GIDs, и возваращет количество элементов
// CIDs в *<pnCIDs>. Только для CID фонтов( OpenType CFF )
unsigned short *GetCIDToGIDMap(int *pnCIDs);
// Лицензионные ограничения на включение фонта( в соответствие со
// спецификацией True Type):
// * 4: таблицы OS/2 не найдена или некорректна
// * 3: разрешено устанавливать
// * 2: разрешено редактировать
// * 1: разрешено просматривать и печатать
// * 0: ограничено лицензией
int GetEmbeddingRestrictions();
// Convert to a Type 42 font, suitable for embedding in a PostScript
// file. <psName> will be used as the PostScript font name (so we
// don't need to depend on the 'name' table in the font). The
// <encoding> array specifies the mapping from char codes to names.
// If <encoding> is NULL, the encoding is unknown or undefined. The
// <codeToGID> array specifies the mapping from char codes to GIDs.
// (Not useful for OpenType CFF fonts.)
void ToType42(char *sPSName, char **ppEncoding, unsigned short *pCodeToGID, FontFileOutputFunc pOutputFunc, void *pOutputStream );
// Convert to a Type 1 font, suitable for embedding in a PostScript
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
// otherwise it will be left as binary data. If <psName> is
// non-NULL, it will be used as the PostScript font name. (Only
// useful for OpenType CFF fonts.)
void ToType1(char *sPSName, char **ppNewEncoding, bool bASKII, FontFileOutputFunc pOutputFunc, void *pOutputStream );
// Convert to a Type 2 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name (so we don't need to depend on the 'name' table in the
// font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
// entries. (Not useful for OpenType CFF fonts.)
void ToCIDType2(char *sPSName, unsigned short *pCIDMap, int nCIDCount, bool bNeedVerticalMetrics, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name. (Only useful for OpenType CFF fonts.)
void ToCIDType0(char *sPSName, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name (so we don't need to depend on the 'name'
// table in the font). The <cidMap> array maps CIDs to GIDs; it has
// <nCIDs> entries. (Not useful for OpenType CFF fonts.)
void ToType0(char *sPSName, unsigned short *pCIDMap, int nCIDCount, bool bNeedVerticalMetrics, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name. (Only useful for OpenType CFF fonts.)
void ToType0(char *sPSName, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Записываем TrueTypeFont File, заполняя недостающие таблицы и корректируя
// различные ошибки. Если задан парметр <sName>, в шрифте переписываем таблицу
// 'name'. Если задан парамтре <pCodeToGID>, тогда в шрифте переписываем
// таблицу 'cmap'.
void WriteTTF(FontFileOutputFunc pOutputFunc, void *pOutputStream, const char *sName = NULL, unsigned short *pCodeToGID = NULL, unsigned char *pUseGlyfs = NULL, long lGlyfsCount = 0) ;
private:
CFontFileTrueType(char *sFileName, int nLen, bool bFreeFileData);
void ConvertEncoding (char **ppEncoding, FontFileOutputFunc pOutputFunc, void *pOutputStream);
void ConvertCharStrings(char **ppEncoding, unsigned short *pnCodeToGID, FontFileOutputFunc pOutputFunc, void *pOutputStream);
void ConvertSfnts (FontFileOutputFunc pOutputFunc, void *pOutputStream, StringExt *seName, bool bNeedVerticalMetrics);
void DumpString(unsigned char *sString, int nLength, FontFileOutputFunc pOutputFunc, void *pOutputStream);
unsigned int ComputeTableChecksum(unsigned char *sData, int nLength);
void Parse();
void ReadPostTable();
int SeekTable(char *sTag);
private:
TrueTypeTable *m_pTables;
int m_nTablesCount;
TrueTypeCmap *m_pCMaps;
int m_nCMapsCount;
int m_nGlyphs;
int m_nLocaFormat;
int m_arrBBox[4];
CHash *m_pNameToGID;
bool m_bOpenTypeCFF;
bool m_bSuccess;
};
}
static int CompareTrueTypeLocaIndex(const void *pL1, const void *pL2)
{
TrueTypeLoca *pLoca1 = (TrueTypeLoca *)pL1;
TrueTypeLoca *pLoca2 = (TrueTypeLoca *)pL2;
return pLoca1->nIndex - pLoca2->nIndex;
}
static int CompareTrueTypeTableTag(const void *pTab1, const void *pTab2)
{
TrueTypeTable *pTable1 = (TrueTypeTable *)pTab1;
TrueTypeTable *pTable2 = (TrueTypeTable *)pTab2;
return (int)pTable1->unTag - (int)pTable2->unTag;
}
//------------------------------------------------------------------------
struct T42Table
{
char *sTag; // 4-байтовое название
BOOL bRequired; // Требуется ли по спецификации TrueType?
};
// TrueType tables to be embedded in Type 42 fonts.
// NB: the table names must be in alphabetical order here.
#define nT42Tables 11
static T42Table t42Tables[nT42Tables] =
{
{ "cvt ", TRUE },
{ "fpgm", TRUE },
{ "glyf", TRUE },
{ "head", TRUE },
{ "hhea", TRUE },
{ "hmtx", TRUE },
{ "loca", TRUE },
{ "maxp", TRUE },
{ "prep", TRUE },
{ "vhea", FALSE },
{ "vmtx", FALSE }
};
#define t42HeadTable 3
#define t42LocaTable 6
#define t42GlyfTable 2
#define t42VheaTable 9
#define t42VmtxTable 10
//------------------------------------------------------------------------
// CFontFileTrueType
//------------------------------------------------------------------------
class CFontFileTrueType: public CFontFileBase
{
public:
// Создаем объект TTF из буфера.
static CFontFileTrueType *LoadFromBuffer(char *sBuffer, int lenA);
// Создаем объект TTF из файла.
static CFontFileTrueType *LoadFromFile(wchar_t *wsFileName);
virtual ~CFontFileTrueType();
// TRUE, если данный OpenType фонт содержите данные формата CFF.
// FALSE,если это TrueType фонт ( или OpenType фонт с данными в формате TrueType).
BOOL IsOpenTypeCFF()
{
return m_bOpenTypeCFF;
}
int GetCmapsCount();
int GetCmapPlatform(int nIndex);
int GetCmapEncoding(int nIndex);
int FindCmap(int nPlatform, int nEncoding);
// Возвращает GID, соответствующий символу <nChar> в <nIndex>ной CMap.
unsigned short MapCodeToGID(int nCMapIndex, int nChar);
// Возвращает GID, соответствующий <sName> в таблице post. Возвращает 0,
// если символа с таким именем не нашли, или таблицы post нет.
int MapNameToGID(char *sName);
// Возвращает карту CIDs в GIDs, и возваращет количество элементов
// CIDs в *<pnCIDs>. Только для CID фонтов( OpenType CFF )
unsigned short *GetCIDToGIDMap(int *pnCIDs);
// Лицензионные ограничения на включение фонта( в соответствие со
// спецификацией True Type):
// * 4: таблицы OS/2 не найдена или некорректна
// * 3: разрешено устанавливать
// * 2: разрешено редактировать
// * 1: разрешено просматривать и печатать
// * 0: ограничено лицензией
int GetEmbeddingRestrictions();
// Convert to a Type 42 font, suitable for embedding in a PostScript
// file. <psName> will be used as the PostScript font name (so we
// don't need to depend on the 'name' table in the font). The
// <encoding> array specifies the mapping from char codes to names.
// If <encoding> is NULL, the encoding is unknown or undefined. The
// <codeToGID> array specifies the mapping from char codes to GIDs.
// (Not useful for OpenType CFF fonts.)
void ToType42(char *sPSName, char **ppEncoding, unsigned short *pCodeToGID, FontFileOutputFunc pOutputFunc, void *pOutputStream );
// Convert to a Type 1 font, suitable for embedding in a PostScript
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
// otherwise it will be left as binary data. If <psName> is
// non-NULL, it will be used as the PostScript font name. (Only
// useful for OpenType CFF fonts.)
void ToType1(char *sPSName, char **ppNewEncoding, BOOL bASKII, FontFileOutputFunc pOutputFunc, void *pOutputStream );
// Convert to a Type 2 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name (so we don't need to depend on the 'name' table in the
// font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
// entries. (Not useful for OpenType CFF fonts.)
void ToCIDType2(char *sPSName, unsigned short *pCIDMap, int nCIDCount, BOOL bNeedVerticalMetrics, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name. (Only useful for OpenType CFF fonts.)
void ToCIDType0(char *sPSName, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name (so we don't need to depend on the 'name'
// table in the font). The <cidMap> array maps CIDs to GIDs; it has
// <nCIDs> entries. (Not useful for OpenType CFF fonts.)
void ToType0(char *sPSName, unsigned short *pCIDMap, int nCIDCount, BOOL bNeedVerticalMetrics, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name. (Only useful for OpenType CFF fonts.)
void ToType0(char *sPSName, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Записываем TrueTypeFont File, заполняя недостающие таблицы и корректируя
// различные ошибки. Если задан парметр <sName>, в шрифте переписываем таблицу
// 'name'. Если задан парамтре <pCodeToGID>, тогда в шрифте переписываем
// таблицу 'cmap'.
void WriteTTF(FontFileOutputFunc pOutputFunc, void *pOutputStream, char *sName = NULL, unsigned short *pCodeToGID = NULL, unsigned char *pUseGlyfs = NULL, long lGlyfsCount = 0) ;
private:
CFontFileTrueType(char *sFileName, int nLen, BOOL bFreeFileData);
void ConvertEncoding (char **ppEncoding, FontFileOutputFunc pOutputFunc, void *pOutputStream);
void ConvertCharStrings(char **ppEncoding, unsigned short *pnCodeToGID, FontFileOutputFunc pOutputFunc, void *pOutputStream);
void ConvertSfnts (FontFileOutputFunc pOutputFunc, void *pOutputStream, StringExt *seName, BOOL bNeedVerticalMetrics);
void DumpString(unsigned char *sString, int nLength, FontFileOutputFunc pOutputFunc, void *pOutputStream);
unsigned int ComputeTableChecksum(unsigned char *sData, int nLength);
void Parse();
void ReadPostTable();
int SeekTable(char *sTag);
private:
TrueTypeTable *m_pTables;
int m_nTablesCount;
TrueTypeCmap *m_pCMaps;
int m_nCMapsCount;
int m_nGlyphs;
int m_nLocaFormat;
int m_arrBBox[4];
CHash *m_pNameToGID;
BOOL m_bOpenTypeCFF;
BOOL m_bSuccess;
};
#endif /* _FONT_FILE_TRUETYPE_H */
#endif /* _ASC_FONTCONVERTER_FONT_FILE_TRUETYPE_H */
#include "stdafx.h"
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include "MemoryUtils.h"
#include "FontFileEncodings.h"
#include "FontFileType1.h"
#define LINESIZE 1024
#define PFB_MARKER 128
#define PFB_ASCII 1
#define PFB_BINARY 2
#define PFB_DONE 3
#define IS_PS_NEWLINE( ch ) \
( (ch) == '\r' || \
(ch) == '\n' )
#define IS_PS_SPACE( ch ) \
( (ch) == ' ' || \
IS_PS_NEWLINE( ch ) || \
(ch) == '\t' || \
(ch) == '\f' || \
(ch) == '\0' )
// Таблица для быстрого конвертирования цифр (десятичных и не десятичных) в числа
static const signed char c_arrCharTable[128] =
{
/* 0x00 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
};
// Ни один символ больше >= 0x80 не может представлять число
#define OP >=
#define WriteChar(Value) \
nChar = (char)(Value);\
pOutputFunc( pOutputStream, &nChar, 1 );
unsigned int EexecDecode (unsigned char** cursor, unsigned char* limit, unsigned char* buffer, unsigned int n, unsigned short* seed )
{
unsigned char* p;
unsigned int r;
unsigned int s = *seed;
p = *cursor;
if ( n > (unsigned int)(limit - p) )
n = (unsigned int)(limit - p);
for ( r = 0; r < n; r++ )
{
unsigned int val = p[r];
unsigned int b = ( val ^ ( s >> 8 ) );
s = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
buffer[r] = (unsigned char) b;
}
*cursor = p + n;
*seed = (unsigned short)s;
return r;
}
unsigned int ASCIIHexDecode(unsigned char** cursor, unsigned char* limit, unsigned char* buffer, unsigned int n)
{
unsigned char* p;
unsigned int r = 0;
unsigned int w = 0;
unsigned int pad = 0x01;
n *= 2;
p = *cursor;
if ( n > (unsigned int)( limit - p ) )
n = (unsigned int)( limit - p );
/* we try to process two nibbles at a time to be as fast as possible */
for ( ; r < n; r++ )
{
FT_UInt c = p[r];
if ( IS_PS_SPACE( c ) )
continue;
if ( c OP 0x80 )
break;
c = c_arrCharTable[c & 0x7F];
if ( (unsigned)c >= 16 )
break;
pad = ( pad << 4 ) | c;
if ( pad & 0x100 )
{
buffer[w++] = (FT_Byte)pad;
pad = 0x01;
}
}
if ( pad != 0x01 )
buffer[w++] = (FT_Byte)( pad << 4 );
*cursor = p + r;
return w;
}
//------------------------------------------------------------------------
// CFontFileType1
//------------------------------------------------------------------------
CFontFileType1 *CFontFileType1::LoadFromBuffer(char *sBuffer, int nLen)
namespace NSFontConverter
{
return new CFontFileType1(sBuffer, nLen, FALSE);
}
#define LINESIZE 1024
#define PFB_MARKER 128
#define PFB_ASCII 1
#define PFB_BINARY 2
#define PFB_DONE 3
CFontFileType1 *CFontFileType1::LoadFromFile(wchar_t *wsFileName)
{
char *sBuffer;
int nLen = 0;
if ( !( sBuffer = CFontFileBase::ReadFile(wsFileName, &nLen) ) )
return NULL;
return new CFontFileType1(sBuffer, nLen, TRUE);
}
#define IS_PS_NEWLINE( ch ) \
( (ch) == '\r' || \
(ch) == '\n' )
#define IS_PS_SPACE( ch ) \
( (ch) == ' ' || \
IS_PS_NEWLINE( ch ) || \
(ch) == '\t' || \
(ch) == '\f' || \
(ch) == '\0' )
// Таблица для быстрого конвертирования цифр (десятичных и не десятичных) в числа
static const signed char c_arrCharTable[128] =
{
/* 0x00 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
};
// Ни один символ больше >= 0x80 не может представлять число
#define OP >=
#define WriteChar(Value) \
nChar = (char)(Value);\
pOutputFunc( pOutputStream, &nChar, 1 );
unsigned int EexecDecode (unsigned char** cursor, unsigned char* limit, unsigned char* buffer, unsigned int n, unsigned short* seed )
{
unsigned char* p;
unsigned int r;
unsigned int s = *seed;
p = *cursor;
if ( n > (unsigned int)(limit - p) )
n = (unsigned int)(limit - p);
for ( r = 0; r < n; r++ )
{
unsigned int val = p[r];
unsigned int b = ( val ^ ( s >> 8 ) );
s = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
buffer[r] = (unsigned char) b;
}
*cursor = p + n;
*seed = (unsigned short)s;
return r;
}
unsigned int ASCIIHexDecode(unsigned char** cursor, unsigned char* limit, unsigned char* buffer, unsigned int n)
{
unsigned char* p;
unsigned int r = 0;
unsigned int w = 0;
unsigned int pad = 0x01;
n *= 2;
p = *cursor;
if ( n > (unsigned int)( limit - p ) )
n = (unsigned int)( limit - p );
/* we try to process two nibbles at a time to be as fast as possible */
for ( ; r < n; r++ )
{
FT_UInt c = p[r];
if ( IS_PS_SPACE( c ) )
continue;
if ( c OP 0x80 )
break;
c = c_arrCharTable[c & 0x7F];
if ( (unsigned)c >= 16 )
break;
pad = ( pad << 4 ) | c;
if ( pad & 0x100 )
{
buffer[w++] = (FT_Byte)pad;
pad = 0x01;
}
}
if ( pad != 0x01 )
buffer[w++] = (FT_Byte)( pad << 4 );
*cursor = p + r;
return w;
}
//------------------------------------------------------------------------
// CFontFileType1
//------------------------------------------------------------------------
CFontFileType1 *CFontFileType1::LoadFromBuffer(char *sBuffer, int nLen)
{
return new CFontFileType1(sBuffer, nLen, false);
}
CFontFileType1 *CFontFileType1::LoadFromFile(const wchar_t *wsFileName)
{
char *sBuffer;
int nLen = 0;
CFontFileType1::CFontFileType1(char *sBuffer, int nLen, BOOL bFreeData):
CFontFileBase(sBuffer, nLen, bFreeData)
{
m_sName = NULL;
m_arrEncoding = NULL;
Parse();
m_bParsed = FALSE;
}
if ( !( sBuffer = CFontFileBase::ReadFile(wsFileName, &nLen) ) )
return NULL;
CFontFileType1::~CFontFileType1()
{
if (m_sName)
MemUtilsFree(m_sName);
if ( m_arrEncoding && m_arrEncoding != c_arrsFontFileType1StandardEncoding )
{
for (int nIndex = 0; nIndex < 256; ++nIndex )
{
MemUtilsFree( m_arrEncoding[nIndex] );
}
MemUtilsFree(m_arrEncoding);
}
}
return new CFontFileType1(sBuffer, nLen, true);
}
char *CFontFileType1::GetName()
{
if ( !m_bParsed )
Parse();
return m_sName;
}
CFontFileType1::CFontFileType1(char *sBuffer, int nLen, bool bFreeData):
CFontFileBase(sBuffer, nLen, bFreeData)
{
m_sName = NULL;
m_arrEncoding = NULL;
char **CFontFileType1::GetEncoding()
{
if (!m_bParsed)
Parse();
Parse();
m_bParsed = false;
}
return m_arrEncoding;
}
CFontFileType1::~CFontFileType1()
{
if (m_sName)
MemUtilsFree(m_sName);
if ( m_arrEncoding && m_arrEncoding != c_arrsFontFileType1StandardEncoding )
{
for (int nIndex = 0; nIndex < 256; ++nIndex )
{
MemUtilsFree( m_arrEncoding[nIndex] );
}
MemUtilsFree(m_arrEncoding);
}
}
void CFontFileType1::WriteEncoded(char **ppNewEncoding, FontFileOutputFunc pOutputFunc, void *pOutputStream)
{
char sBuffer[512];
char *sLine, *sLine2, *sCurChar;
// копируем все до строчки /Encoding
for ( sLine = (char *)m_sFile; sLine && strncmp( sLine, "/Encoding", 9); sLine = GetNextLine(sLine) );
if ( !sLine )
{
// не нашли кодировку, тогда копируем целиком фонт файл
(*pOutputFunc)( pOutputStream, (char *)m_sFile, m_nLen);
return;
}
(*pOutputFunc)( pOutputStream, (char *)m_sFile, sLine - (char *)m_sFile);
// пишем новую кодировку
(*pOutputFunc)( pOutputStream, "/Encoding 256 array\n", 20);
(*pOutputFunc)( pOutputStream, "0 1 255 {1 index exch /.notdef put} for\n", 40);
for ( int nIndex = 0; nIndex < 256; ++nIndex )
{
if (ppNewEncoding[nIndex])
{
sprintf( sBuffer, "dup %d /%s put\n", nIndex, ppNewEncoding[nIndex]);
(*pOutputFunc)( pOutputStream, sBuffer, strlen( sBuffer ));
}
}
(*pOutputFunc)( pOutputStream, "readonly def\n", 13);
if ( !strncmp( sLine, "/Encoding StandardEncoding def", 30) )
{
sLine = GetNextLine(sLine);
}
else
{
sCurChar = sLine + 10;
sLine = NULL;
for (; sCurChar < (char *)m_sFile + m_nLen; ++sCurChar)
{
if ((*sCurChar == ' ' || *sCurChar == '\t' || *sCurChar == '\x0a' || *sCurChar == '\x0d' || *sCurChar == '\x0c' || *sCurChar == '\0') && sCurChar + 4 <= (char *)m_sFile + m_nLen && !strncmp(sCurChar + 1, "def", 3) )
{
sLine = sCurChar + 4;
break;
}
}
}
// У некоторых фонтов две записи /Encoding, поэтому проверяем наличие второй записи
if ( sLine )
{
int nIndex;
for ( sLine2 = sLine, nIndex = 0; nIndex < 20 && sLine2 && strncmp(sLine2, "/Encoding", 9); sLine2 = GetNextLine(sLine2), ++nIndex) ;
if ( nIndex < 20 && sLine2 )
{
(*pOutputFunc)( pOutputStream, sLine, sLine2 - sLine);
if ( !strncmp(sLine2, "/Encoding StandardEncoding def", 30) )
{
sLine = GetNextLine( sLine2 );
}
else
{
sCurChar = sLine2 + 10;
sLine = NULL;
for (; sCurChar < (char *)m_sFile + m_nLen; ++sCurChar)
{
if ((*sCurChar == ' ' || *sCurChar == '\t' || *sCurChar == '\x0a' || *sCurChar == '\x0d' || *sCurChar == '\x0c' || *sCurChar == '\0') && sCurChar + 4 <= (char *)m_sFile + m_nLen && !strncmp(sCurChar + 1, "def", 3) )
{
sLine = sCurChar + 4;
break;
}
}
}
}
// копируем все после кодировки
if ( sLine )
{
(*pOutputFunc)( pOutputStream, sLine, ((char *)m_sFile + m_nLen) - sLine );
}
}
}
char *CFontFileType1::GetName()
{
if ( !m_bParsed )
Parse();
char *CFontFileType1::GetNextLine(char *sLine)
{
while ( sLine < (char *)m_sFile + m_nLen && *sLine != '\x0a' && *sLine != '\x0d')
++sLine;
return m_sName;
}
if ( sLine < (char *)m_sFile + m_nLen && *sLine == '\x0d')
++sLine;
char **CFontFileType1::GetEncoding()
{
if (!m_bParsed)
Parse();
if ( sLine < (char *)m_sFile + m_nLen && *sLine == '\x0a')
++sLine;
return m_arrEncoding;
}
if ( sLine >= (char *)m_sFile + m_nLen )
return NULL;
void CFontFileType1::WriteEncoded(char **ppNewEncoding, FontFileOutputFunc pOutputFunc, void *pOutputStream)
{
char sBuffer[512];
char *sLine, *sLine2, *sCurChar;
// копируем все до строчки /Encoding
for ( sLine = (char *)m_sFile; sLine && strncmp( sLine, "/Encoding", 9); sLine = GetNextLine(sLine) );
if ( !sLine )
{
// не нашли кодировку, тогда копируем целиком фонт файл
(*pOutputFunc)( pOutputStream, (char *)m_sFile, m_nLen);
return;
}
(*pOutputFunc)( pOutputStream, (char *)m_sFile, sLine - (char *)m_sFile);
// пишем новую кодировку
(*pOutputFunc)( pOutputStream, "/Encoding 256 array\n", 20);
(*pOutputFunc)( pOutputStream, "0 1 255 {1 index exch /.notdef put} for\n", 40);
for ( int nIndex = 0; nIndex < 256; ++nIndex )
{
if (ppNewEncoding[nIndex])
{
sprintf( sBuffer, "dup %d /%s put\n", nIndex, ppNewEncoding[nIndex]);
(*pOutputFunc)( pOutputStream, sBuffer, strlen( sBuffer ));
}
}
(*pOutputFunc)( pOutputStream, "readonly def\n", 13);
if ( !strncmp( sLine, "/Encoding StandardEncoding def", 30) )
{
sLine = GetNextLine(sLine);
}
else
{
sCurChar = sLine + 10;
sLine = NULL;
for (; sCurChar < (char *)m_sFile + m_nLen; ++sCurChar)
{
if ((*sCurChar == ' ' || *sCurChar == '\t' || *sCurChar == '\x0a' || *sCurChar == '\x0d' || *sCurChar == '\x0c' || *sCurChar == '\0') && sCurChar + 4 <= (char *)m_sFile + m_nLen && !strncmp(sCurChar + 1, "def", 3) )
{
sLine = sCurChar + 4;
break;
}
}
}
// У некоторых фонтов две записи /Encoding, поэтому проверяем наличие второй записи
if ( sLine )
{
int nIndex;
for ( sLine2 = sLine, nIndex = 0; nIndex < 20 && sLine2 && strncmp(sLine2, "/Encoding", 9); sLine2 = GetNextLine(sLine2), ++nIndex) ;
if ( nIndex < 20 && sLine2 )
{
(*pOutputFunc)( pOutputStream, sLine, sLine2 - sLine);
if ( !strncmp(sLine2, "/Encoding StandardEncoding def", 30) )
{
sLine = GetNextLine( sLine2 );
}
else
{
sCurChar = sLine2 + 10;
sLine = NULL;
for (; sCurChar < (char *)m_sFile + m_nLen; ++sCurChar)
{
if ((*sCurChar == ' ' || *sCurChar == '\t' || *sCurChar == '\x0a' || *sCurChar == '\x0d' || *sCurChar == '\x0c' || *sCurChar == '\0') && sCurChar + 4 <= (char *)m_sFile + m_nLen && !strncmp(sCurChar + 1, "def", 3) )
{
sLine = sCurChar + 4;
break;
}
}
}
}
// копируем все после кодировки
if ( sLine )
{
(*pOutputFunc)( pOutputStream, sLine, ((char *)m_sFile + m_nLen) - sLine );
}
}
}
return sLine;
}
char *CFontFileType1::GetNextLine(char *sLine)
{
while ( sLine < (char *)m_sFile + m_nLen && *sLine != '\x0a' && *sLine != '\x0d')
++sLine;
void CFontFileType1::Parse()
{
// Сначала проверим, если это pfb файл, тогда избавимся от всех его маркеров.
Reset();
while( m_nPos < m_nLen && ( ' ' == m_sFile[m_nPos] || '\t' == m_sFile[m_nPos] || '\r' == m_sFile[m_nPos] || '\n' == m_sFile[m_nPos] ) )
++m_nPos;
BOOL bSuccess = TRUE;
int nChar = GetU8( m_nPos, &bSuccess );
if ( !bSuccess || ( PFB_MARKER != nChar && '%' != nChar ) )
return;
else if ( PFB_MARKER == nChar )
{
if ( !RemovePfbMarkers() )
return;
}
char *sLine, *sLine1, *pCur, *pTemp;
char sBuffer[256];
int nCount, nCode;
int nIndex = 0;
unsigned char *sEexec = NULL;
m_oTopDict.arrdFontBBox[0] = 0; m_oTopDict.arrdFontBBox[1] = 0;
m_oTopDict.arrdFontBBox[2] = 0; m_oTopDict.arrdFontBBox[3] = 0;
m_oTopDict.arrdFontMatrix[0] = 0.001; m_oTopDict.arrdFontMatrix[1] = 0;
m_oTopDict.arrdFontMatrix[2] = 0; m_oTopDict.arrdFontMatrix[3] = 0.001;
m_oTopDict.arrdFontMatrix[4] = 0; m_oTopDict.arrdFontMatrix[5] = 0;
for (nIndex = 1, sLine = (char *)m_sFile; nIndex <= 100 && sLine && (!m_sName || !m_arrEncoding); ++nIndex )
{
if ( !m_sName && !strncmp( sLine, "/FontName", 9) )
{
strncpy( sBuffer, sLine, 255);
sBuffer[255] = '\0';
if ( ( pCur = strchr( sBuffer + 9, '/' ) ) && ( pCur = strtok( pCur + 1, " \t\n\r" ) ) )
{
m_sName = CopyString( pCur );
}
sLine = GetNextLine(sLine);
}
else if ( !strncmp( sLine, "/FontMatrix", 11 ) )
{
strncpy( sBuffer, sLine, 255);
sBuffer[255] = '\0';
ReadDoubleArray<6>( (unsigned char*)(sBuffer + 11), 244, m_oTopDict.arrdFontMatrix );
sLine = GetNextLine( sLine );
}
else if ( !strncmp( sLine, "/FontBBox", 9 ) )
{
strncpy( sBuffer, sLine, 255);
sBuffer[255] = '\0';
ReadDoubleArray<4>( (unsigned char*)(sBuffer + 9), 246, m_oTopDict.arrdFontBBox );
sLine = GetNextLine( sLine );
}
else if (!m_arrEncoding && !strncmp( sLine, "/Encoding StandardEncoding def", 30))
{
m_arrEncoding = c_arrsFontFileType1StandardEncoding;
}
else if (!m_arrEncoding && !strncmp( sLine, "/Encoding 256 array", 19))
{
m_arrEncoding = (char **)MemUtilsMallocArray(256, sizeof(char *));
int nJ = 0;
for (nJ = 0; nJ < 256; ++nJ )
{
m_arrEncoding[nJ] = NULL;
}
for (nJ = 0, sLine = GetNextLine(sLine); nJ < 300 && sLine && ( sLine1 = GetNextLine( sLine )); ++nJ, sLine = sLine1)
{
if ( ( nCount = sLine1 - sLine ) > 255 )
{
nCount = 255;
}
strncpy( sBuffer, sLine, nCount);
sBuffer[ nCount ] = '\0';
for ( pCur = sBuffer; *pCur == ' ' || *pCur == '\t'; ++pCur );
if ( !strncmp( pCur, "dup", 3 ) )
{
for ( pCur += 3; *pCur == ' ' || *pCur == '\t'; ++pCur ) ;
for ( pTemp = pCur; *pTemp >= '0' && *pTemp <= '9'; ++pTemp ) ;
if ( *pTemp )
{
char nChar = *pTemp;
*pTemp = '\0';
nCode = atoi( pCur );
*pTemp = nChar;
if ( nCode == 8 && *pTemp == '#')
{
nCode = 0;
for (++pTemp; *pTemp >= '0' && *pTemp <= '7'; ++pTemp)
{
nCode = nCode * 8 + (*pTemp - '0');
}
}
if ( nCode < 256 )
{
for ( pCur = pTemp; *pCur == ' ' || *pCur == '\t'; ++pCur ) ;
if ( *pCur == '/')
{
++pCur;
for ( pTemp = pCur; *pTemp && *pTemp != ' ' && *pTemp != '\t'; ++pTemp ) ;
*pTemp = '\0';
m_arrEncoding[ nCode ] = CopyString( pCur );
}
}
}
}
else
{
if ( strtok( sBuffer, " \t") && ( pCur = strtok(NULL, " \t\n\r")) && !strcmp( pCur, "def"))
{
break;
}
}
}
}
else
{
if ( !sEexec )
sEexec = (unsigned char*)strstr( sLine, "currentfile eexec" );
sLine = GetNextLine(sLine);
}
}
if ( NULL != sEexec )
{
unsigned char* sTemp = sEexec;
while ( sTemp != (unsigned char*)strstr( (char*)sTemp, "cleartomark" ) && sTemp < m_sFile + m_nLen )
sTemp++;
int nBufferLen = sTemp - ( sEexec + 17 );
unsigned char *sEexecBuffer = (unsigned char*)MemUtilsMalloc( nBufferLen );
if ( !sEexecBuffer )
return;
memcpy( sEexecBuffer, sEexec + 17, nBufferLen );
DecryptEexec( &sEexecBuffer, nBufferLen );
sEexec = sEexecBuffer + 4; // Первые четыре байта были случайными
int nEexecLen = nBufferLen - 4;
// Теперь прочитаем содержимое Private Dict
BOOL bGlyphsSection = FALSE, bSubrsSection = FALSE;
//unsigned short ushChar = '';
CString sToken, sGlyph;
int nLength = 0;
// Выставляем значения по умолчанию элементов Private Dict
m_oPrivateDict.nBlueValues = 0;
m_oPrivateDict.nOtherBlues = 0;
m_oPrivateDict.nFamilyBlues = 0;
m_oPrivateDict.nFamilyOtherBlues = 0;
m_oPrivateDict.dBlueScale = 0.039625;
m_oPrivateDict.nBlueShift = 7;
m_oPrivateDict.nBlueFuzz = 1;
m_oPrivateDict.bHasStdHW = FALSE;
m_oPrivateDict.bHasStdVW = FALSE;
m_oPrivateDict.nStemSnapH = 0;
m_oPrivateDict.nStemSnapV = 0;
m_oPrivateDict.bHasForceBold = FALSE;
m_oPrivateDict.nLanguageGroup = 0;
m_oPrivateDict.nLenIV = 4;
m_oPrivateDict.dExpansionFactor = 0.06;
for ( int nIndex = 0; nIndex < nEexecLen; nIndex++ )
{
unsigned char nChar = sEexec[nIndex];
if ( ( bGlyphsSection || bSubrsSection ) && 'R' == nChar && nLength > 0 )
{
unsigned char *sData = new unsigned char[nLength];
if ( sData )
{
memcpy( sData, sEexec + nIndex + 3, nLength );
unsigned short unKey = 4330U;
unsigned char *sCur = sData;
EexecDecode( &sCur, sCur + nLength, sCur, nLength, &unKey );
if ( m_oPrivateDict.nLenIV > 0 && m_oPrivateDict.nLenIV < nLength )
{
Type1Charstring& oCharstring = DecodeCharString( sData + m_oPrivateDict.nLenIV, nLength - m_oPrivateDict.nLenIV );
if ( bGlyphsSection )
{
int nUnicode = Type1NameToUnicodeW( sGlyph.GetBuffer() );
if ( 0 != nUnicode )
m_arrCharstrings.Add( Type1Glyph( sGlyph, nUnicode, oCharstring ) );
}
else // if ( bSubrsSection )
{
m_arrSubrs.Add( oCharstring );
}
}
delete sData;
}
nIndex += nLength + 3;
}
else if ( IS_PS_SPACE( nChar ) )
{
nLength = Utils::GetInteger( sToken );
sToken.Empty();
}
else
{
sToken.AppendChar( nChar );
if ( !bGlyphsSection && '/' == sToken[0] )
{
int nTempChar = sToken[1];
switch (nTempChar)
{
case 'B':
{
if ( _T("/BlueValues") == sToken )
m_oPrivateDict.nBlueValues = ReadIntArray<type1MaxBlueValues>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrnBlueValues );
else if ( _T("/BlueScale") == sToken )
m_oPrivateDict.dBlueScale = ReadDouble( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
else if ( _T("/BlueShift") == sToken )
m_oPrivateDict.nBlueShift = ReadInt( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
else if ( _T("/BlueFuzz") == sToken )
m_oPrivateDict.nBlueFuzz = ReadInt( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
break;
}
case 'C':
{
if ( _T("/CharString") == sToken )
bGlyphsSection = TRUE;
break;
}
case 'E':
{
if ( _T("/ExpansionFactor") == sToken )
m_oPrivateDict.dExpansionFactor = ReadDouble( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
break;
}
case 'F':
{
if ( _T("/FamilyBlues") == sToken )
m_oPrivateDict.nFamilyBlues = ReadIntArray<type1MaxBlueValues>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrnFamilyBlues );
else if ( _T("/FamilyOtherBlues") == sToken )
m_oPrivateDict.nFamilyOtherBlues = ReadIntArray<type1MaxOtherBlues>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrnFamilyOtherBlues );
else if ( _T("/ForceBold") == sToken )
{
m_oPrivateDict.bHasForceBold = TRUE;
m_oPrivateDict.bForceBold = ReadBool( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
}
break;
}
case 'L':
{
if ( _T("/LanguageGroup") == sToken )
m_oPrivateDict.nLanguageGroup = ReadInt( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
else if ( _T("/lenIV") == sToken )
m_oPrivateDict.nLenIV = ReadInt( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
break;
}
case 'S':
{
if ( _T("/Subrs") == sToken )
bSubrsSection = TRUE;
else if ( _T("/StemSnapH") == sToken )
m_oPrivateDict.nStemSnapH = ReadDoubleArray<type1MaxStemSnap>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrdStemSnapH );
else if ( _T("/StemSnapV") == sToken )
m_oPrivateDict.nStemSnapV = ReadDoubleArray<type1MaxStemSnap>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrdStemSnapV );
else if ( _T("/StdHW") == sToken )
{
// Здесь содержится массив с одним значением
double dTemp[1];
if ( ReadDoubleArray<1>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, dTemp ) > 0 )
{
m_oPrivateDict.bHasStdHW = TRUE;
m_oPrivateDict.dStdHW = dTemp[0];
}
}
else if ( _T("/StdVW") == sToken )
{
// Здесь содержится массив с одним значением
double dTemp[1];
if ( ReadDoubleArray<1>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, dTemp ) > 0 )
{
m_oPrivateDict.bHasStdHW = TRUE;
m_oPrivateDict.dStdVW = dTemp[0];
}
}
}
}
}
else if ( '/' == nChar )
{
sToken.Empty();
sGlyph.Empty();
while ( ( nChar = sEexec[++nIndex] ) != ' ' )
sGlyph.AppendChar( nChar );
}
}
}
MemUtilsFree( sEexecBuffer );
// Проведем сортировку элементов m_arrCharstrings по юникодному значению
qsort( m_arrCharstrings.GetData(), m_arrCharstrings.GetSize(), sizeof(Type1Glyph), CompareType1Glyph );
}
m_bParsed = TRUE;
}
if ( sLine < (char *)m_sFile + m_nLen && *sLine == '\x0d')
++sLine;
void CFontFileType1::DecryptEexec(unsigned char** ppEexecBuffer, int nLen)
{
// Согласно спецификации Type1, первый байт не должен быть ASCII пробелом
// (пробел, таб, перенос каретки или перенос строки).
unsigned char *sCur = (unsigned char*)(*ppEexecBuffer);
while( sCur < (unsigned char*)(*ppEexecBuffer) + nLen && ( ' ' == *sCur || '\t' == *sCur || '\r' == *sCur || '\n' == *sCur ) )
++sCur;
// Теперь нам надо определить в каком формате у нас данные: ASKII или бинарные данные.
// Если первые четыре байта являются шестнадцатиричными символами, значит, кодировка ASCII.
BOOL bASCII = FALSE;
if ( isxdigit( sCur[0] ) && isxdigit( sCur[1] ) && isxdigit( sCur[2] ) && isxdigit( sCur[3] ) )
bASCII = TRUE;
if ( bASCII )
ASCIIHexDecode( &sCur, sCur + nLen, sCur, nLen );
unsigned short ushKey = 55665U;
EexecDecode( &sCur, *ppEexecBuffer + nLen, sCur, nLen, &ushKey );
}
bool CFontFileType1::RemovePfbMarkers()
{
BOOL bSuccess = TRUE;
int nBlockType = 0;
int nBlockLen = 0;
int nChar = 0;
unsigned char *sBuffer = NULL;
int nBufLen = 0;
while ( nBlockType != PFB_DONE )
{
while ( 0 == nBlockLen )
{
nChar = ReadU8( &bSuccess );
if ( !bSuccess )
return false;
nBlockType = ReadU8( &bSuccess );
if ( !bSuccess || PFB_MARKER != nChar || ( PFB_ASCII != nBlockType && PFB_BINARY != nBlockType && PFB_DONE != nBlockType ) )
return false;
if ( PFB_DONE == nBlockType )
break;
nBlockLen = ReadU32LE( &bSuccess );
if ( !bSuccess )
return false;
}
// Читаем сам блок данных
if ( nBlockLen > 0 )
{
if ( !sBuffer )
{
sBuffer = (unsigned char*)MemUtilsMalloc( nBlockLen );
if ( !sBuffer )
return false;
}
else
sBuffer = (unsigned char*)MemUtilsRealloc( sBuffer, nBufLen + nBlockLen );
Read( sBuffer + nBufLen, nBlockLen );
nBufLen += nBlockLen;
}
nBlockLen = 0;
}
if ( m_bFreeFileData )
MemUtilsFree( m_sFile );
m_bFreeFileData = TRUE;
m_sFile = (unsigned char*)sBuffer;
m_sFileData = m_sFile;
m_nLen = nBufLen;
m_nPos = 0;
return true;
}
if ( sLine < (char *)m_sFile + m_nLen && *sLine == '\x0a')
++sLine;
Type1Charstring CFontFileType1::DecodeCharString(unsigned char *sString, int nLen)
{
CSimpleArray<Type1CharstringItem> sCharString;
int nLSB = 0, nWidth = 0;
for ( int nIndex = 0; nIndex < nLen; nIndex++ )
{
int nValue = sString[nIndex];
if ( nValue < 32 ) // команда
{
int nCommand = 0;
if ( 12 == nValue )
{
int nNextValue = sString[++nIndex];
if ( 16 == nNextValue )
{
if ( sCharString.GetSize() <= 0 )
continue;
int nInd = sCharString[sCharString.GetSize() - 1].nValue;
sCharString.RemoveAt( sCharString.GetSize() - 1 );
while ( sCharString.GetSize() > 0 && FALSE == sCharString[sCharString.GetSize() - 1].bCommand )
sCharString.RemoveAt( sCharString.GetSize() - 1 );
// If the flex mechanishm is not used in a font program, Adobe
// state that that entries 0, 1 and 2 can simply be replace by
// {}, which means that we can simply ignore them.
if ( nInd < 3 )
continue;
// This is the same things about hint replacement, if it is not used
// entry 3 can be replaced by {3}
if ( 3 == nInd )
{
sCharString.Add( Type1CharstringItem( 3, TRUE ) );
nIndex++;
continue;
}
}
nCommand = 12 + ( nNextValue << 8 );
}
else
{
if ( 13 == nValue )
{
if ( 2 == sCharString.GetSize() )
nWidth = sCharString[1].nValue;
else if ( 4 == sCharString.GetSize() && 0x0C0C == sCharString[3].nValue && sCharString[3].bCommand )
nWidth = sCharString[1].nValue / sCharString[2].nValue;
else
{
// TO DO: обработать ошибку
nWidth = 0;
}
if ( sCharString.GetSize() > 0 )
{
nLSB = sCharString[0].nValue;
sCharString.Add( Type1CharstringItem( nLSB, FALSE ) );
sCharString.Add( Type1CharstringItem( c_nType1hmoveto, TRUE ) );
sCharString.RemoveAt( 0 );
}
else
{
nLSB = 0;
sCharString.Add( Type1CharstringItem( nLSB, FALSE ) );
sCharString.Add( Type1CharstringItem( c_nType1hmoveto, TRUE ) );
}
continue;
}
nCommand = nValue;
}
// Some charstring commands are meaningless in Type2 and will return
// a null, let's just ignored them
if ( !nCommand && nIndex < nLen )
continue;
else if ( !nCommand )
break;
else if ( c_nType1seac == nCommand || c_nType1sbw == nCommand )
{
// TO DO: обработать ошибку
}
sCharString.Add( Type1CharstringItem( nCommand, TRUE ) );
}
else
{
if ( nValue <= 246 )
nValue = nValue - 139;
else if ( nValue <= 250 )
nValue = ( ( nValue - 247 ) * 256 ) + (int)( sString[++nIndex] ) + 108;
else if ( nValue <= 254 )
nValue = -( ( nValue - 251 ) * 256 ) - (int)( sString[++nIndex] ) - 108;
else
nValue = ( sString[++nIndex] & 0xff ) << 24 | ( sString[++nIndex] & 0xff ) << 16 | ( sString[++nIndex] & 0xff ) << 8 | ( sString[++nIndex] & 0xff ) << 0;
sCharString.Add( Type1CharstringItem( nValue, FALSE ) );
}
}
return Type1Charstring( sCharString, nWidth, nLSB );
}
Type1Charstring CFontFileType1::FlattenCharstring(Type1Charstring& oCharstring, int nBias)
{
Type1Charstring oNew;
oNew.nLSB = oCharstring.nLSB;
oNew.nWidth = oCharstring.nWidth;
for ( int nIndex = 0; nIndex < oCharstring.arrCharstring.GetSize(); nIndex++ )
{
Type1CharstringItem oItem = oCharstring.arrCharstring[nIndex];
int nValue = oItem.nValue;
if ( oItem.bCommand )
{
if ( nValue == c_nType1sub )
{
oNew.arrCharstring.Add( Type1CharstringItem( 12, TRUE ) );
oNew.arrCharstring.Add( Type1CharstringItem( 11, TRUE ) );
}
else if ( nValue == c_nType1div )
{
oNew.arrCharstring.Add( Type1CharstringItem( 12, TRUE ) );
oNew.arrCharstring.Add( Type1CharstringItem( 12, TRUE ) );
}
else if ( nValue == c_nType1pop )
{
//oNew.arrCharstring.Add( Type1CharstringItem( 1, TRUE ) );
oNew.arrCharstring.Add( Type1CharstringItem( 12, TRUE ) );
oNew.arrCharstring.Add( Type1CharstringItem( 18, TRUE ) );
}
else if ( nValue == c_nType1callsubr )
{
//int nTempLen = oNew.arrCharstring.GetSize();
//int nT1 = oNew.arrCharstring[nTempLen - 2].nValue;
//int nT2 = oNew.arrCharstring[nTempLen - 1].nValue;
//int nInd = nT1 << 8 | nT2;
//if ( 107 == nBias )
//{
// if ( nInd <= 215 )
// {
// oNew.arrCharstring.RemoveAt( nTempLen - 1 );
// oNew.arrCharstring.RemoveAt( nTempLen - 2 );
// oNew.arrCharstring[nTempLen - 3].nValue = nInd - nBias + 139;
// oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, TRUE ) );
// }
// else
// {
// oNew.arrCharstring.RemoveAt( nTempLen - 1 );
// oNew.arrCharstring[nTempLen - 3].nValue = ((nInd - nBias) - 108) / 256 + 247;
// oNew.arrCharstring[nTempLen - 2].nValue = ((nInd - nBias) - 108) - (oNew.arrCharstring[nTempLen - 3].nValue - 247) * 256;
// oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, TRUE ) );
// }
//}
//else
//{
// nInd -= nBias;
// oNew.arrCharstring[nTempLen - 2].nValue = nInd >> 8;
// oNew.arrCharstring[nTempLen - 1].nValue = nInd & 0xFF;
// oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, TRUE ) );
//}
oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, TRUE ) );
}
else
oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, TRUE ) );
}
else
{
// Type1 charstrings используют деления для чисел больших 32000
if ( oItem.nValue > 32000 )
{
int nDivisor = oCharstring.arrCharstring[nIndex + 1].nValue;
if ( 0 != nDivisor )
nValue /= nDivisor;
}
oNew.arrCharstring.Add( Type1CharstringItem( 28, TRUE ) );
oNew.arrCharstring.Add( Type1CharstringItem( nValue >> 8, FALSE ) );
oNew.arrCharstring.Add( Type1CharstringItem( nValue & 0xFF, FALSE ) );
}
}
return oNew;
}
void CFontFileType1::CFFCreateIndexHeader(FontFileOutputFunc pOutputFunc, void *pOutputStream, CSimpleArray<CString> aObjects)
{
char nChar;
int nCount = aObjects.GetSize();
if ( 0 == nCount )
{
pOutputFunc( pOutputStream, "\x00\x00\x00", 3 );
return;
}
// Первые два байта - количество элементов
WriteChar( nCount >> 8 );
WriteChar( nCount & 0xFF );
// Размер сдвигов, ставим по максимуму
WriteChar( 0x04 );
int nRelativeOffset = 1;
for ( int nIndex = 0; nIndex < nCount + 1; nIndex++ )
{
WriteChar( (nRelativeOffset >> 24) & 0xFF );
WriteChar( (nRelativeOffset >> 16) & 0xFF );
WriteChar( (nRelativeOffset >> 8) & 0xFF );
WriteChar( (nRelativeOffset) & 0xFF );
if ( nIndex < nCount )
nRelativeOffset += aObjects[nIndex].GetLength();
}
USES_CONVERSION;
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
int nCurLen = aObjects[nIndex].GetLength();
char* sCur = W2A( aObjects[nIndex] );
pOutputFunc( pOutputStream, sCur, nCurLen );
}
}
void CFontFileType1::CFFCreateIndexHeader(FontFileOutputFunc pOutputFunc, void *pOutputStream, CSimpleArray<Type1Charstring> aObjects)
{
char nChar;
int nCount = aObjects.GetSize();
if ( 0 == nCount )
{
pOutputFunc( pOutputStream, "\x00\x00\x00", 3 );
return;
}
// Первые два байта - количество элементов
WriteChar( nCount >> 8 );
WriteChar( nCount & 0xFF );
// Размер сдвигов, ставим по максимуму
WriteChar( 0x04 );
int nRelativeOffset = 1;
for ( int nIndex = 0; nIndex < nCount + 1; nIndex++ )
{
WriteChar( (nRelativeOffset >> 24) & 0xFF );
WriteChar( (nRelativeOffset >> 16) & 0xFF );
WriteChar( (nRelativeOffset >> 8) & 0xFF );
WriteChar( (nRelativeOffset) & 0xFF );
if ( nIndex < nCount )
nRelativeOffset += aObjects[nIndex].arrCharstring.GetSize();
}
for ( int nI = 0; nI < nCount; nI++ )
{
for ( int nJ = 0; nJ < aObjects[nI].arrCharstring.GetSize(); nJ++ )
{
WriteChar( aObjects[nI].arrCharstring[nJ].nValue & 0xFF );
}
}
}
void CFontFileType1::CFFEncodeNumber(FontFileOutputFunc pOutputFunc, void *pOutputStream, int nValue, bool bForceLong)
{
char nChar;
if ( !bForceLong && nValue >= -32768 && nValue <= 32767 )
{
WriteChar( 0x1c );
WriteChar( ( nValue >> 8 ) & 0xFF );
WriteChar( nValue & 0xFF );
}
else // if ( nValue >= (-2147483648) && nValue <= 2147483647 )
{
WriteChar( 0x1d );
WriteChar( ( nValue >> 24 ) & 0xFF );
WriteChar( ( nValue >> 16 ) & 0xFF );
WriteChar( ( nValue >> 8 ) & 0xFF );
WriteChar( nValue & 0xFF );
if ( sLine >= (char *)m_sFile + m_nLen )
return NULL;
return sLine;
}
void CFontFileType1::Parse()
{
// Сначала проверим, если это pfb файл, тогда избавимся от всех его маркеров.
Reset();
while( m_nPos < m_nLen && ( ' ' == m_sFile[m_nPos] || '\t' == m_sFile[m_nPos] || '\r' == m_sFile[m_nPos] || '\n' == m_sFile[m_nPos] ) )
++m_nPos;
bool bSuccess = true;
int nChar = GetU8( m_nPos, &bSuccess );
if ( !bSuccess || ( PFB_MARKER != nChar && '%' != nChar ) )
return;
else if ( PFB_MARKER == nChar )
{
if ( !RemovePfbMarkers() )
return;
}
char *sLine, *sLine1, *pCur, *pTemp;
char sBuffer[256];
int nCount, nCode;
int nIndex = 0;
unsigned char *sEexec = NULL;
m_oTopDict.arrdFontBBox[0] = 0; m_oTopDict.arrdFontBBox[1] = 0;
m_oTopDict.arrdFontBBox[2] = 0; m_oTopDict.arrdFontBBox[3] = 0;
m_oTopDict.arrdFontMatrix[0] = 0.001; m_oTopDict.arrdFontMatrix[1] = 0;
m_oTopDict.arrdFontMatrix[2] = 0; m_oTopDict.arrdFontMatrix[3] = 0.001;
m_oTopDict.arrdFontMatrix[4] = 0; m_oTopDict.arrdFontMatrix[5] = 0;
for (nIndex = 1, sLine = (char *)m_sFile; nIndex <= 100 && sLine && (!m_sName || !m_arrEncoding); ++nIndex )
{
if ( !m_sName && !strncmp( sLine, "/FontName", 9) )
{
strncpy( sBuffer, sLine, 255);
sBuffer[255] = '\0';
if ( ( pCur = strchr( sBuffer + 9, '/' ) ) && ( pCur = strtok( pCur + 1, " \t\n\r" ) ) )
{
m_sName = CopyString( pCur );
}
sLine = GetNextLine(sLine);
}
else if ( !strncmp( sLine, "/FontMatrix", 11 ) )
{
strncpy( sBuffer, sLine, 255);
sBuffer[255] = '\0';
ReadDoubleArray<6>( (unsigned char*)(sBuffer + 11), 244, m_oTopDict.arrdFontMatrix );
sLine = GetNextLine( sLine );
}
else if ( !strncmp( sLine, "/FontBBox", 9 ) )
{
strncpy( sBuffer, sLine, 255);
sBuffer[255] = '\0';
ReadDoubleArray<4>( (unsigned char*)(sBuffer + 9), 246, m_oTopDict.arrdFontBBox );
sLine = GetNextLine( sLine );
}
else if (!m_arrEncoding && !strncmp( sLine, "/Encoding StandardEncoding def", 30))
{
m_arrEncoding = c_arrsFontFileType1StandardEncoding;
}
else if (!m_arrEncoding && !strncmp( sLine, "/Encoding 256 array", 19))
{
m_arrEncoding = (char **)MemUtilsMallocArray(256, sizeof(char *));
int nJ = 0;
for (nJ = 0; nJ < 256; ++nJ )
{
m_arrEncoding[nJ] = NULL;
}
for (nJ = 0, sLine = GetNextLine(sLine); nJ < 300 && sLine && ( sLine1 = GetNextLine( sLine )); ++nJ, sLine = sLine1)
{
if ( ( nCount = sLine1 - sLine ) > 255 )
{
nCount = 255;
}
strncpy( sBuffer, sLine, nCount);
sBuffer[ nCount ] = '\0';
for ( pCur = sBuffer; *pCur == ' ' || *pCur == '\t'; ++pCur );
if ( !strncmp( pCur, "dup", 3 ) )
{
for ( pCur += 3; *pCur == ' ' || *pCur == '\t'; ++pCur ) ;
for ( pTemp = pCur; *pTemp >= '0' && *pTemp <= '9'; ++pTemp ) ;
if ( *pTemp )
{
char nChar = *pTemp;
*pTemp = '\0';
nCode = atoi( pCur );
*pTemp = nChar;
if ( nCode == 8 && *pTemp == '#')
{
nCode = 0;
for (++pTemp; *pTemp >= '0' && *pTemp <= '7'; ++pTemp)
{
nCode = nCode * 8 + (*pTemp - '0');
}
}
if ( nCode < 256 )
{
for ( pCur = pTemp; *pCur == ' ' || *pCur == '\t'; ++pCur ) ;
if ( *pCur == '/')
{
++pCur;
for ( pTemp = pCur; *pTemp && *pTemp != ' ' && *pTemp != '\t'; ++pTemp ) ;
*pTemp = '\0';
m_arrEncoding[ nCode ] = CopyString( pCur );
}
}
}
}
else
{
if ( strtok( sBuffer, " \t") && ( pCur = strtok(NULL, " \t\n\r")) && !strcmp( pCur, "def"))
{
break;
}
}
}
}
else
{
if ( !sEexec )
sEexec = (unsigned char*)strstr( sLine, "currentfile eexec" );
sLine = GetNextLine(sLine);
}
}
if ( NULL != sEexec )
{
unsigned char* sTemp = sEexec;
while ( sTemp != (unsigned char*)strstr( (char*)sTemp, "cleartomark" ) && sTemp < m_sFile + m_nLen )
sTemp++;
int nBufferLen = sTemp - ( sEexec + 17 );
unsigned char *sEexecBuffer = (unsigned char*)MemUtilsMalloc( nBufferLen );
if ( !sEexecBuffer )
return;
memcpy( sEexecBuffer, sEexec + 17, nBufferLen );
DecryptEexec( &sEexecBuffer, nBufferLen );
sEexec = sEexecBuffer + 4; // Первые четыре байта были случайными
int nEexecLen = nBufferLen - 4;
// Теперь прочитаем содержимое Private Dict
bool bGlyphsSection = false, bSubrsSection = false;
//unsigned short ushChar = '';
std::wstring sToken, sGlyph;
int nLength = 0;
// Выставляем значения по умолчанию элементов Private Dict
m_oPrivateDict.nBlueValues = 0;
m_oPrivateDict.nOtherBlues = 0;
m_oPrivateDict.nFamilyBlues = 0;
m_oPrivateDict.nFamilyOtherBlues = 0;
m_oPrivateDict.dBlueScale = 0.039625;
m_oPrivateDict.nBlueShift = 7;
m_oPrivateDict.nBlueFuzz = 1;
m_oPrivateDict.bHasStdHW = false;
m_oPrivateDict.bHasStdVW = false;
m_oPrivateDict.nStemSnapH = 0;
m_oPrivateDict.nStemSnapV = 0;
m_oPrivateDict.bHasForceBold = false;
m_oPrivateDict.nLanguageGroup = 0;
m_oPrivateDict.nLenIV = 4;
m_oPrivateDict.dExpansionFactor = 0.06;
for ( int nIndex = 0; nIndex < nEexecLen; nIndex++ )
{
unsigned char nChar = sEexec[nIndex];
if ( ( bGlyphsSection || bSubrsSection ) && 'R' == nChar && nLength > 0 )
{
unsigned char *sData = new unsigned char[nLength];
if ( sData )
{
memcpy( sData, sEexec + nIndex + 3, nLength );
unsigned short unKey = 4330U;
unsigned char *sCur = sData;
EexecDecode( &sCur, sCur + nLength, sCur, nLength, &unKey );
if ( m_oPrivateDict.nLenIV > 0 && m_oPrivateDict.nLenIV < nLength )
{
Type1Charstring& oCharstring = DecodeCharString( sData + m_oPrivateDict.nLenIV, nLength - m_oPrivateDict.nLenIV );
if ( bGlyphsSection )
{
int nUnicode = Type1NameToUnicodeW( sGlyph.c_str() );
if ( 0 != nUnicode )
m_arrCharstrings.Add( Type1Glyph( sGlyph, nUnicode, oCharstring ) );
}
else // if ( bSubrsSection )
{
m_arrSubrs.Add( oCharstring );
}
}
delete sData;
}
nIndex += nLength + 3;
}
else if ( IS_PS_SPACE( nChar ) )
{
nLength = Utils::GetInteger( sToken );
sToken.clear();
}
else
{
sToken.push_back( (wchar_t)nChar );
if ( !bGlyphsSection && '/' == sToken[0] )
{
int nTempChar = sToken[1];
switch (nTempChar)
{
case 'B':
{
if ( L"/BlueValues" == sToken )
m_oPrivateDict.nBlueValues = ReadIntArray<type1MaxBlueValues>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrnBlueValues );
else if ( L"/BlueScale" == sToken )
m_oPrivateDict.dBlueScale = ReadDouble( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
else if ( L"/BlueShift" == sToken )
m_oPrivateDict.nBlueShift = ReadInt( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
else if ( L"/BlueFuzz" == sToken )
m_oPrivateDict.nBlueFuzz = ReadInt( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
break;
}
case 'C':
{
if ( L"/CharString" == sToken )
bGlyphsSection = true;
break;
}
case 'E':
{
if ( L"/ExpansionFactor" == sToken )
m_oPrivateDict.dExpansionFactor = ReadDouble( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
break;
}
case 'F':
{
if ( L"/FamilyBlues" == sToken )
m_oPrivateDict.nFamilyBlues = ReadIntArray<type1MaxBlueValues>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrnFamilyBlues );
else if ( L"/FamilyOtherBlues" == sToken )
m_oPrivateDict.nFamilyOtherBlues = ReadIntArray<type1MaxOtherBlues>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrnFamilyOtherBlues );
else if ( L"/ForceBold" == sToken )
{
m_oPrivateDict.bHasForceBold = true;
m_oPrivateDict.bForceBold = ReadBool( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
}
break;
}
case 'L':
{
if ( L"/LanguageGroup" == sToken )
m_oPrivateDict.nLanguageGroup = ReadInt( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
else if ( L"/lenIV" == sToken )
m_oPrivateDict.nLenIV = ReadInt( sEexec + nIndex + 1, nEexecLen - nIndex - 1 );
break;
}
case 'S':
{
if ( L"/Subrs" == sToken )
bSubrsSection = true;
else if ( L"/StemSnapH" == sToken )
m_oPrivateDict.nStemSnapH = ReadDoubleArray<type1MaxStemSnap>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrdStemSnapH );
else if ( L"/StemSnapV" == sToken )
m_oPrivateDict.nStemSnapV = ReadDoubleArray<type1MaxStemSnap>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, m_oPrivateDict.arrdStemSnapV );
else if ( L"/StdHW" == sToken )
{
// Здесь содержится массив с одним значением
double dTemp[1];
if ( ReadDoubleArray<1>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, dTemp ) > 0 )
{
m_oPrivateDict.bHasStdHW = true;
m_oPrivateDict.dStdHW = dTemp[0];
}
}
else if ( L"/StdVW" == sToken )
{
// Здесь содержится массив с одним значением
double dTemp[1];
if ( ReadDoubleArray<1>( sEexec + nIndex + 2, nEexecLen - nIndex - 2, dTemp ) > 0 )
{
m_oPrivateDict.bHasStdHW = true;
m_oPrivateDict.dStdVW = dTemp[0];
}
}
}
}
}
else if ( '/' == nChar )
{
sToken.clear();
sGlyph.clear();
while ( ( nChar = sEexec[++nIndex] ) != ' ' )
sGlyph.push_back( (wchar_t)nChar );
}
}
}
MemUtilsFree( sEexecBuffer );
// Проведем сортировку элементов m_arrCharstrings по юникодному значению
qsort( m_arrCharstrings.GetData(), m_arrCharstrings.GetSize(), sizeof(Type1Glyph), CompareType1Glyph );
}
m_bParsed = true;
}
void CFontFileType1::DecryptEexec(unsigned char** ppEexecBuffer, int nLen)
{
// Согласно спецификации Type1, первый байт не должен быть ASCII пробелом
// (пробел, таб, перенос каретки или перенос строки).
unsigned char *sCur = (unsigned char*)(*ppEexecBuffer);
while( sCur < (unsigned char*)(*ppEexecBuffer) + nLen && ( ' ' == *sCur || '\t' == *sCur || '\r' == *sCur || '\n' == *sCur ) )
++sCur;
// Теперь нам надо определить в каком формате у нас данные: ASKII или бинарные данные.
// Если первые четыре байта являются шестнадцатиричными символами, значит, кодировка ASCII.
bool bASCII = false;
if ( isxdigit( sCur[0] ) && isxdigit( sCur[1] ) && isxdigit( sCur[2] ) && isxdigit( sCur[3] ) )
bASCII = true;
if ( bASCII )
ASCIIHexDecode( &sCur, sCur + nLen, sCur, nLen );
unsigned short ushKey = 55665U;
EexecDecode( &sCur, *ppEexecBuffer + nLen, sCur, nLen, &ushKey );
}
bool CFontFileType1::RemovePfbMarkers()
{
bool bSuccess = true;
int nBlockType = 0;
int nBlockLen = 0;
int nChar = 0;
unsigned char *sBuffer = NULL;
int nBufLen = 0;
while ( nBlockType != PFB_DONE )
{
while ( 0 == nBlockLen )
{
nChar = ReadU8( &bSuccess );
if ( !bSuccess )
return false;
nBlockType = ReadU8( &bSuccess );
if ( !bSuccess || PFB_MARKER != nChar || ( PFB_ASCII != nBlockType && PFB_BINARY != nBlockType && PFB_DONE != nBlockType ) )
return false;
if ( PFB_DONE == nBlockType )
break;
nBlockLen = ReadU32LE( &bSuccess );
if ( !bSuccess )
return false;
}
// Читаем сам блок данных
if ( nBlockLen > 0 )
{
if ( !sBuffer )
{
sBuffer = (unsigned char*)MemUtilsMalloc( nBlockLen );
if ( !sBuffer )
return false;
}
else
sBuffer = (unsigned char*)MemUtilsRealloc( sBuffer, nBufLen + nBlockLen );
Read( sBuffer + nBufLen, nBlockLen );
nBufLen += nBlockLen;
}
nBlockLen = 0;
}
if ( m_bFreeFileData )
MemUtilsFree( m_sFile );
m_bFreeFileData = true;
m_sFile = (unsigned char*)sBuffer;
m_sFileData = m_sFile;
m_nLen = nBufLen;
m_nPos = 0;
return true;
}
Type1Charstring CFontFileType1::DecodeCharString(unsigned char *sString, int nLen)
{
CArray<Type1CharstringItem> sCharString;
int nLSB = 0, nWidth = 0;
for ( int nIndex = 0; nIndex < nLen; nIndex++ )
{
int nValue = sString[nIndex];
if ( nValue < 32 ) // команда
{
int nCommand = 0;
if ( 12 == nValue )
{
int nNextValue = sString[++nIndex];
if ( 16 == nNextValue )
{
if ( sCharString.GetSize() <= 0 )
continue;
int nInd = sCharString[sCharString.GetSize() - 1].nValue;
sCharString.RemoveAt( sCharString.GetSize() - 1 );
while ( sCharString.GetSize() > 0 && false == sCharString[sCharString.GetSize() - 1].bCommand )
sCharString.RemoveAt( sCharString.GetSize() - 1 );
// If the flex mechanishm is not used in a font program, Adobe
// state that that entries 0, 1 and 2 can simply be replace by
// {}, which means that we can simply ignore them.
if ( nInd < 3 )
continue;
// This is the same things about hint replacement, if it is not used
// entry 3 can be replaced by {3}
if ( 3 == nInd )
{
sCharString.Add( Type1CharstringItem( 3, true ) );
nIndex++;
continue;
}
}
nCommand = 12 + ( nNextValue << 8 );
}
else
{
if ( 13 == nValue )
{
if ( 2 == sCharString.GetSize() )
nWidth = sCharString[1].nValue;
else if ( 4 == sCharString.GetSize() && 0x0C0C == sCharString[3].nValue && sCharString[3].bCommand )
nWidth = sCharString[1].nValue / sCharString[2].nValue;
else
{
// TO DO: обработать ошибку
nWidth = 0;
}
if ( sCharString.GetSize() > 0 )
{
nLSB = sCharString[0].nValue;
sCharString.Add( Type1CharstringItem( nLSB, false ) );
sCharString.Add( Type1CharstringItem( c_nType1hmoveto, true ) );
sCharString.RemoveAt( 0 );
}
else
{
nLSB = 0;
sCharString.Add( Type1CharstringItem( nLSB, false ) );
sCharString.Add( Type1CharstringItem( c_nType1hmoveto, true ) );
}
continue;
}
nCommand = nValue;
}
// Some charstring commands are meaningless in Type2 and will return
// a null, let's just ignored them
if ( !nCommand && nIndex < nLen )
continue;
else if ( !nCommand )
break;
else if ( c_nType1seac == nCommand || c_nType1sbw == nCommand )
{
// TO DO: обработать ошибку
}
sCharString.Add( Type1CharstringItem( nCommand, true ) );
}
else
{
if ( nValue <= 246 )
nValue = nValue - 139;
else if ( nValue <= 250 )
nValue = ( ( nValue - 247 ) * 256 ) + (int)( sString[++nIndex] ) + 108;
else if ( nValue <= 254 )
nValue = -( ( nValue - 251 ) * 256 ) - (int)( sString[++nIndex] ) - 108;
else
nValue = ( sString[++nIndex] & 0xff ) << 24 | ( sString[++nIndex] & 0xff ) << 16 | ( sString[++nIndex] & 0xff ) << 8 | ( sString[++nIndex] & 0xff ) << 0;
sCharString.Add( Type1CharstringItem( nValue, false ) );
}
}
return Type1Charstring( sCharString, nWidth, nLSB );
}
Type1Charstring CFontFileType1::FlattenCharstring(Type1Charstring& oCharstring, int nBias)
{
Type1Charstring oNew;
oNew.nLSB = oCharstring.nLSB;
oNew.nWidth = oCharstring.nWidth;
for ( int nIndex = 0; nIndex < oCharstring.arrCharstring.GetSize(); nIndex++ )
{
Type1CharstringItem oItem = oCharstring.arrCharstring[nIndex];
int nValue = oItem.nValue;
if ( oItem.bCommand )
{
if ( nValue == c_nType1sub )
{
oNew.arrCharstring.Add( Type1CharstringItem( 12, true ) );
oNew.arrCharstring.Add( Type1CharstringItem( 11, true ) );
}
else if ( nValue == c_nType1div )
{
oNew.arrCharstring.Add( Type1CharstringItem( 12, true ) );
oNew.arrCharstring.Add( Type1CharstringItem( 12, true ) );
}
else if ( nValue == c_nType1pop )
{
//oNew.arrCharstring.Add( Type1CharstringItem( 1, true ) );
oNew.arrCharstring.Add( Type1CharstringItem( 12, true ) );
oNew.arrCharstring.Add( Type1CharstringItem( 18, true ) );
}
else if ( nValue == c_nType1callsubr )
{
//int nTempLen = oNew.arrCharstring.GetSize();
//int nT1 = oNew.arrCharstring[nTempLen - 2].nValue;
//int nT2 = oNew.arrCharstring[nTempLen - 1].nValue;
//int nInd = nT1 << 8 | nT2;
//if ( 107 == nBias )
//{
// if ( nInd <= 215 )
// {
// oNew.arrCharstring.RemoveAt( nTempLen - 1 );
// oNew.arrCharstring.RemoveAt( nTempLen - 2 );
// oNew.arrCharstring[nTempLen - 3].nValue = nInd - nBias + 139;
// oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, true ) );
// }
// else
// {
// oNew.arrCharstring.RemoveAt( nTempLen - 1 );
// oNew.arrCharstring[nTempLen - 3].nValue = ((nInd - nBias) - 108) / 256 + 247;
// oNew.arrCharstring[nTempLen - 2].nValue = ((nInd - nBias) - 108) - (oNew.arrCharstring[nTempLen - 3].nValue - 247) * 256;
// oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, true ) );
// }
//}
//else
//{
// nInd -= nBias;
// oNew.arrCharstring[nTempLen - 2].nValue = nInd >> 8;
// oNew.arrCharstring[nTempLen - 1].nValue = nInd & 0xFF;
// oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, true ) );
//}
oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, true ) );
}
else
oNew.arrCharstring.Add( Type1CharstringItem( oItem.nValue, true ) );
}
else
{
// Type1 charstrings используют деления для чисел больших 32000
if ( oItem.nValue > 32000 )
{
int nDivisor = oCharstring.arrCharstring[nIndex + 1].nValue;
if ( 0 != nDivisor )
nValue /= nDivisor;
}
oNew.arrCharstring.Add( Type1CharstringItem( 28, true ) );
oNew.arrCharstring.Add( Type1CharstringItem( nValue >> 8, false ) );
oNew.arrCharstring.Add( Type1CharstringItem( nValue & 0xFF, false ) );
}
}
return oNew;
}
void CFontFileType1::CFFCreateIndexHeader(FontFileOutputFunc pOutputFunc, void *pOutputStream, CArray<std::wstring> aObjects)
{
char nChar;
int nCount = aObjects.GetSize();
if ( 0 == nCount )
{
pOutputFunc( pOutputStream, "\x00\x00\x00", 3 );
return;
}
// Первые два байта - количество элементов
WriteChar( nCount >> 8 );
WriteChar( nCount & 0xFF );
// Размер сдвигов, ставим по максимуму
WriteChar( 0x04 );
int nRelativeOffset = 1;
for ( int nIndex = 0; nIndex < nCount + 1; nIndex++ )
{
WriteChar( (nRelativeOffset >> 24) & 0xFF );
WriteChar( (nRelativeOffset >> 16) & 0xFF );
WriteChar( (nRelativeOffset >> 8) & 0xFF );
WriteChar( (nRelativeOffset) & 0xFF );
if ( nIndex < nCount )
nRelativeOffset += aObjects[nIndex].length();
}
for ( int nIndex = 0; nIndex < nCount; nIndex++ )
{
std::string sCur = U_TO_UTF8((aObjects[nIndex]));
pOutputFunc( pOutputStream, sCur.c_str(), sCur.length() );
}
}
void CFontFileType1::CFFCreateIndexHeader(FontFileOutputFunc pOutputFunc, void *pOutputStream, CArray<Type1Charstring> aObjects)
{
char nChar;
int nCount = aObjects.GetSize();
if ( 0 == nCount )
{
pOutputFunc( pOutputStream, "\x00\x00\x00", 3 );
return;
}
// Первые два байта - количество элементов
WriteChar( nCount >> 8 );
WriteChar( nCount & 0xFF );
// Размер сдвигов, ставим по максимуму
WriteChar( 0x04 );
int nRelativeOffset = 1;
for ( int nIndex = 0; nIndex < nCount + 1; nIndex++ )
{
WriteChar( (nRelativeOffset >> 24) & 0xFF );
WriteChar( (nRelativeOffset >> 16) & 0xFF );
WriteChar( (nRelativeOffset >> 8) & 0xFF );
WriteChar( (nRelativeOffset) & 0xFF );
if ( nIndex < nCount )
nRelativeOffset += aObjects[nIndex].arrCharstring.GetSize();
}
for ( int nI = 0; nI < nCount; nI++ )
{
for ( int nJ = 0; nJ < aObjects[nI].arrCharstring.GetSize(); nJ++ )
{
WriteChar( aObjects[nI].arrCharstring[nJ].nValue & 0xFF );
}
}
}
void CFontFileType1::CFFEncodeNumber(FontFileOutputFunc pOutputFunc, void *pOutputStream, int nValue, bool bForceLong)
{
char nChar;
if ( !bForceLong && nValue >= -32768 && nValue <= 32767 )
{
WriteChar( 0x1c );
WriteChar( ( nValue >> 8 ) & 0xFF );
WriteChar( nValue & 0xFF );
}
else // if ( nValue >= (-2147483648) && nValue <= 2147483647 )
{
WriteChar( 0x1d );
WriteChar( ( nValue >> 24 ) & 0xFF );
WriteChar( ( nValue >> 16 ) & 0xFF );
WriteChar( ( nValue >> 8 ) & 0xFF );
WriteChar( nValue & 0xFF );
}
}
void CFontFileType1::CFFEncodeNumber(FontFileOutputFunc pOutputFunc, void *pOutputStream, double dValue)
{
char nChar = 0;
WriteChar( 0x1e ); // начало десятичного числа
std::wstring sValue = std::to_wstring(dValue);
bool bFirstNibble = true;
for ( int nIndex = 0; nIndex < sValue.length(); nIndex++ )
{
int nCurChar = sValue.c_str()[ nIndex ];
if ( '0' <= nCurChar && nCurChar <= '9' )
nCurChar -= (int)('0');
else if ( '.' == nCurChar )
nCurChar = 0x0a;
else if ( '-' == nCurChar )
nCurChar = 0x0e;
else
continue;
if ( bFirstNibble )
nChar = nCurChar << 4;
else
{
nChar += nCurChar;
WriteChar( nChar );
}
bFirstNibble = !bFirstNibble;
}
// Записываем окончаниедесятичного числа
if ( bFirstNibble )
nChar = (char)0xff;
else
nChar += 0x0f;
WriteChar( nChar );
}
void CFontFileType1::ToCFF(FontFileOutputFunc pOutputFunc, void *pOutputStream)
{
std::wstring sFontName = NSFile::CUtf8Converter::GetUnicodeFromCharPtr( m_sName, (LONG)strlen(m_sName) );
CArray<std::wstring> aString;
int nBias = 0;
int nSubrsLen = m_arrSubrs.GetSize();
if ( nSubrsLen < 1240 )
nBias = 107;
else if ( nSubrsLen < 33900 )
nBias = 1131;
else
nBias = 32768;
CArray<Type1Charstring> arrType2Charstrings;
Type1Charstring oFirstCharstring;
oFirstCharstring.arrCharstring.Add( Type1CharstringItem( 0x8B, false ) );
oFirstCharstring.arrCharstring.Add( Type1CharstringItem( 0x0E, false ) );
arrType2Charstrings.Add( oFirstCharstring );
for ( int nIndex = 0; nIndex < m_arrCharstrings.GetSize(); nIndex++ )
{
std::wstring sG = m_arrCharstrings[nIndex].sGlyph;
if ( L"afii10090" == sG )
int k = 10;
arrType2Charstrings.Add( FlattenCharstring( m_arrCharstrings[nIndex].oData, nBias ) );
}
CArray<Type1Charstring> arrType2Subrs;
//Type1Charstring oBias;
////oBias.arrCharstring.Add( Type1CharstringItem( 0x0B, false ) );
//oBias.arrCharstring.Add( Type1CharstringItem( 0x0E, false ) );
//for ( int nIndex = 0; nIndex < nBias; nIndex++ )
// arrType2Subrs.Add( oBias );
for ( int nIndex = 0; nIndex < nSubrsLen; nIndex++ )
{
//if ( nIndex == 256 )
//{
// Type1Charstring oBias;
// oBias.arrCharstring.Add( Type1CharstringItem( 0x0B, false ) );
// for ( int nIndex = 0; nIndex < nBias; nIndex++ )
// arrType2Subrs.Add( oBias );
//}
arrType2Subrs.Add( FlattenCharstring( m_arrSubrs[nIndex], 0 ) );
}
// Header
TCharBuffer oHeader;
oHeader.Write( "\x01\x00\x04\x04", 4 );
// Name
TCharBuffer oName;
aString.RemoveAll();
aString.Add( sFontName );
CFFCreateIndexHeader( CharBufferWrite, &oName, aString );
// Strings
TCharBuffer oStrings;
aString.RemoveAll();
int nNewSID = CFF_STANDARD_STRINGS_COUNT;
aString.Add( L"Version 0.11" ); nNewSID++; // Version
aString.Add( L"See original notice" ); nNewSID++; // Notice
aString.Add( sFontName ); nNewSID++; // FullName
aString.Add( sFontName ); nNewSID++; // FamilyName
aString.Add( L"Medium" ); nNewSID++; // Weight
for ( int nIndex = 0; nIndex < m_arrCharstrings.GetSize(); nIndex++ )
{
int nSID = GetCFFStringIndex( m_arrCharstrings[nIndex].sGlyph.c_str() );
if ( nSID < 0 )
{
aString.Add( m_arrCharstrings[nIndex].sGlyph );
nSID = nNewSID;
nNewSID++;
}
m_arrCharstrings[nIndex].nReserved = nSID;
}
CFFCreateIndexHeader( CharBufferWrite, &oStrings, aString );
// GlobalSubrs
TCharBuffer oGlobalSubrs;
aString.RemoveAll(); // Записываем пустой массив
CFFCreateIndexHeader( CharBufferWrite, &oGlobalSubrs, aString );
// Charset
TCharBuffer oCharset;
oCharset.Write( (char)0x00 ); // Encoding
int nGlyphsCount = m_arrCharstrings.GetSize();
for ( int nIndex = 0; nIndex < nGlyphsCount; nIndex++ )
{
int nSID = m_arrCharstrings[nIndex].nReserved;
oCharset.Write( (char)(nSID >> 8) );
oCharset.Write( (char)(nSID & 0xFF) );
}
// Charstrings
TCharBuffer oCharstrings;
CFFCreateIndexHeader( NSFontConverter::CharBufferWrite, &oCharstrings, arrType2Charstrings );
// Private
TCharBuffer oPrivate;
oPrivate.Write( "\x8b\x14", 2 ); // defaultWidth
oPrivate.Write( "\x8b\x15", 2 ); // nominalWidth
// Private: BlueValues
if ( m_oPrivateDict.nBlueValues > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnBlueValues[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nBlueValues; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnBlueValues[nIndex] - m_oPrivateDict.arrnBlueValues[nIndex - 1] );
oPrivate.Write( (char)0x06 );
}
// Private: OtherBlues
if ( m_oPrivateDict.nOtherBlues > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnOtherBlues[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nOtherBlues; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnOtherBlues[nIndex] - m_oPrivateDict.arrnOtherBlues[nIndex - 1] );
oPrivate.Write( (char)0x07 );
}
// Private: FamilyBlues
if ( m_oPrivateDict.nFamilyBlues > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnFamilyBlues[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nFamilyBlues; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnFamilyBlues[nIndex] - m_oPrivateDict.arrnFamilyBlues[nIndex - 1] );
oPrivate.Write( (char)0x08 );
}
// Private: FamilyOtherBlues
if ( m_oPrivateDict.nFamilyOtherBlues > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnFamilyOtherBlues[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nFamilyOtherBlues; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnFamilyOtherBlues[nIndex] - m_oPrivateDict.arrnFamilyOtherBlues[nIndex - 1] );
oPrivate.Write( (char)0x09 );
}
// Private: StemSnapH
if ( m_oPrivateDict.nStemSnapH > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrdStemSnapH[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nStemSnapH; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrdStemSnapH[nIndex] - m_oPrivateDict.arrdStemSnapH[nIndex - 1] );
oPrivate.Write( "\x0c\x0c" , 2);
}
// Private: StemSnapV
if ( m_oPrivateDict.nStemSnapV > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrdStemSnapV[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nStemSnapV; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrdStemSnapV[nIndex] - m_oPrivateDict.arrdStemSnapV[nIndex - 1] );
oPrivate.Write( "\x0c\x0d" , 2);
}
// Private: BlueShift
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.nBlueShift );
oPrivate.Write( "\x0c\x0a", 2 );
// Private: BlueFuzz
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.nBlueFuzz );
oPrivate.Write( "\x0c\x0b", 2 );
// Private: BlueScale
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.dBlueScale );
oPrivate.Write( "\x0c\x09", 2 );
// Private: LanguageGroup
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.nLanguageGroup );
oPrivate.Write( "\x0c\x11", 2 );
// Private: ExpansionFactor
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.dExpansionFactor );
oPrivate.Write( "\x0c\x18", 2 );
// Private: Subrs
int nPrivateLen = oPrivate.nLen + (5 + 1);
CFFEncodeNumber( CharBufferWrite, &oPrivate, nPrivateLen, true );
oPrivate.Write( "\x13", 1 );
// LocalSubrs
TCharBuffer oLocalSubrs;
CFFCreateIndexHeader( CharBufferWrite, &oLocalSubrs, arrType2Subrs );
// Top Dict
TCharBuffer oTopDict;
oTopDict.Write( "\x00\x01\x04\x00\x00\x00\x01\x00\x00\0x00\x00", 11 );
oTopDict.Write( "\xf8\x1b\x00", 3 ); // Version
oTopDict.Write( "\xf8\x1c\x01", 3 ); // Notice
oTopDict.Write( "\xf8\x1d\x02", 3 ); // FullName
oTopDict.Write( "\xf8\x1e\x03", 3 ); // FamilyName
oTopDict.Write( "\xf8\x1f\x04", 3 ); // Weight
oTopDict.Write( "\x1c\x00\x00\x10", 4 ); // Encoding
// BBox
CFFEncodeNumber( CharBufferWrite, &oTopDict, m_oTopDict.arrdFontBBox[0] );
CFFEncodeNumber( CharBufferWrite, &oTopDict, m_oTopDict.arrdFontBBox[1] );
CFFEncodeNumber( CharBufferWrite, &oTopDict, m_oTopDict.arrdFontBBox[2] );
CFFEncodeNumber( CharBufferWrite, &oTopDict, m_oTopDict.arrdFontBBox[3] );
oTopDict.Write( "\x05", 1 );
// Теперь оценим размер TopDict: Возьмем текущую длину, добавим к ней (4 * 5 + 3)
// ( 4 числа, которые пишем по 5 байт + 3 байта на 3 команды)
int nTopDictLen = oTopDict.nLen + ( 4 * 5 + 3);
int nOffset = oHeader.nLen + oName.nLen + nTopDictLen + oStrings.nLen + oGlobalSubrs.nLen;
CFFEncodeNumber( CharBufferWrite, &oTopDict, nOffset, true );
oTopDict.Write( "\x0f", 1 ); // Charset
nOffset += oCharset.nLen;//( arrType2Charstrings.GetSize() * 2 ) + 1;
CFFEncodeNumber( CharBufferWrite, &oTopDict, nOffset, true );
oTopDict.Write( "\x11", 1 ); // Charstrings
CFFEncodeNumber( CharBufferWrite, &oTopDict, oPrivate.nLen, true );
nOffset += oCharstrings.nLen;
CFFEncodeNumber( CharBufferWrite, &oTopDict, nOffset, true );
oTopDict.Write( "\x12", 1 ); // Private
// Теперь запишем реальный размер TopDict
int nTopDictDataLen = nTopDictLen - 10;
oTopDict.sBuffer[7] = ( nTopDictDataLen >> 24 ) & 0xFF;
oTopDict.sBuffer[8] = ( nTopDictDataLen >> 16 ) & 0xFF;
oTopDict.sBuffer[9] = ( nTopDictDataLen >> 8 ) & 0xFF;
oTopDict.sBuffer[10] = nTopDictDataLen & 0xFF;
// Записываем все в файл
pOutputFunc( pOutputStream, oHeader.sBuffer, oHeader.nLen );
pOutputFunc( pOutputStream, oName.sBuffer, oName.nLen );
pOutputFunc( pOutputStream, oTopDict.sBuffer, oTopDict.nLen );
pOutputFunc( pOutputStream, oStrings.sBuffer, oStrings.nLen );
pOutputFunc( pOutputStream, oGlobalSubrs.sBuffer, oGlobalSubrs.nLen );
pOutputFunc( pOutputStream, oCharset.sBuffer, oCharset.nLen );
pOutputFunc( pOutputStream, oCharstrings.sBuffer, oCharstrings.nLen );
pOutputFunc( pOutputStream, oPrivate.sBuffer, oPrivate.nLen );
pOutputFunc( pOutputStream, oLocalSubrs.sBuffer, oLocalSubrs.nLen );
}
}
void CFontFileType1::CFFEncodeNumber(FontFileOutputFunc pOutputFunc, void *pOutputStream, double dValue)
{
char nChar = 0;
WriteChar( 0x1e ); // начало десятичного числа
CString sValue;
sValue.Format( _T("%f"), dValue );
bool bFirstNibble = true;
for ( int nIndex = 0; nIndex < sValue.GetLength(); nIndex++ )
{
int nCurChar = sValue.GetAt( nIndex );
if ( '0' <= nCurChar && nCurChar <= '9' )
nCurChar -= (int)('0');
else if ( '.' == nCurChar )
nCurChar = 0x0a;
else if ( '-' == nCurChar )
nCurChar = 0x0e;
else
continue;
if ( bFirstNibble )
nChar = nCurChar << 4;
else
{
nChar += nCurChar;
WriteChar( nChar );
}
bFirstNibble = !bFirstNibble;
}
// Записываем окончаниедесятичного числа
if ( bFirstNibble )
nChar = (char)0xff;
else
nChar += 0x0f;
WriteChar( nChar );
}
void CFontFileType1::ToCFF(FontFileOutputFunc pOutputFunc, void *pOutputStream)
{
CString sFontName( m_sName );
CSimpleArray<CString> aString;
int nBias = 0;
int nSubrsLen = m_arrSubrs.GetSize();
if ( nSubrsLen < 1240 )
nBias = 107;
else if ( nSubrsLen < 33900 )
nBias = 1131;
else
nBias = 32768;
CSimpleArray<Type1Charstring> arrType2Charstrings;
Type1Charstring oFirstCharstring;
oFirstCharstring.arrCharstring.Add( Type1CharstringItem( 0x8B, FALSE ) );
oFirstCharstring.arrCharstring.Add( Type1CharstringItem( 0x0E, FALSE ) );
arrType2Charstrings.Add( oFirstCharstring );
for ( int nIndex = 0; nIndex < m_arrCharstrings.GetSize(); nIndex++ )
{
CString sG = m_arrCharstrings[nIndex].sGlyph;
if ( _T("afii10090") == sG )
int k = 10;
arrType2Charstrings.Add( FlattenCharstring( m_arrCharstrings[nIndex].oData, nBias ) );
}
CSimpleArray<Type1Charstring> arrType2Subrs;
//Type1Charstring oBias;
////oBias.arrCharstring.Add( Type1CharstringItem( 0x0B, FALSE ) );
//oBias.arrCharstring.Add( Type1CharstringItem( 0x0E, FALSE ) );
//for ( int nIndex = 0; nIndex < nBias; nIndex++ )
// arrType2Subrs.Add( oBias );
for ( int nIndex = 0; nIndex < nSubrsLen; nIndex++ )
{
//if ( nIndex == 256 )
//{
// Type1Charstring oBias;
// oBias.arrCharstring.Add( Type1CharstringItem( 0x0B, FALSE ) );
// for ( int nIndex = 0; nIndex < nBias; nIndex++ )
// arrType2Subrs.Add( oBias );
//}
arrType2Subrs.Add( FlattenCharstring( m_arrSubrs[nIndex], 0 ) );
}
// Header
TCharBuffer oHeader;
oHeader.Write( "\x01\x00\x04\x04", 4 );
// Name
TCharBuffer oName;
aString.RemoveAll();
aString.Add( sFontName );
CFFCreateIndexHeader( CharBufferWrite, &oName, aString );
// Strings
TCharBuffer oStrings;
aString.RemoveAll();
int nNewSID = CFF_STANDARD_STRINGS_COUNT;
aString.Add( _T("Version 0.11") ); nNewSID++; // Version
aString.Add( _T("See original notice") ); nNewSID++; // Notice
aString.Add( sFontName ); nNewSID++; // FullName
aString.Add( sFontName ); nNewSID++; // FamilyName
aString.Add( _T("Medium") ); nNewSID++; // Weight
for ( int nIndex = 0; nIndex < m_arrCharstrings.GetSize(); nIndex++ )
{
int nSID = GetCFFStringIndex( m_arrCharstrings[nIndex].sGlyph.GetBuffer() );
if ( nSID < 0 )
{
aString.Add( m_arrCharstrings[nIndex].sGlyph );
nSID = nNewSID;
nNewSID++;
}
m_arrCharstrings[nIndex].nReserved = nSID;
}
CFFCreateIndexHeader( CharBufferWrite, &oStrings, aString );
// GlobalSubrs
TCharBuffer oGlobalSubrs;
aString.RemoveAll(); // Записываем пустой массив
CFFCreateIndexHeader( CharBufferWrite, &oGlobalSubrs, aString );
// Charset
TCharBuffer oCharset;
oCharset.Write( (char)0x00 ); // Encoding
int nGlyphsCount = m_arrCharstrings.GetSize();
for ( int nIndex = 0; nIndex < nGlyphsCount; nIndex++ )
{
int nSID = m_arrCharstrings[nIndex].nReserved;
oCharset.Write( (char)(nSID >> 8) );
oCharset.Write( (char)(nSID & 0xFF) );
}
// Charstrings
TCharBuffer oCharstrings;
CFFCreateIndexHeader( CharBufferWrite, &oCharstrings, arrType2Charstrings );
// Private
TCharBuffer oPrivate;
oPrivate.Write( "\x8b\x14", 2 ); // defaultWidth
oPrivate.Write( "\x8b\x15", 2 ); // nominalWidth
// Private: BlueValues
if ( m_oPrivateDict.nBlueValues > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnBlueValues[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nBlueValues; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnBlueValues[nIndex] - m_oPrivateDict.arrnBlueValues[nIndex - 1] );
oPrivate.Write( (char)0x06 );
}
// Private: OtherBlues
if ( m_oPrivateDict.nOtherBlues > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnOtherBlues[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nOtherBlues; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnOtherBlues[nIndex] - m_oPrivateDict.arrnOtherBlues[nIndex - 1] );
oPrivate.Write( (char)0x07 );
}
// Private: FamilyBlues
if ( m_oPrivateDict.nFamilyBlues > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnFamilyBlues[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nFamilyBlues; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnFamilyBlues[nIndex] - m_oPrivateDict.arrnFamilyBlues[nIndex - 1] );
oPrivate.Write( (char)0x08 );
}
// Private: FamilyOtherBlues
if ( m_oPrivateDict.nFamilyOtherBlues > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnFamilyOtherBlues[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nFamilyOtherBlues; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrnFamilyOtherBlues[nIndex] - m_oPrivateDict.arrnFamilyOtherBlues[nIndex - 1] );
oPrivate.Write( (char)0x09 );
}
// Private: StemSnapH
if ( m_oPrivateDict.nStemSnapH > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrdStemSnapH[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nStemSnapH; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrdStemSnapH[nIndex] - m_oPrivateDict.arrdStemSnapH[nIndex - 1] );
oPrivate.Write( "\x0c\x0c" , 2);
}
// Private: StemSnapV
if ( m_oPrivateDict.nStemSnapV > 0 )
{
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrdStemSnapV[0] );
for ( int nIndex = 1; nIndex < m_oPrivateDict.nStemSnapV; nIndex++ )
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.arrdStemSnapV[nIndex] - m_oPrivateDict.arrdStemSnapV[nIndex - 1] );
oPrivate.Write( "\x0c\x0d" , 2);
}
// Private: BlueShift
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.nBlueShift );
oPrivate.Write( "\x0c\x0a", 2 );
// Private: BlueFuzz
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.nBlueFuzz );
oPrivate.Write( "\x0c\x0b", 2 );
// Private: BlueScale
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.dBlueScale );
oPrivate.Write( "\x0c\x09", 2 );
// Private: LanguageGroup
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.nLanguageGroup );
oPrivate.Write( "\x0c\x11", 2 );
// Private: ExpansionFactor
CFFEncodeNumber( CharBufferWrite, &oPrivate, m_oPrivateDict.dExpansionFactor );
oPrivate.Write( "\x0c\x18", 2 );
// Private: Subrs
int nPrivateLen = oPrivate.nLen + (5 + 1);
CFFEncodeNumber( CharBufferWrite, &oPrivate, nPrivateLen, true );
oPrivate.Write( "\x13", 1 );
// LocalSubrs
TCharBuffer oLocalSubrs;
CFFCreateIndexHeader( CharBufferWrite, &oLocalSubrs, arrType2Subrs );
// Top Dict
TCharBuffer oTopDict;
oTopDict.Write( "\x00\x01\x04\x00\x00\x00\x01\x00\x00\0x00\x00", 11 );
oTopDict.Write( "\xf8\x1b\x00", 3 ); // Version
oTopDict.Write( "\xf8\x1c\x01", 3 ); // Notice
oTopDict.Write( "\xf8\x1d\x02", 3 ); // FullName
oTopDict.Write( "\xf8\x1e\x03", 3 ); // FamilyName
oTopDict.Write( "\xf8\x1f\x04", 3 ); // Weight
oTopDict.Write( "\x1c\x00\x00\x10", 4 ); // Encoding
// BBox
CFFEncodeNumber( CharBufferWrite, &oTopDict, m_oTopDict.arrdFontBBox[0] );
CFFEncodeNumber( CharBufferWrite, &oTopDict, m_oTopDict.arrdFontBBox[1] );
CFFEncodeNumber( CharBufferWrite, &oTopDict, m_oTopDict.arrdFontBBox[2] );
CFFEncodeNumber( CharBufferWrite, &oTopDict, m_oTopDict.arrdFontBBox[3] );
oTopDict.Write( "\x05", 1 );
// Теперь оценим размер TopDict: Возьмем текущую длину, добавим к ней (4 * 5 + 3)
// ( 4 числа, которые пишем по 5 байт + 3 байта на 3 команды)
int nTopDictLen = oTopDict.nLen + ( 4 * 5 + 3);
int nOffset = oHeader.nLen + oName.nLen + nTopDictLen + oStrings.nLen + oGlobalSubrs.nLen;
CFFEncodeNumber( CharBufferWrite, &oTopDict, nOffset, true );
oTopDict.Write( "\x0f", 1 ); // Charset
nOffset += oCharset.nLen;//( arrType2Charstrings.GetSize() * 2 ) + 1;
CFFEncodeNumber( CharBufferWrite, &oTopDict, nOffset, true );
oTopDict.Write( "\x11", 1 ); // Charstrings
CFFEncodeNumber( CharBufferWrite, &oTopDict, oPrivate.nLen, true );
nOffset += oCharstrings.nLen;
CFFEncodeNumber( CharBufferWrite, &oTopDict, nOffset, true );
oTopDict.Write( "\x12", 1 ); // Private
// Теперь запишем реальный размер TopDict
int nTopDictDataLen = nTopDictLen - 10;
oTopDict.sBuffer[7] = ( nTopDictDataLen >> 24 ) & 0xFF;
oTopDict.sBuffer[8] = ( nTopDictDataLen >> 16 ) & 0xFF;
oTopDict.sBuffer[9] = ( nTopDictDataLen >> 8 ) & 0xFF;
oTopDict.sBuffer[10] = nTopDictDataLen & 0xFF;
// Записываем все в файл
pOutputFunc( pOutputStream, oHeader.sBuffer, oHeader.nLen );
pOutputFunc( pOutputStream, oName.sBuffer, oName.nLen );
pOutputFunc( pOutputStream, oTopDict.sBuffer, oTopDict.nLen );
pOutputFunc( pOutputStream, oStrings.sBuffer, oStrings.nLen );
pOutputFunc( pOutputStream, oGlobalSubrs.sBuffer, oGlobalSubrs.nLen );
pOutputFunc( pOutputStream, oCharset.sBuffer, oCharset.nLen );
pOutputFunc( pOutputStream, oCharstrings.sBuffer, oCharstrings.nLen );
pOutputFunc( pOutputStream, oPrivate.sBuffer, oPrivate.nLen );
pOutputFunc( pOutputStream, oLocalSubrs.sBuffer, oLocalSubrs.nLen );
}
\ No newline at end of file
#ifndef _FONT_FILE_TYPE1_H
#define _FONT_FILE_TYPE1_H
#ifndef _ASC_FONTCONVERTER_FONT_FILE_TYPE1_H
#define _ASC_FONTCONVERTER_FONT_FILE_TYPE1_H
#include "Utils.h"
#include "FontFileBase.h"
#include "FontFileEncodings.h"
#include "../../common/Array.h"
#define type1MaxBlueValues 14 // 7 пар
#define type1MaxOtherBlues 10 // 5 пар
#define type1MaxStemSnap 12
struct Type1PrivateDict
{
int arrnBlueValues[type1MaxBlueValues];
int nBlueValues;
int arrnOtherBlues[type1MaxOtherBlues];
int nOtherBlues;
int arrnFamilyBlues[type1MaxBlueValues];
int nFamilyBlues;
int arrnFamilyOtherBlues[type1MaxOtherBlues];
int nFamilyOtherBlues;
double dBlueScale;
int nBlueShift;
int nBlueFuzz;
double dStdHW;
BOOL bHasStdHW;
double dStdVW;
BOOL bHasStdVW;
double arrdStemSnapH[type1MaxStemSnap];
int nStemSnapH;
double arrdStemSnapV[type1MaxStemSnap];
int nStemSnapV;
BOOL bHasForceBold;
BOOL bForceBold;
int nLanguageGroup;
int nLenIV;
double dExpansionFactor;
};
struct Type1TopDict
{
// TO DO: дополнить данную структуру
double arrdFontMatrix[6];
double arrdFontBBox[4];
};
// команды
const int c_nType1hstem = 0x0001; // 'hstem'
const int c_nType1vstem = 0x0003; // 'vstem'
const int c_nType1vmoveto = 0x0004; // 'vmoveto'
const int c_nType1rlineto = 0x0005; // 'rlineto'
const int c_nType1hlineto = 0x0006; // 'hlineto'
const int c_nType1vlineto = 0x0007; // 'vlineto'
const int c_nType1rrcurveto = 0x0008; // 'rrcurveto'
const int c_nType1closepath = 0x0009; // 'closepath' не используется в Type2
const int c_nType1callsubr = 0x000A; // 'callsubr
const int c_nType1return = 0x000B; // 'return'
const int c_nType1dotsection = 0x000C; // 'dotsection' не используется в Type2
const int c_nType1vstem3 = 0x010C; // 'vstem'
const int c_nType1hstem3 = 0x020C; // 'hstem'
const int c_nType1seac = 0x060C; // 'seac' Type1 only
const int c_nType1sbw = 0x070C; // 'sbw' Type1 only
const int c_nType1sub = 0x0B0C; // 'sub'
const int c_nType1div = 0x0C0C; // 'div'
const int c_nType1callothersubr = 0x100C; // 'callothersubr'
const int c_nType1pop = 0x110C; // 'pop'
const int c_nType1setcurrentpoint = 0x210C; // 'setcurrentpoint' не используется в Type2
const int c_nType1hsbw = 0x000D; // 'hsbw'
const int c_nType1endchar = 0x000E; // 'endchar'
const int c_nType1rmoveto = 0x0015; // 'rmoveto'
const int c_nType1hmoveto = 0x0016; // 'hmoveto'
const int c_nType1vhcurveto = 0x001E; // 'vhcurveto'
const int c_nType1hvcurveto = 0x001F; // 'hvcurveto'
struct Type1CharstringItem
{
int nValue; // Значение
BOOL bCommand; // TRUE: значение - номер команды, FALSE: значение - параметр команды
Type1CharstringItem(int nVal, BOOL bCom)
{
nValue = nVal;
bCommand = bCom;
}
};
struct Type1Charstring
namespace NSFontConverter
{
CSimpleArray<Type1CharstringItem> arrCharstring;
int nWidth;
int nLSB;
Type1Charstring()
{
nWidth = 0;
nLSB = 0;
}
Type1Charstring(CSimpleArray<Type1CharstringItem> &arrCs, int nW, int nL)
{
arrCharstring = arrCs;
nWidth = nW;
nLSB = nL;
}
};
struct Type1Glyph
{
CString sGlyph; // Type1 имя глифа
int nUnicode; // Юникодное значение глифа
Type1Charstring oData;
int nReserved; // Используем для SID при конвертации Type1->Type2
Type1Glyph(CString& sGlyf, int nUni, Type1Charstring &oCharstring)
{
sGlyph = sGlyf;
nUnicode = nUni;
oData = oCharstring;
nReserved = 0;
}
};
static int CompareType1Glyph(const void *pGlyph1, const void *pGlyph2)
{
Type1Glyph *pGlyf1 = (Type1Glyph *)pGlyph1;
Type1Glyph *pGlyf2 = (Type1Glyph *)pGlyph2;
return pGlyf1->nUnicode - pGlyf2->nUnicode;
#define type1MaxBlueValues 14 // 7 пар
#define type1MaxOtherBlues 10 // 5 пар
#define type1MaxStemSnap 12
struct Type1PrivateDict
{
int arrnBlueValues[type1MaxBlueValues];
int nBlueValues;
int arrnOtherBlues[type1MaxOtherBlues];
int nOtherBlues;
int arrnFamilyBlues[type1MaxBlueValues];
int nFamilyBlues;
int arrnFamilyOtherBlues[type1MaxOtherBlues];
int nFamilyOtherBlues;
double dBlueScale;
int nBlueShift;
int nBlueFuzz;
double dStdHW;
bool bHasStdHW;
double dStdVW;
bool bHasStdVW;
double arrdStemSnapH[type1MaxStemSnap];
int nStemSnapH;
double arrdStemSnapV[type1MaxStemSnap];
int nStemSnapV;
bool bHasForceBold;
bool bForceBold;
int nLanguageGroup;
int nLenIV;
double dExpansionFactor;
};
struct Type1TopDict
{
// TO DO: дополнить данную структуру
double arrdFontMatrix[6];
double arrdFontBBox[4];
};
// команды
const int c_nType1hstem = 0x0001; // 'hstem'
const int c_nType1vstem = 0x0003; // 'vstem'
const int c_nType1vmoveto = 0x0004; // 'vmoveto'
const int c_nType1rlineto = 0x0005; // 'rlineto'
const int c_nType1hlineto = 0x0006; // 'hlineto'
const int c_nType1vlineto = 0x0007; // 'vlineto'
const int c_nType1rrcurveto = 0x0008; // 'rrcurveto'
const int c_nType1closepath = 0x0009; // 'closepath' не используется в Type2
const int c_nType1callsubr = 0x000A; // 'callsubr
const int c_nType1return = 0x000B; // 'return'
const int c_nType1dotsection = 0x000C; // 'dotsection' не используется в Type2
const int c_nType1vstem3 = 0x010C; // 'vstem'
const int c_nType1hstem3 = 0x020C; // 'hstem'
const int c_nType1seac = 0x060C; // 'seac' Type1 only
const int c_nType1sbw = 0x070C; // 'sbw' Type1 only
const int c_nType1sub = 0x0B0C; // 'sub'
const int c_nType1div = 0x0C0C; // 'div'
const int c_nType1callothersubr = 0x100C; // 'callothersubr'
const int c_nType1pop = 0x110C; // 'pop'
const int c_nType1setcurrentpoint = 0x210C; // 'setcurrentpoint' не используется в Type2
const int c_nType1hsbw = 0x000D; // 'hsbw'
const int c_nType1endchar = 0x000E; // 'endchar'
const int c_nType1rmoveto = 0x0015; // 'rmoveto'
const int c_nType1hmoveto = 0x0016; // 'hmoveto'
const int c_nType1vhcurveto = 0x001E; // 'vhcurveto'
const int c_nType1hvcurveto = 0x001F; // 'hvcurveto'
struct Type1CharstringItem
{
int nValue; // Значение
bool bCommand; // TRUE: значение - номер команды, FALSE: значение - параметр команды
Type1CharstringItem(int nVal, bool bCom)
{
nValue = nVal;
bCommand = bCom;
}
Type1CharstringItem()
{
nValue = 0;
bCommand = false;
}
};
struct Type1Charstring
{
CArray<Type1CharstringItem> arrCharstring;
int nWidth;
int nLSB;
Type1Charstring()
{
nWidth = 0;
nLSB = 0;
}
Type1Charstring(CArray<Type1CharstringItem> &arrCs, int nW, int nL)
{
arrCharstring = arrCs;
nWidth = nW;
nLSB = nL;
}
};
struct Type1Glyph
{
std::wstring sGlyph; // Type1 имя глифа
int nUnicode; // Юникодное значение глифа
Type1Charstring oData;
int nReserved; // Используем для SID при конвертации Type1->Type2
Type1Glyph(std::wstring& sGlyf, int nUni, Type1Charstring &oCharstring)
{
sGlyph = sGlyf;
nUnicode = nUni;
oData = oCharstring;
nReserved = 0;
}
Type1Glyph()
{
nUnicode = 0;
nReserved = 0;
}
};
static int CompareType1Glyph(const void *pGlyph1, const void *pGlyph2)
{
Type1Glyph *pGlyf1 = (Type1Glyph *)pGlyph1;
Type1Glyph *pGlyf2 = (Type1Glyph *)pGlyph2;
return pGlyf1->nUnicode - pGlyf2->nUnicode;
}
//------------------------------------------------------------------------
// CFontFileType1
//------------------------------------------------------------------------
class CFontFileType1: public CFontFileBase
{
public:
static CFontFileType1 *LoadFromBuffer(char *sBuffer, int nLen);
static CFontFileType1 *LoadFromFile(const wchar_t *wsFileName);
virtual ~CFontFileType1();
char *GetName();
char **GetEncoding();
void WriteEncoded(char **ppNewEncoding, FontFileOutputFunc pOutputFunc, void *pOutputStream);
void ToCFF(FontFileOutputFunc pOutputFunc, void *pOutputStream);
private:
CFontFileType1(char *sBuffer, int nLen, bool bFreeData);
void Parse();
void DecryptEexec(unsigned char** ppEexecBuffer, int nLen);
Type1Charstring DecodeCharString(unsigned char *sString, int nLen);
char *GetNextLine(char *sLine);
bool RemovePfbMarkers();
template<int nMax>
int ReadDoubleArray(unsigned char *sString, int nLen, double (&pArray)[nMax])
{
int nStart = 0;
while( sString[nStart] != '[' )
{
nStart++;
if ( nStart >= nLen )
return 0;
}
int nEnd = ++nStart;
while ( sString[nEnd] != ']' )
{
nEnd++;
if ( nEnd >= nLen )
return 0;
}
sString = sString + nStart;
nLen = nEnd - nStart;
int nCount = 0;
const int c_nNumLimit = 32;
unsigned char sBuffer[c_nNumLimit];
int nBufPos = 0;
bool bNewItem = true;
for ( int nIndex = 0; nIndex < nLen; ++nIndex )
{
unsigned char unChar = sString[nIndex];
if ( ' ' == unChar )
{
if ( !bNewItem )
bNewItem = true;
continue;
}
if ( bNewItem )
{
if ( nCount >= nMax )
break;
// Добавляем предыдущее число в массив
if ( nCount > 0 )
pArray[nCount - 1] = Utils::GetDouble( (const char *)sBuffer );
memset( sBuffer, 0x00, c_nNumLimit );
nBufPos = 0;
bNewItem = false;
nCount++;
}
sBuffer[nBufPos++] = unChar;
}
if ( 0 != sBuffer[0] && nCount > 0 )
pArray[nCount - 1] = Utils::GetDouble( (const char *)sBuffer );
return nCount;
}
template<int nMax>
int ReadIntArray (unsigned char *sString, int nLen, int (&pArray)[nMax])
{
int nStart = 0;
while( sString[nStart] != '[' )
{
nStart++;
if ( nStart >= nLen )
return 0;
}
int nEnd = ++nStart;
while ( sString[nEnd] != ']' )
{
nEnd++;
if ( nEnd >= nLen )
return 0;
}
sString = sString + nStart;
nLen = nEnd - nStart;
int nCount = 0;
const int c_nNumLimit = 32;
unsigned char sBuffer[c_nNumLimit];
int nBufPos = 0;
bool bNewItem = true;
for ( int nIndex = 0; nIndex < nLen; ++nIndex )
{
unsigned char unChar = sString[nIndex];
if ( ' ' == unChar )
{
if ( !bNewItem )
bNewItem = true;
continue;
}
if ( bNewItem )
{
if ( nCount >= nMax )
break;
// Добавляем предыдущее число в массив
if ( nCount > 0 )
pArray[nCount - 1] = Utils::GetInteger( (const char *)sBuffer );
memset( sBuffer, 0x00, c_nNumLimit );
nBufPos = 0;
bNewItem = false;
nCount++;
}
sBuffer[nBufPos++] = unChar;
}
if ( 0 != sBuffer[0] && nCount > 0 )
pArray[nCount - 1] = Utils::GetInteger( (const char *)sBuffer );
return nCount;
}
double ReadDouble (unsigned char *sString, int nMaxLen)
{
// Смещаемся к первому пробелу (после него идет значение)
int nPos = 0;
while ( ' ' == sString[nPos] && nPos < nMaxLen )
nPos++;
return Utils::GetDouble( (const char*)( sString + nPos ) );
}
int ReadInt (unsigned char *sString, int nMaxLen)
{
int nPos = 0;
while ( ' ' == sString[nPos] && nPos < nMaxLen )
nPos++;
return Utils::GetInteger( (const char*)( sString + nPos ) );
}
bool ReadBool (unsigned char *sString, int nMaxLen)
{
int nStartPos = 0;
while ( ' ' == sString[nStartPos] && nStartPos < nMaxLen )
nStartPos++;
if ( nStartPos >= nMaxLen - 4 )
return false;
if ( 't' == sString[nStartPos + 0] &&
'r' == sString[nStartPos + 1] &&
'u' == sString[nStartPos + 2] &&
'e' == sString[nStartPos + 3] )
return true;
return false;
}
Type1Charstring FlattenCharstring(Type1Charstring& oCharstring, int nBias = 0);
void CFFCreateIndexHeader(FontFileOutputFunc pOutputFunc, void *pOutputStream, CArray<std::wstring> aObjects);
void CFFCreateIndexHeader(FontFileOutputFunc pOutputFunc, void *pOutputStream, CArray<Type1Charstring> aObjects);
void CFFEncodeNumber (FontFileOutputFunc pOutputFunc, void *pOutputStream, int nValue, bool bForceLong = false);
void CFFEncodeNumber (FontFileOutputFunc pOutputFunc, void *pOutputStream, double dValue);
private:
char *m_sName;
char **m_arrEncoding;
bool m_bParsed;
Type1PrivateDict m_oPrivateDict;
Type1TopDict m_oTopDict;
CArray<Type1Glyph> m_arrCharstrings;
CArray<Type1Charstring> m_arrSubrs;
};
}
//------------------------------------------------------------------------
// CFontFileType1
//------------------------------------------------------------------------
class CFontFileType1: public CFontFileBase
{
public:
static CFontFileType1 *LoadFromBuffer(char *sBuffer, int nLen);
static CFontFileType1 *LoadFromFile(wchar_t *wsFileName);
virtual ~CFontFileType1();
char *GetName();
char **GetEncoding();
void WriteEncoded(char **ppNewEncoding, FontFileOutputFunc pOutputFunc, void *pOutputStream);
void ToCFF(FontFileOutputFunc pOutputFunc, void *pOutputStream);
private:
CFontFileType1(char *sBuffer, int nLen, BOOL bFreeData);
void Parse();
void DecryptEexec(unsigned char** ppEexecBuffer, int nLen);
Type1Charstring DecodeCharString(unsigned char *sString, int nLen);
char *GetNextLine(char *sLine);
bool RemovePfbMarkers();
template<int nMax>
int ReadDoubleArray(unsigned char *sString, int nLen, double (&pArray)[nMax])
{
int nStart = 0;
while( sString[nStart] != '[' )
{
nStart++;
if ( nStart >= nLen )
return 0;
}
int nEnd = ++nStart;
while ( sString[nEnd] != ']' )
{
nEnd++;
if ( nEnd >= nLen )
return 0;
}
sString = sString + nStart;
nLen = nEnd - nStart;
int nCount = 0;
const int c_nNumLimit = 32;
unsigned char sBuffer[c_nNumLimit];
int nBufPos = 0;
bool bNewItem = true;
for ( int nIndex = 0; nIndex < nLen; ++nIndex )
{
unsigned char unChar = sString[nIndex];
if ( ' ' == unChar )
{
if ( !bNewItem )
bNewItem = true;
continue;
}
if ( bNewItem )
{
if ( nCount >= nMax )
break;
// Добавляем предыдущее число в массив
if ( nCount > 0 )
pArray[nCount - 1] = Utils::GetDouble( (const char *)sBuffer );
memset( sBuffer, 0x00, c_nNumLimit );
nBufPos = 0;
bNewItem = false;
nCount++;
}
sBuffer[nBufPos++] = unChar;
}
if ( 0 != sBuffer[0] && nCount > 0 )
pArray[nCount - 1] = Utils::GetDouble( (const char *)sBuffer );
return nCount;
}
template<int nMax>
int ReadIntArray (unsigned char *sString, int nLen, int (&pArray)[nMax])
{
int nStart = 0;
while( sString[nStart] != '[' )
{
nStart++;
if ( nStart >= nLen )
return 0;
}
int nEnd = ++nStart;
while ( sString[nEnd] != ']' )
{
nEnd++;
if ( nEnd >= nLen )
return 0;
}
sString = sString + nStart;
nLen = nEnd - nStart;
int nCount = 0;
const int c_nNumLimit = 32;
unsigned char sBuffer[c_nNumLimit];
int nBufPos = 0;
bool bNewItem = true;
for ( int nIndex = 0; nIndex < nLen; ++nIndex )
{
unsigned char unChar = sString[nIndex];
if ( ' ' == unChar )
{
if ( !bNewItem )
bNewItem = true;
continue;
}
if ( bNewItem )
{
if ( nCount >= nMax )
break;
// Добавляем предыдущее число в массив
if ( nCount > 0 )
pArray[nCount - 1] = Utils::GetInteger( (const char *)sBuffer );
memset( sBuffer, 0x00, c_nNumLimit );
nBufPos = 0;
bNewItem = false;
nCount++;
}
sBuffer[nBufPos++] = unChar;
}
if ( 0 != sBuffer[0] && nCount > 0 )
pArray[nCount - 1] = Utils::GetInteger( (const char *)sBuffer );
return nCount;
}
double ReadDouble (unsigned char *sString, int nMaxLen)
{
// Смещаемся к первому пробелу (после него идет значение)
int nPos = 0;
while ( ' ' == sString[nPos] && nPos < nMaxLen )
nPos++;
return Utils::GetDouble( (const char*)( sString + nPos ) );
}
int ReadInt (unsigned char *sString, int nMaxLen)
{
int nPos = 0;
while ( ' ' == sString[nPos] && nPos < nMaxLen )
nPos++;
return Utils::GetInteger( (const char*)( sString + nPos ) );
}
BOOL ReadBool (unsigned char *sString, int nMaxLen)
{
int nStartPos = 0;
while ( ' ' == sString[nStartPos] && nStartPos < nMaxLen )
nStartPos++;
if ( nStartPos >= nMaxLen - 4 )
return FALSE;
if ( 't' == sString[nStartPos + 0] &&
'r' == sString[nStartPos + 1] &&
'u' == sString[nStartPos + 2] &&
'e' == sString[nStartPos + 3] )
return TRUE;
return FALSE;
}
Type1Charstring FlattenCharstring(Type1Charstring& oCharstring, int nBias = 0);
void CFFCreateIndexHeader(FontFileOutputFunc pOutputFunc, void *pOutputStream, CSimpleArray<CString> aObjects);
void CFFCreateIndexHeader(FontFileOutputFunc pOutputFunc, void *pOutputStream, CSimpleArray<Type1Charstring> aObjects);
void CFFEncodeNumber (FontFileOutputFunc pOutputFunc, void *pOutputStream, int nValue, bool bForceLong = false);
void CFFEncodeNumber (FontFileOutputFunc pOutputFunc, void *pOutputStream, double dValue);
private:
char *m_sName;
char **m_arrEncoding;
BOOL m_bParsed;
Type1PrivateDict m_oPrivateDict;
Type1TopDict m_oTopDict;
CSimpleArray<Type1Glyph> m_arrCharstrings;
CSimpleArray<Type1Charstring> m_arrSubrs;
};
#endif /* _FONT_FILE_TYPE1_H */
#endif /* _ASC_FONTCONVERTER_FONT_FILE_TYPE1_H */
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef _FONT_FILE_TYPE1C_H
#define _FONT_FILE_TYPE1C_H
#ifndef _ASC_FONTCONVERTER_FONT_FILE_TYPE1C_H
#define _ASC_FONTCONVERTER_FONT_FILE_TYPE1C_H
#include "FontFileBase.h"
#include "Utils.h"
class StringExt;
//------------------------------------------------------------------------
struct Type1CIndex
{
int nPos; // Позиция в файле от начала файла
int nCount; // Количество вхождений
int nOffsetSize; // Offset size
int nStartPos; // Начальная позиция index data - 1
int nEndPos; // Позиция следующего байта после Type1CIndex
};
struct Type1CIndexVal
{
int nPos; // Позиция в файле от начала файла
int nLen; // Длина в байтах
};
struct Type1CTopDict
{
int nFirstOperator;
int nVersionSID;
int nNoticeSID;
int nCopyrightSID;
int nFullNameSID;
int nFamilyNameSID;
int nWeightSID;
int nIsFixedPitch;
double dItalicAngle;
double dUnderlinePosition;
double dUnderlineThickness;
int nPaintType;
int nCharStringType;
double arrdFontMatrix[6];
BOOL bHasFontMatrix; // В CID фонтах возможно матрица фонта лежит в FD, а не в верхнем словаре
int nUniqueID;
double arrdFontBBox[4];
double dStrokeWidth;
int nCharsetOffset;
int nEncodingOffset;
int nCharStringsOffset;
int nPrivateSize;
int nPrivateOffset;
// CIDFont entries
int nRegistrySID;
int nOrderingSID;
int nSupplement;
int nFDArrayOffset;
int nFDSelectOffset;
};
#define type1CMaxBlueValues 14
#define type1CMaxOtherBlues 10
#define type1CMaxStemSnap 12
struct Type1CPrivateDict
{
double arrdFontMatrix[6];
BOOL bHasFontMatrix;
int arrnBlueValues[type1CMaxBlueValues];
int nBlueValues;
int arrnOtherBlues[type1CMaxOtherBlues];
int nOtherBlues;
int arrnFamilyBlues[type1CMaxBlueValues];
int nFamilyBlues;
int arrnFamilyOtherBlues[type1CMaxOtherBlues];
int nFamilyOtherBlues;
double dBlueScale;
int nBlueShift;
int nBlueFuzz;
double dStdHW;
BOOL bHasStdHW;
double dStdVW;
BOOL bHasStdVW;
double arrdStemSnapH[type1CMaxStemSnap];
int nStemSnapH;
double arrdStemSnapV[type1CMaxStemSnap];
int nStemSnapV;
BOOL bForceBold;
BOOL bHasForceBold;
double dForceBoldThreshold;
int nLanguageGroup;
double dExpansionFactor;
int nInitialRandomSeed;
int nSubrsOffset;
double dDefaultWidthX;
BOOL bDefaultWidthXFP;
double dNominalWidthX;
BOOL bNominalWidthXFP;
};
struct Type1COperator
{
BOOL bIsNumber; // true -> number, false -> operator
BOOL bIsFloat; // true -> floating point number, false -> int
union
{
double dNumber;
int nOperator;
};
};
struct Type1CEexecBuf
{
FontFileOutputFunc pOutputFunc;
void *pOutputStream;
BOOL bASKII; // ASCII кодировка?
unsigned short unEncryptionKey; // eexec encryption key
int nLine; // количество eexec-символов, оставшихся на текущей строке
};
//------------------------------------------------------------------------
// CFontFileType1C
//------------------------------------------------------------------------
class CFontFileType1C: public CFontFileBase
{
public:
static CFontFileType1C *LoadFromBuffer(char *sBuffer, int nLen);
static CFontFileType1C *LoadFromFile(wchar_t *wsFileName);
virtual ~CFontFileType1C();
char *GetName();
// Возвращаем кодировку, как массив 256 имен (некоторые могут быть
// NULL). Используется только для 8-битных фонтов.
char **GetEncoding();
unsigned short *GetCIDToGIDMap(int *arrCIDs);
// Convert to a Type 1 font, suitable for embedding in a PostScript
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
// otherwise it will be left as binary data. If <psName> is non-NULL,
// it will be used as the PostScript font name.
void ToType1(char *sPSName, char **ppNewEncoding, BOOL bASKII, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name.
void ToCIDType0(char *sPSName, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name.
void ToType0(char *sPSName, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Конвертируем в OpenType (CFF)
void ToOpenTypeCFF(FontFileOutputFunc pOutputFunc, void *pOutputStream, FT_Face pFace);
private:
CFontFileType1C(char *sBuffer, int nLen, BOOL bFreeData);
void EexecConvertGlyph(Type1CEexecBuf *pEexecBuf, char *sGlyphName, int nOffset, int nBytes, Type1CIndex *pSubrIndex, Type1CPrivateDict *pDict);
void ConvertGlyph(int nOffset, int nBytes, StringExt *seCharBuffer, Type1CIndex *pSubrIndex, Type1CPrivateDict *pDict, BOOL bTop);
void ConvertGlyphWidth(BOOL bUseOperation, StringExt *seCharBuffer, Type1CPrivateDict *pDict);
void ConvertNum(double dValue, BOOL bIsFloat, StringExt *seCharBuffer);
void EexecWrite(Type1CEexecBuf *pEexecBuf, char *sBuffer);
void EexecWriteCharString(Type1CEexecBuf *pEexecBuf, unsigned char *sBuffer, int nLen);
BOOL Parse();
void ReadTopDict();
void ReadFD(int nOffset, int nLength, Type1CPrivateDict *pDict);
void ReadPrivateDict(int nOffset, int nLength, Type1CPrivateDict *pDict);
void ReadFDSelect();
void BuildEncoding();
BOOL ReadCharset();
int GetOperator(int nPos, BOOL bCharString, BOOL *pbSuccess);
int GetDeltaIntArray(int *pArray, int nMaxLen);
int GetDeltaDoubleArray(double *pArray, int nMaxLen);
void GetIndex(int nPos, Type1CIndex *pIndex, BOOL *pbSuccess);
void GetIndexVal(Type1CIndex *pIndex, int nIndex, Type1CIndexVal *pIndexVal, BOOL *bSuccess);
char *GetString(int nSID, char *sBuffer, BOOL *pbSuccess);
unsigned int ComputeTTTableChecksum(unsigned char *sData, int nLength)
namespace NSFontConverter
{
unsigned int nWord = 0;
unsigned int nChecksum = 0;
for ( int nIndex = 0; nIndex + 3 < nLength; nIndex += 4 )
{
nWord = ( ( sData[ nIndex ] & 0xff) << 24) + ((sData[ nIndex + 1 ] & 0xff) << 16) + ((sData[ nIndex + 2 ] & 0xff) << 8) + (sData[ nIndex + 3 ] & 0xff);
nChecksum += nWord;
}
if ( nLength & 3 )
{
nWord = 0;
int nTemp = nLength & ~3;
switch ( nLength & 3 )
{
case 3:
nWord |= (sData[nTemp + 2] & 0xff) << 8;
case 2:
nWord |= (sData[nTemp + 1] & 0xff) << 16;
case 1:
nWord |= (sData[nTemp] & 0xff) << 24;
break;
}
nChecksum += nWord;
}
return nChecksum;
class StringExt;
//------------------------------------------------------------------------
struct Type1CIndex
{
int nPos; // Позиция в файле от начала файла
int nCount; // Количество вхождений
int nOffsetSize; // Offset size
int nStartPos; // Начальная позиция index data - 1
int nEndPos; // Позиция следующего байта после Type1CIndex
};
struct Type1CIndexVal
{
int nPos; // Позиция в файле от начала файла
int nLen; // Длина в байтах
};
struct Type1CTopDict
{
int nFirstOperator;
int nVersionSID;
int nNoticeSID;
int nCopyrightSID;
int nFullNameSID;
int nFamilyNameSID;
int nWeightSID;
int nIsFixedPitch;
double dItalicAngle;
double dUnderlinePosition;
double dUnderlineThickness;
int nPaintType;
int nCharStringType;
double arrdFontMatrix[6];
bool bHasFontMatrix; // В CID фонтах возможно матрица фонта лежит в FD, а не в верхнем словаре
int nUniqueID;
double arrdFontBBox[4];
double dStrokeWidth;
int nCharsetOffset;
int nEncodingOffset;
int nCharStringsOffset;
int nPrivateSize;
int nPrivateOffset;
// CIDFont entries
int nRegistrySID;
int nOrderingSID;
int nSupplement;
int nFDArrayOffset;
int nFDSelectOffset;
};
#define type1CMaxBlueValues 14
#define type1CMaxOtherBlues 10
#define type1CMaxStemSnap 12
struct Type1CPrivateDict
{
double arrdFontMatrix[6];
bool bHasFontMatrix;
int arrnBlueValues[type1CMaxBlueValues];
int nBlueValues;
int arrnOtherBlues[type1CMaxOtherBlues];
int nOtherBlues;
int arrnFamilyBlues[type1CMaxBlueValues];
int nFamilyBlues;
int arrnFamilyOtherBlues[type1CMaxOtherBlues];
int nFamilyOtherBlues;
double dBlueScale;
int nBlueShift;
int nBlueFuzz;
double dStdHW;
bool bHasStdHW;
double dStdVW;
bool bHasStdVW;
double arrdStemSnapH[type1CMaxStemSnap];
int nStemSnapH;
double arrdStemSnapV[type1CMaxStemSnap];
int nStemSnapV;
bool bForceBold;
bool bHasForceBold;
double dForceBoldThreshold;
int nLanguageGroup;
double dExpansionFactor;
int nInitialRandomSeed;
int nSubrsOffset;
double dDefaultWidthX;
bool bDefaultWidthXFP;
double dNominalWidthX;
bool bNominalWidthXFP;
};
struct Type1COperator
{
bool bIsNumber; // true -> number, false -> operator
bool bIsFloat; // true -> floating point number, false -> int
union
{
double dNumber;
int nOperator;
};
};
struct Type1CEexecBuf
{
FontFileOutputFunc pOutputFunc;
void *pOutputStream;
bool bASKII; // ASCII кодировка?
unsigned short unEncryptionKey; // eexec encryption key
int nLine; // количество eexec-символов, оставшихся на текущей строке
};
//------------------------------------------------------------------------
// CFontFileType1C
//------------------------------------------------------------------------
class CFontFileType1C: public CFontFileBase
{
public:
static CFontFileType1C *LoadFromBuffer(char *sBuffer, int nLen);
static CFontFileType1C *LoadFromFile(const wchar_t *wsFileName);
virtual ~CFontFileType1C();
char *GetName();
// Возвращаем кодировку, как массив 256 имен (некоторые могут быть
// NULL). Используется только для 8-битных фонтов.
char **GetEncoding();
unsigned short *GetCIDToGIDMap(int *arrCIDs);
// Convert to a Type 1 font, suitable for embedding in a PostScript
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
// otherwise it will be left as binary data. If <psName> is non-NULL,
// it will be used as the PostScript font name.
void ToType1(char *sPSName, char **ppNewEncoding, bool bASKII, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name.
void ToCIDType0(char *sPSName, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name.
void ToType0(char *sPSName, FontFileOutputFunc pOutputFunc, void *pOutputStream);
// Конвертируем в OpenType (CFF)
void ToOpenTypeCFF(FontFileOutputFunc pOutputFunc, void *pOutputStream, FT_Face pFace);
private:
CFontFileType1C(char *sBuffer, int nLen, bool bFreeData);
void EexecConvertGlyph(Type1CEexecBuf *pEexecBuf, char *sGlyphName, int nOffset, int nBytes, Type1CIndex *pSubrIndex, Type1CPrivateDict *pDict);
void ConvertGlyph(int nOffset, int nBytes, StringExt *seCharBuffer, Type1CIndex *pSubrIndex, Type1CPrivateDict *pDict, bool bTop);
void ConvertGlyphWidth(bool bUseOperation, StringExt *seCharBuffer, Type1CPrivateDict *pDict);
void ConvertNum(double dValue, bool bIsFloat, StringExt *seCharBuffer);
void EexecWrite(Type1CEexecBuf *pEexecBuf, char *sBuffer);
void EexecWriteCharString(Type1CEexecBuf *pEexecBuf, unsigned char *sBuffer, int nLen);
bool Parse();
void ReadTopDict();
void ReadFD(int nOffset, int nLength, Type1CPrivateDict *pDict);
void ReadPrivateDict(int nOffset, int nLength, Type1CPrivateDict *pDict);
void ReadFDSelect();
void BuildEncoding();
bool ReadCharset();
int GetOperator(int nPos, bool bCharString, bool *pbSuccess);
int GetDeltaIntArray(int *pArray, int nMaxLen);
int GetDeltaDoubleArray(double *pArray, int nMaxLen);
void GetIndex(int nPos, Type1CIndex *pIndex, bool *pbSuccess);
void GetIndexVal(Type1CIndex *pIndex, int nIndex, Type1CIndexVal *pIndexVal, bool *bSuccess);
char *GetString(int nSID, char *sBuffer, bool *pbSuccess);
unsigned int ComputeTTTableChecksum(unsigned char *sData, int nLength)
{
unsigned int nWord = 0;
unsigned int nChecksum = 0;
for ( int nIndex = 0; nIndex + 3 < nLength; nIndex += 4 )
{
nWord = ( ( sData[ nIndex ] & 0xff) << 24) + ((sData[ nIndex + 1 ] & 0xff) << 16) + ((sData[ nIndex + 2 ] & 0xff) << 8) + (sData[ nIndex + 3 ] & 0xff);
nChecksum += nWord;
}
if ( nLength & 3 )
{
nWord = 0;
int nTemp = nLength & ~3;
switch ( nLength & 3 )
{
case 3:
nWord |= (sData[nTemp + 2] & 0xff) << 8;
case 2:
nWord |= (sData[nTemp + 1] & 0xff) << 16;
case 1:
nWord |= (sData[nTemp] & 0xff) << 24;
break;
}
nChecksum += nWord;
}
return nChecksum;
}
private:
StringExt *m_seName;
char **m_arrEncoding;
Type1CIndex m_oNameIndex;
Type1CIndex m_oTopDictIndex;
Type1CIndex m_oStringIndex;
Type1CIndex m_oGsubrIndex;
Type1CIndex m_oCharStringsIndex;
Type1CTopDict m_oTopDict;
Type1CPrivateDict *m_pPrivateDicts;
int m_nGlyphsCount;
int m_nFDsCount;
unsigned char *m_pnFDSelect;
unsigned short *m_pnCharset;
int m_nGsubrBias;
bool m_bSuccessParsed;
Type1COperator m_arrOperators[49];
int m_nOperatorsCount;
int m_nHints; // для текущего символа
bool m_bFirstOperator;
bool m_bOpenPath; // true, если есть незакрытый пат
};
}
private:
StringExt *m_seName;
char **m_arrEncoding;
Type1CIndex m_oNameIndex;
Type1CIndex m_oTopDictIndex;
Type1CIndex m_oStringIndex;
Type1CIndex m_oGsubrIndex;
Type1CIndex m_oCharStringsIndex;
Type1CTopDict m_oTopDict;
Type1CPrivateDict *m_pPrivateDicts;
int m_nGlyphsCount;
int m_nFDsCount;
unsigned char *m_pnFDSelect;
unsigned short *m_pnCharset;
int m_nGsubrBias;
BOOL m_bSuccessParsed;
Type1COperator m_arrOperators[49];
int m_nOperatorsCount;
int m_nHints; // для текущего символа
BOOL m_bFirstOperator;
BOOL m_bOpenPath; // true, если есть незакрытый пат
};
#endif /* _FONT_FILE_TYPE1C_H */
#endif /* _ASC_FONTCONVERTER_FONT_FILE_TYPE1C_H */
......@@ -2,6 +2,8 @@
#define _ASC_FONT_CONVERTER_MEMORY_UTILS_H_
#include <stdio.h>
#include <limits>
#include <string>
namespace NSFontConverter
{
......
......@@ -101,7 +101,7 @@ namespace NSFontConverter
StringExt::StringExt(const char *sSrc)
{
int nLen = strlen( sSrc );
int nLen = (int)strlen( sSrc );
m_sData = NULL;
Resize(m_nLength = nLen);
......@@ -148,7 +148,7 @@ namespace NSFontConverter
char *pData = NULL;
int nLen;
FormatInt( nValue, sBuffer, sizeof( sBuffer ), FALSE, 0, 10, &pData, &nLen);
FormatInt( nValue, sBuffer, sizeof( sBuffer ), false, 0, 10, &pData, &nLen);
return new StringExt( pData, nLen );
}
......@@ -231,7 +231,7 @@ namespace NSFontConverter
{
StringExtFormatArg uArg;
int nIndex, nWidth, nPrecision;
BOOL bReverseAlign, bZeroFill;
bool bReverseAlign, bZeroFill;
StringExtFormatType eFormatType;
char sBuffer[65];
int nLen;
......@@ -266,11 +266,11 @@ namespace NSFontConverter
++pCur;
if ( *pCur == '-' )
{
bReverseAlign = TRUE;
bReverseAlign = true;
++pCur;
}
else
bReverseAlign = FALSE;
bReverseAlign = false;
nWidth = 0;
bZeroFill = *pCur == '0';
for (; *pCur >= '0' && *pCur <= '9'; ++pCur )
......@@ -415,10 +415,10 @@ namespace NSFontConverter
FormatUInt( uArg.ulValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 2, &sTemp, &nLen );
break;
case fmtDouble:
FormatDouble( uArg.fValue, sBuffer, sizeof(sBuffer), nPrecision, FALSE, &sTemp, &nLen );
FormatDouble( uArg.fValue, sBuffer, sizeof(sBuffer), nPrecision, false, &sTemp, &nLen );
break;
case fmtDoubleTrim:
FormatDouble( uArg.fValue, sBuffer, sizeof(sBuffer), nPrecision, TRUE, &sTemp, &nLen );
FormatDouble( uArg.fValue, sBuffer, sizeof(sBuffer), nPrecision, true, &sTemp, &nLen );
break;
case fmtChar:
sBuffer[0] = uArg.cValue;
......@@ -474,10 +474,10 @@ namespace NSFontConverter
return this;
}
void StringExt::FormatInt ( long nValue, char *sBuffer, int nBufferSize, BOOL bZeroFill, int nWidth, int nBase, char **ppData, int *pnLen)
void StringExt::FormatInt ( long nValue, char *sBuffer, int nBufferSize, bool bZeroFill, int nWidth, int nBase, char **ppData, int *pnLen)
{
static char c_sValues[17] = "0123456789abcdef";
BOOL bNegative = FALSE;
bool bNegative = false;
int nStart;
int nCur = nBufferSize;
......@@ -513,7 +513,7 @@ namespace NSFontConverter
*pnLen = nBufferSize - nCur;
}
void StringExt::FormatUInt(unsigned long nValue, char *sBuffer, int nBufferSize, BOOL bZeroFill, int nWidth, int nBase, char **ppData, int *pnLen)
void StringExt::FormatUInt(unsigned long nValue, char *sBuffer, int nBufferSize, bool bZeroFill, int nWidth, int nBase, char **ppData, int *pnLen)
{
static char c_sValues[17] = "0123456789abcdef";
......@@ -541,9 +541,9 @@ namespace NSFontConverter
*pnLen = nBufferSize - nCur;
}
void StringExt::FormatDouble( double dValue, char *sBuffer, int nBufferSize, int nPrecision, BOOL bTrim, char **ppData, int *pnLen)
void StringExt::FormatDouble( double dValue, char *sBuffer, int nBufferSize, int nPrecision, bool bTrim, char **ppData, int *pnLen)
{
BOOL bNegative = FALSE, bStarted = FALSE;
bool bNegative = false, bStarted = false;
double dTemp = 0;
int nInt;
......@@ -560,7 +560,7 @@ namespace NSFontConverter
if ( bStarted || nInt != 0 )
{
sBuffer[--nCur] = '0' + nInt;
bStarted = TRUE;
bStarted = true;
}
dValue = dTemp;
}
......
......@@ -122,9 +122,9 @@ namespace NSFontConverter
void Resize(int nLength);
static void FormatInt ( long nValue, char *sBuffer, int nBufferSize, BOOL bZeroFill, int nWidth, int nBase, char **ppData, int *nLen);
static void FormatUInt (unsigned long nValue, char *sBuffer, int nBufferSize, BOOL bZeroFill, int nWidth, int nBase, char **ppData, int *nLen);
static void FormatDouble( double nValue, char *sBuffer, int nBufferSize, int nPrecision, BOOL bTrim, char **ppData, int *nLen);
static void FormatInt ( long nValue, char *sBuffer, int nBufferSize, bool bZeroFill, int nWidth, int nBase, char **ppData, int *nLen);
static void FormatUInt (unsigned long nValue, char *sBuffer, int nBufferSize, bool bZeroFill, int nWidth, int nBase, char **ppData, int *nLen);
static void FormatDouble( double nValue, char *sBuffer, int nBufferSize, int nPrecision, bool bTrim, char **ppData, int *nLen);
private:
......
......@@ -6,6 +6,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TRUETYPE_TABLES_H
#include "MemoryUtils.h"
#include <string>
......@@ -43,7 +44,7 @@ namespace NSFontConverter
sBuffer[nLen++] = nChar;
}
void Write(char *sString, int nStringLen = -1)
void Write(const char *sString, int nStringLen = -1)
{
if ( nStringLen < 0 )
nStringLen = strlen( sString );
......@@ -77,13 +78,13 @@ namespace NSFontConverter
}
};
static void CharBufferWrite(void *pBuffer, char *sData, int nLen)
static void CharBufferWrite(void *pBuffer, const char *sData, int nLen)
{
TCharBuffer *pCharBuffer = (TCharBuffer*)pBuffer;
pCharBuffer->Write( sData, nLen );
}
static void FileWrite(void* pFile, char *sData, int nLen)
static void FileWrite(void* pFile, const char *sData, int nLen)
{
::fwrite( sData, 1, nLen, (FILE*)pFile );
::fflush( (FILE*)pFile );
......@@ -111,7 +112,7 @@ namespace NSFontConverter
inline static int64_t GetHex (const std::wstring& string)
{
int64_t nResult = 0;
int nLen = string.length();
int nLen = (int)string.length();
const wchar_t* buf = string.c_str();
for ( int nIndex = 0; nIndex < nLen; ++nIndex )
{
......@@ -120,6 +121,25 @@ namespace NSFontConverter
return nResult;
}
inline static int GetInteger (const std::wstring& string)
{
return std::stoi(string);
}
inline static int GetInteger (const char* string)
{
return atoi(string);
}
inline static double GetDouble (const std::wstring& string)
{
return std::stod(string);
}
inline static double GetDouble (const char* string)
{
double d = 0;
sscanf(string, "%lf", &d);
return d;
}
}
// Функция взята из Graphics.dll
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment