950 lines
22 KiB
C++
950 lines
22 KiB
C++
/*
|
|
* (c) Copyright Ascensio System SIA 2010-2023
|
|
*
|
|
* This program is a free software product. You can redistribute it and/or
|
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
|
* version 3 as published by the Free Software Foundation. In accordance with
|
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
|
* of any third-party rights.
|
|
*
|
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
|
*
|
|
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
|
* street, Riga, Latvia, EU, LV-1050.
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions
|
|
* of the Program must display Appropriate Legal Notices, as required under
|
|
* Section 5 of the GNU AGPL version 3.
|
|
*
|
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
|
* grant you any rights under trademark law for use of our trademarks.
|
|
*
|
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
|
* well as technical writing content are licensed under the terms of the
|
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
|
*
|
|
*/
|
|
#include "ApplicationFonts.h"
|
|
#include "../common/File.h"
|
|
#include <stdio.h>
|
|
#include "ftsnames.h"
|
|
#include FT_LCD_FILTER_H
|
|
#include "internal/tttypes.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CFontStream::CFontStream() : NSFonts::IFontStream()
|
|
{
|
|
m_pData = NULL;
|
|
m_lSize = 0;
|
|
m_bIsAttach = false;
|
|
}
|
|
CFontStream::~CFontStream()
|
|
{
|
|
if (!m_bIsAttach)
|
|
RELEASEARRAYOBJECTS(m_pData);
|
|
}
|
|
|
|
int CFontStream::CreateFromFile(const std::wstring& strFileName, BYTE* pDataUse)
|
|
{
|
|
NSFile::CFileBinary oFile;
|
|
if (!oFile.OpenFile(strFileName))
|
|
return FALSE;
|
|
|
|
m_lSize = oFile.GetFileSize();
|
|
|
|
if (NULL == pDataUse)
|
|
m_pData = new BYTE[m_lSize];
|
|
else
|
|
{
|
|
m_bIsAttach = true;
|
|
m_pData = pDataUse;
|
|
}
|
|
|
|
DWORD dwRead = 0;
|
|
DWORD dwNeedRead = (DWORD)m_lSize;
|
|
oFile.ReadFile(m_pData, dwNeedRead, dwRead);
|
|
|
|
if (dwNeedRead != dwRead)
|
|
{
|
|
if (!m_bIsAttach)
|
|
RELEASEARRAYOBJECTS(m_pData);
|
|
|
|
m_lSize = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
oFile.CloseFile();
|
|
return true;
|
|
}
|
|
|
|
int CFontStream::CreateFromMemory(BYTE* pData, LONG lSize, bool bClear)
|
|
{
|
|
if (bClear)
|
|
{
|
|
m_pData = new BYTE[lSize];
|
|
memcpy(m_pData, pData, lSize);
|
|
m_bIsAttach = false;
|
|
}
|
|
else
|
|
{
|
|
m_pData = pData;
|
|
m_bIsAttach = true;
|
|
}
|
|
m_lSize = lSize;
|
|
|
|
if (!m_pData)
|
|
{
|
|
m_lSize = 0;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
void CFontStream::GetMemory(BYTE*& pData, LONG& lSize)
|
|
{
|
|
pData = m_pData;
|
|
lSize = m_lSize;
|
|
}
|
|
|
|
CApplicationFontStreams::CApplicationFontStreams() : NSFonts::IApplicationFontStreams()
|
|
{
|
|
}
|
|
CApplicationFontStreams::~CApplicationFontStreams()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
NSFonts::IFontStream* CApplicationFontStreams::GetStream(const std::wstring &strFile)
|
|
{
|
|
CFontStream* pStream = m_mapStreams[strFile];
|
|
|
|
if (NULL != pStream)
|
|
return pStream;
|
|
|
|
if (NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage())
|
|
{
|
|
pStream = (CFontStream*)NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage()->Get(strFile);
|
|
if (pStream)
|
|
{
|
|
// чтобы удалить и из мапа и из стораджа
|
|
pStream->AddRef();
|
|
}
|
|
}
|
|
|
|
#ifndef FONT_ENGINE_DISABLE_FILESYSTEM
|
|
if (!pStream)
|
|
{
|
|
pStream = new CFontStream();
|
|
pStream->CreateFromFile(strFile);
|
|
}
|
|
#endif
|
|
|
|
m_mapStreams[strFile] = pStream;
|
|
return pStream;
|
|
}
|
|
void CApplicationFontStreams::CheckStreams(std::map<std::wstring,bool> &mapFiles)
|
|
{
|
|
std::map<std::wstring, CFontStream*>::iterator iter = m_mapStreams.begin();
|
|
while (iter != m_mapStreams.end())
|
|
{
|
|
CFontStream* pFile = iter->second;
|
|
|
|
if (mapFiles.find(iter->first) != mapFiles.end())
|
|
{
|
|
RELEASEINTERFACE(pFile);
|
|
iter = m_mapStreams.erase(iter);
|
|
}
|
|
else
|
|
iter++;
|
|
}
|
|
}
|
|
|
|
void CApplicationFontStreams::Clear()
|
|
{
|
|
if (NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage())
|
|
NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage()->Clear();
|
|
|
|
for (std::map<std::wstring, CFontStream*>::iterator iter = m_mapStreams.begin(); iter != m_mapStreams.end(); ++iter)
|
|
{
|
|
CFontStream* pFile = iter->second;
|
|
RELEASEINTERFACE(pFile);
|
|
}
|
|
m_mapStreams.clear();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
NSFonts::IFontFile* NSFonts::IFontManager::LoadFontFile(NSFonts::CLibrary& library, NSFonts::IFontStream* pStreamI, int lFaceIndex)
|
|
{
|
|
CFontStream* pStream = (CFontStream*)pStreamI;
|
|
FT_Open_Args oOpenArgs;
|
|
oOpenArgs.flags = FT_OPEN_MEMORY | FT_OPEN_PARAMS;
|
|
oOpenArgs.memory_base = pStream->m_pData;
|
|
oOpenArgs.memory_size = pStream->m_lSize;
|
|
|
|
FT_Parameter *pParams = (FT_Parameter *)::malloc( sizeof(FT_Parameter) * 4 );
|
|
pParams[0].tag = FT_MAKE_TAG( 'i', 'g', 'p', 'f' );
|
|
pParams[0].data = NULL;
|
|
pParams[1].tag = FT_MAKE_TAG( 'i', 'g', 'p', 's' );
|
|
pParams[1].data = NULL;
|
|
pParams[2].tag = FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY;
|
|
pParams[2].data = NULL;
|
|
pParams[3].tag = FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY;
|
|
pParams[3].data = NULL;
|
|
|
|
oOpenArgs.params = pParams;
|
|
oOpenArgs.num_params = 4;
|
|
|
|
FT_Face pFace;
|
|
if ( FT_Open_Face( library.m_internal->m_library, &oOpenArgs, lFaceIndex, &pFace ) )
|
|
return NULL;
|
|
|
|
::free(pParams);
|
|
|
|
CFontFile* pFont = new CFontFile();
|
|
pFont->m_lFaceIndex = lFaceIndex;
|
|
|
|
pFont->m_lUnits_Per_Em = pFace->units_per_EM;
|
|
pFont->m_lAscender = pFace->ascender;
|
|
pFont->m_lDescender = pFace->descender;
|
|
pFont->m_lLineHeight = pFace->height;
|
|
|
|
pFont->m_nNum_charmaps = pFace->num_charmaps;
|
|
|
|
pFont->m_pFace = pFace;
|
|
pFont->LoadDefaultCharAndSymbolicCmapIndex();
|
|
|
|
if (FT_Set_Char_Size(pFace, 0, (FT_F26Dot6)(pFont->m_dSize * 64), 0, 0))
|
|
{
|
|
delete pFont;
|
|
return NULL;
|
|
}
|
|
|
|
pFont->ResetTextMatrix();
|
|
pFont->ResetFontMatrix();
|
|
|
|
return pFont;
|
|
}
|
|
|
|
NSFonts::IFontFile* CFontsCache::LockFont(NSFonts::CLibrary& library, const std::wstring& strFileName, const int& lFaceIndex, const double& dSize)
|
|
{
|
|
if (NULL == m_pApplicationFontStreams)
|
|
return NULL;
|
|
|
|
std::string sLock = U_TO_UTF8(strFileName);
|
|
sLock += (std::to_string(lFaceIndex) + "_" + std::to_string((int)(100 * dSize + 0.5)));
|
|
|
|
CFontFile* pFile = m_mapFiles[sLock];
|
|
|
|
if (NULL != pFile)
|
|
{
|
|
pFile->AddRef();
|
|
return pFile;
|
|
}
|
|
|
|
CFontStream* pStream = (CFontStream*)m_pApplicationFontStreams->GetStream(strFileName);
|
|
if (NULL == pStream)
|
|
return NULL;
|
|
pFile = (CFontFile*)CFontManager::LoadFontFile(library, pStream, lFaceIndex);
|
|
if (NULL == pFile)
|
|
return NULL;
|
|
|
|
if (-1 != m_lCacheSize)
|
|
{
|
|
m_arFiles.push_back(sLock);
|
|
if ((int)m_arFiles.size() > m_lCacheSize)
|
|
{
|
|
std::string sPop = *m_arFiles.begin();
|
|
std::map<std::string, CFontFile*>::iterator _find = m_mapFiles.find(sPop);
|
|
|
|
if (m_mapFiles.end() != _find)
|
|
{
|
|
CFontFile* pFontRemove = _find->second;
|
|
RELEASEINTERFACE(pFontRemove);
|
|
m_arFiles.pop_front();
|
|
m_mapFiles.erase(_find);
|
|
}
|
|
else
|
|
{
|
|
// такого быть не должно
|
|
m_mapFiles.erase(_find);
|
|
}
|
|
}
|
|
}
|
|
|
|
pFile->m_pStream = pStream;
|
|
pFile->m_pStream->AddRef();
|
|
m_mapFiles[sLock] = pFile;
|
|
|
|
pFile->AddRef();
|
|
return pFile;
|
|
}
|
|
|
|
CFontsCache::CFontsCache() : NSFonts::IFontsCache()
|
|
{
|
|
m_pApplicationFontStreams = NULL;
|
|
m_lCacheSize = -1;
|
|
|
|
m_pLibrary = NULL;
|
|
FT_Init_FreeType(&m_pLibrary);
|
|
FT_Library_SetLcdFilter(m_pLibrary, FT_LCD_FILTER_DEFAULT);
|
|
}
|
|
CFontsCache::~CFontsCache()
|
|
{
|
|
Clear();
|
|
|
|
if (m_pLibrary)
|
|
FT_Done_FreeType(m_pLibrary);
|
|
}
|
|
void CFontsCache::Clear()
|
|
{
|
|
for (std::map<std::string, CFontFile*>::iterator iter = m_mapFiles.begin(); iter != m_mapFiles.end(); ++iter)
|
|
{
|
|
CFontFile* pFile = iter->second;
|
|
RELEASEINTERFACE(pFile);
|
|
}
|
|
m_mapFiles.clear();
|
|
|
|
if (-1 != m_lCacheSize)
|
|
m_arFiles.clear();
|
|
}
|
|
void CFontsCache::SetCacheSize(const int& lMaxSize)
|
|
{
|
|
if (lMaxSize <= 0)
|
|
m_lCacheSize = -1;
|
|
else
|
|
m_lCacheSize = lMaxSize;
|
|
}
|
|
FT_Library CFontsCache::GetLibrary()
|
|
{
|
|
return m_pLibrary;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
CFontManager::CFontManager() : NSFonts::IFontManager()
|
|
{
|
|
m_pFont = NULL;
|
|
m_pApplication = NULL;
|
|
m_pOwnerCache = NULL;
|
|
|
|
m_bStringGID = FALSE;
|
|
m_nLOAD_MODE = 40968;
|
|
|
|
m_nRENDER_MODE = FT_RENDER_MODE_NORMAL;
|
|
|
|
m_bUseDefaultFont = FALSE;
|
|
m_fCharSpacing = 0;
|
|
|
|
m_lUnits_Per_Em = 0;
|
|
m_lAscender = 0;
|
|
m_lDescender = 0;
|
|
m_lLineHeight = 0;
|
|
|
|
m_bCorrectFontByName = true;
|
|
}
|
|
|
|
CFontManager::~CFontManager()
|
|
{
|
|
RELEASEINTERFACE(m_pFont);
|
|
RELEASEOBJECT(m_pOwnerCache);
|
|
}
|
|
void CFontManager::SetOwnerCache(NSFonts::IFontsCache* pCache)
|
|
{
|
|
m_pOwnerCache = (CFontsCache*)pCache;
|
|
}
|
|
|
|
NSFonts::IFontsCache* CFontManager::GetCache() { return m_pOwnerCache; }
|
|
NSFonts::IApplicationFonts* CFontManager::GetApplication() { return m_pApplication; }
|
|
NSFonts::IFontFile* CFontManager::GetFile() { return m_pFont; }
|
|
|
|
void CFontManager::AfterLoad()
|
|
{
|
|
if (NULL == m_pFont)
|
|
{
|
|
m_lUnits_Per_Em = 0;
|
|
m_lAscender = 0;
|
|
m_lDescender = 0;
|
|
m_lLineHeight = 0;
|
|
}
|
|
else
|
|
{
|
|
m_lUnits_Per_Em = m_pFont->m_lUnits_Per_Em;
|
|
m_lAscender = m_pFont->m_lAscender;
|
|
m_lDescender = m_pFont->m_lDescender;
|
|
m_lLineHeight = m_pFont->m_lLineHeight;
|
|
|
|
m_pFont->CheckHintsSupport();
|
|
}
|
|
}
|
|
|
|
void CFontManager::Initialize()
|
|
{
|
|
}
|
|
|
|
double CFontManager::UpdateSize(const double &dOldSize, const double &dDpi, const double &dNewDpi)
|
|
{
|
|
if (0 == dNewDpi && 0 == dDpi)
|
|
return dOldSize;
|
|
else if (0 == dNewDpi)
|
|
return dOldSize * dDpi / 72.0;
|
|
else if (0 == dDpi)
|
|
return dOldSize * 72.0 / dNewDpi;
|
|
|
|
return dOldSize * dDpi / dNewDpi;
|
|
}
|
|
|
|
INT CFontManager::LoadString1(const std::wstring &wsBuffer, const float &fX, const float &fY)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
m_oString.SetString(wsBuffer, fX, fY);
|
|
m_pFont->GetString(m_oString);
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::LoadString2(const std::wstring &wsBuffer, const float &fX, const float &fY)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
m_oString.SetString(wsBuffer, fX, fY);
|
|
m_pFont->GetString2(m_oString);
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::LoadString1(const unsigned int* pGids, const unsigned int& nGidsCount, const float &fX, const float &fY)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
m_oString.SetString(pGids, nGidsCount, fX, fY);
|
|
m_pFont->GetString(m_oString);
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::LoadString2(const unsigned int* pGids, const unsigned int& nGidsCount, const float &fX, const float &fY)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
m_oString.SetString(pGids, nGidsCount, fX, fY);
|
|
m_pFont->GetString2(m_oString);
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::LoadString3(const int& gid, const float &fX, const float &fY)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
SetStringGID(TRUE);
|
|
m_oString.SetStringGID(gid, fX, fY);
|
|
m_pFont->GetString2(m_oString);
|
|
SetStringGID(FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::LoadString3C(const int& gid, const float &fX, const float &fY)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
SetStringGID(TRUE);
|
|
m_oString.SetStringGID(gid, fX, fY);
|
|
m_pFont->GetString2C(m_oString);
|
|
SetStringGID(FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::LoadString2C(const int& code, const float &fX, const float &fY)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
m_oString.SetStringGID(code, fX, fY);
|
|
m_pFont->GetString2C(m_oString);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
TFontCacheSizes CFontManager::MeasureChar(const LONG &lUnicode)
|
|
{
|
|
if (NULL == m_pFont)
|
|
{
|
|
TFontCacheSizes oRet;
|
|
return oRet;
|
|
}
|
|
return m_pFont->GetChar(lUnicode);
|
|
}
|
|
|
|
TBBoxAdvance CFontManager::MeasureChar2(const LONG& lUnicode)
|
|
{
|
|
TBBoxAdvance ret;
|
|
if (NULL == m_pFont)
|
|
return ret;
|
|
|
|
TFontCacheSizes sizes = m_pFont->GetChar(lUnicode);
|
|
ret.box = sizes.oBBox;
|
|
ret.fAdvanceX = sizes.fAdvanceX;
|
|
ret.fAdvanceY = sizes.fAdvanceY;
|
|
return ret;
|
|
}
|
|
|
|
int CFontManager::GetKerning(UINT unPrevGID, UINT unGID)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return 0;
|
|
|
|
return m_pFont->GetKerning(unPrevGID, unGID);
|
|
}
|
|
|
|
int CFontManager::GetUnderline(float *pfStartX, float *pfStartY, float *pfEndX, float *pfEndY, float *pfSize)
|
|
{
|
|
if ( m_oString.GetLength() <= 0 || !m_pFont )
|
|
{
|
|
*pfStartX = 0;
|
|
*pfStartY = 0;
|
|
*pfEndX = 0;
|
|
*pfEndY = 0;
|
|
*pfSize = 0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
float fStartX = m_oString.m_fX;
|
|
float fStartY = m_oString.m_fY;
|
|
float fEndX = m_oString.m_fEndX;
|
|
float fEndY = m_oString.m_fEndY;
|
|
|
|
short shUnderlinePos = m_pFont->m_pFace->underline_position;
|
|
short shUnderlineSize = m_pFont->m_pFace->underline_thickness;
|
|
|
|
float fKoef = (float)(m_pFont->m_dSize / 1000 * m_pFont->m_unVerDpi / 72.0f);
|
|
float fUnderlinePos = shUnderlinePos * fKoef;
|
|
float fUnderLineSize = shUnderlineSize * fKoef;
|
|
|
|
fStartY -= fUnderlinePos;
|
|
fEndY -= fUnderlinePos;
|
|
|
|
m_oString.Transform( &fStartX, &fStartY );
|
|
m_oString.Transform( &fEndX, &fEndY );
|
|
|
|
*pfStartX = fStartX;
|
|
*pfStartY = fStartY;
|
|
|
|
*pfEndX = fEndX;
|
|
*pfEndY = fEndY;
|
|
|
|
*pfSize = fUnderLineSize;
|
|
|
|
return TRUE;
|
|
}
|
|
TBBox CFontManager::MeasureString()
|
|
{
|
|
TBBox oBox;
|
|
oBox.fMinX = 0xFFFF;
|
|
oBox.fMinY = 0xFFFF;
|
|
oBox.fMaxX = -0xFFFF;
|
|
oBox.fMaxY = -0xFFFF;
|
|
|
|
int nLen = m_oString.GetLength();
|
|
if (nLen <= 0)
|
|
return oBox;
|
|
|
|
for (int nIndex = 0; nIndex < nLen; ++nIndex)
|
|
{
|
|
float fT, fB, fL, fR;
|
|
m_oString.GetBBox(&fL, &fT, &fR, &fB, nIndex);
|
|
|
|
if (oBox.fMaxY < fB)
|
|
oBox.fMaxY = fB;
|
|
|
|
if (oBox.fMinY > fT)
|
|
oBox.fMinY = fT;
|
|
|
|
if (oBox.fMinX > fL)
|
|
oBox.fMinX = fL;
|
|
|
|
if (oBox.fMaxX < fR)
|
|
oBox.fMaxX = fR;
|
|
}
|
|
|
|
return oBox;
|
|
}
|
|
|
|
TBBox CFontManager::MeasureString2()
|
|
{
|
|
TBBox oBox;
|
|
oBox.fMinX = 0;
|
|
oBox.fMinY = 0;
|
|
oBox.fMaxX = 0;
|
|
oBox.fMaxY = 0;
|
|
|
|
int nLen = m_oString.GetLength();
|
|
if (nLen <= 0)
|
|
return oBox;
|
|
|
|
m_oString.GetBBox2(&oBox.fMinX, &oBox.fMinY, &oBox.fMaxX, &oBox.fMaxY);
|
|
return oBox;
|
|
}
|
|
|
|
INT CFontManager::GetNextChar2(TGlyph*& pGlyph, float& fX, float& fY)
|
|
{
|
|
if (!m_oString.GetNext(pGlyph))
|
|
return FALSE;
|
|
|
|
if (glyphstateNormal == pGlyph->eState || (glyphstateDefault == pGlyph->eState && NULL != m_pFont->m_pDefaultFont))
|
|
{
|
|
fX = m_oString.m_fX + pGlyph->fX + pGlyph->oBitmap.nX;
|
|
fY = m_oString.m_fY + pGlyph->fY - pGlyph->oBitmap.nY;
|
|
}
|
|
else
|
|
{
|
|
fX = m_oString.m_fX + pGlyph->fX;
|
|
fY = m_oString.m_fY + pGlyph->fY;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::SetTextMatrix(const double &fA, const double &fB, const double &fC, const double &fD, const double &fE, const double &fF)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
if (fabs(fB) > 0.1)
|
|
{
|
|
int y = 0;
|
|
++y;
|
|
}
|
|
|
|
/*
|
|
if (m_pFont->SetTextMatrix(fA, fB, fC, fD, 0, 0))
|
|
m_oString.SetCTM((float)fA, (float)fB, (float)fC, (float)fD, 0, 0);
|
|
*/
|
|
m_pFont->SetTextMatrix(fA, fB, fC, fD, 0, 0);
|
|
m_oString.SetCTM((float)fA, (float)fB, (float)fC, (float)fD, 0, 0);
|
|
|
|
m_oString.SetTrans((float)fE, (float)fF);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::SetTextMatrix2(const double &fA, const double &fB, const double &fC, const double &fD, const double &fE, const double &fF)
|
|
{
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
m_pFont->SetTextMatrix(fA, fB, fC, fD, 0, 0);
|
|
m_oString.SetCTM((float)fA, (float)fB, (float)fC, (float)fD, 0, 0);
|
|
m_oString.SetTrans((float)fE, (float)fF);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CFontManager::SetStringGID(const INT &bStringGID)
|
|
{
|
|
m_bStringGID = bStringGID;
|
|
|
|
if (NULL == m_pFont)
|
|
return;
|
|
|
|
m_pFont->SetStringGID(m_bStringGID);
|
|
}
|
|
|
|
void CFontManager::SetCharSpacing(const double &dCharSpacing)
|
|
{
|
|
m_fCharSpacing = dCharSpacing;
|
|
|
|
if (NULL == m_pFont)
|
|
return;
|
|
|
|
m_pFont->SetCharSpacing(m_fCharSpacing);
|
|
}
|
|
|
|
INT CFontManager::GetStringPath(NSFonts::ISimpleGraphicsPath* pInterface)
|
|
{
|
|
if (NULL == pInterface)
|
|
return FALSE;
|
|
|
|
int nCount = m_oString.GetLength();
|
|
if ( !m_pFont || nCount <= 0 )
|
|
return FALSE;
|
|
|
|
CFontPath* pOverallPath = new CFontPath();
|
|
if (!pOverallPath)
|
|
return FALSE;
|
|
|
|
for (int nIndex = 0; nIndex < nCount; ++nIndex)
|
|
{
|
|
TGlyph* pCurGlyph = m_oString.GetAt(nIndex);
|
|
CFontPath* pPath = NULL;
|
|
if (glyphstateNormal == pCurGlyph->eState || (glyphstateDefault == pCurGlyph->eState && NULL != m_pFont->m_pDefaultFont))
|
|
{
|
|
if (glyphstateNormal == pCurGlyph->eState)
|
|
{
|
|
pPath = (CFontPath*)m_pFont->GetGlyphPath(pCurGlyph->lUnicode);
|
|
}
|
|
else
|
|
{
|
|
pPath = (CFontPath*)m_pFont->m_pDefaultFont->GetGlyphPath(pCurGlyph->lUnicode);
|
|
}
|
|
}
|
|
|
|
if (!pPath)
|
|
continue;
|
|
|
|
pPath->Reverse();
|
|
pPath->ToMM(m_pFont->m_unHorDpi, m_pFont->m_unVerDpi);
|
|
|
|
pPath->Offset(m_oString.m_fX + pCurGlyph->fX * 25.4 / m_pFont->m_unHorDpi,
|
|
m_oString.m_fY + pCurGlyph->fY * 25.4 / m_pFont->m_unVerDpi);
|
|
|
|
pOverallPath->Append(pPath);
|
|
delete pPath;
|
|
}
|
|
|
|
pOverallPath->ToInterface(pInterface);
|
|
delete pOverallPath;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
NSFonts::CFontInfo* CFontManager::GetFontInfoByParams(NSFonts::CFontSelectFormat& oFormat, bool bIsDictionaryUse)
|
|
{
|
|
NSFonts::CFontInfo* pRes = NULL;
|
|
if (NULL != m_pApplication)
|
|
{
|
|
pRes = m_pApplication->GetList()->GetByParams(oFormat, bIsDictionaryUse);
|
|
}
|
|
return pRes;
|
|
}
|
|
std::vector<NSFonts::CFontInfo*> CFontManager::GetAllStylesByFontName(const std::wstring& strName)
|
|
{
|
|
std::vector<NSFonts::CFontInfo*> aRes;
|
|
if (NULL != m_pApplication)
|
|
aRes = ((CFontList*)(m_pApplication->GetList()))->GetAllByName(strName);
|
|
return aRes;
|
|
}
|
|
INT CFontManager::LoadFontByName(const std::wstring& sName, const double& dSize, const int& lStyle, const double& dDpiX, const double& dDpiY)
|
|
{
|
|
if (NULL == m_pApplication)
|
|
return FALSE;
|
|
|
|
NSFonts::CFontSelectFormat oFormat;
|
|
oFormat.wsName = new std::wstring(sName);
|
|
|
|
oFormat.bBold = new INT(FALSE);
|
|
oFormat.bItalic = new INT(FALSE);
|
|
|
|
if (lStyle & 0x01)
|
|
*oFormat.bBold = TRUE;
|
|
if (lStyle & 0x02)
|
|
*oFormat.bItalic = TRUE;
|
|
|
|
NSFonts::CFontInfo* pInfo = m_pApplication->GetList()->GetByParams(oFormat, m_bCorrectFontByName);
|
|
if (NULL == pInfo)
|
|
return FALSE;
|
|
|
|
INT bLoad = LoadFontFromFile(pInfo->m_wsFontPath, pInfo->m_lIndex, dSize, dDpiX, dDpiY);
|
|
|
|
if (bLoad == TRUE)
|
|
{
|
|
bool bIsNeedBold = false;
|
|
if (NULL != oFormat.bBold && (*oFormat.bBold) == TRUE && pInfo->m_bBold == FALSE)
|
|
bIsNeedBold = true;
|
|
bool bIsNeedItalic = false;
|
|
if (NULL != oFormat.bItalic && (*oFormat.bItalic) == TRUE && pInfo->m_bItalic == FALSE)
|
|
bIsNeedItalic = true;
|
|
|
|
m_pFont->SetNeedBold(bIsNeedBold);
|
|
m_pFont->SetItalic(bIsNeedItalic);
|
|
}
|
|
return bLoad;
|
|
}
|
|
|
|
INT CFontManager::LoadFontFromFile(const std::wstring& sPath, const int& lFaceIndex, const double& dSize, const double& dDpiX, const double& dDpiY)
|
|
{
|
|
if (NULL == m_pApplication)
|
|
return FALSE;
|
|
|
|
CFontsCache* pCache = (CFontsCache*)((m_pOwnerCache != NULL) ? m_pOwnerCache : m_pApplication->GetCache());
|
|
RELEASEINTERFACE(m_pFont);
|
|
|
|
NSFonts::CLibrary library;
|
|
library.m_internal->m_library = pCache->GetLibrary();
|
|
m_pFont = (CFontFile*)pCache->LockFont(library, sPath, lFaceIndex, dSize);
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
m_pFont->m_pFontManager = this;
|
|
m_pFont->SetSizeAndDpi(dSize, dDpiX, dDpiY);
|
|
|
|
m_sName = L"";
|
|
if (m_pFont->m_pFace)
|
|
{
|
|
m_pFont->m_sName = GetCorrectSfntName(m_pFont->m_pFace->family_name);
|
|
m_sName = m_pFont->m_sName;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT CFontManager::LoadFontFromFile2(NSFonts::IFontsCache* pCache, const std::wstring& sPath, const int& lFaceIndex, const double& dSize, const double& dDpiX, const double& dDpiY)
|
|
{
|
|
if (NULL == pCache)
|
|
return FALSE;
|
|
|
|
RELEASEINTERFACE(m_pFont);
|
|
|
|
NSFonts::CLibrary library;
|
|
library.m_internal->m_library = ((CFontsCache*)pCache)->GetLibrary();
|
|
m_pFont = (CFontFile*)pCache->LockFont(library, sPath, lFaceIndex, dSize);
|
|
if (NULL == m_pFont)
|
|
return FALSE;
|
|
|
|
m_pFont->m_pFontManager = this;
|
|
m_pFont->SetSizeAndDpi(dSize, dDpiX, dDpiY);
|
|
|
|
m_sName = L"";
|
|
if (m_pFont->m_pFace)
|
|
{
|
|
m_pFont->m_sName = GetCorrectSfntName(m_pFont->m_pFace->family_name);
|
|
m_sName = m_pFont->m_sName;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CFontManager::CloseFont()
|
|
{
|
|
if (m_pFont)
|
|
{
|
|
m_pFont->ClearCache();
|
|
RELEASEINTERFACE(m_pFont);
|
|
}
|
|
}
|
|
|
|
std::wstring CFontManager::GetFontType()
|
|
{
|
|
if (!m_pFont)
|
|
return L"";
|
|
|
|
return m_pFont->GetFontFormat();
|
|
}
|
|
unsigned int CFontManager::GetNameIndex(const std::wstring& wsName)
|
|
{
|
|
if (!m_pFont)
|
|
return 0;
|
|
|
|
return m_pFont->GetNameIndex(wsName);
|
|
}
|
|
unsigned int CFontManager::GetGIDByUnicode(const unsigned int& unCode)
|
|
{
|
|
if (!m_pFont)
|
|
return 0;
|
|
|
|
return m_pFont->GetGIDByUnicode(unCode);
|
|
}
|
|
int CFontManager::GetUnicodeByGID(const int& gid)
|
|
{
|
|
if (!m_pFont)
|
|
return 0;
|
|
|
|
return m_pFont->GetUnicodeByGID(gid);
|
|
}
|
|
|
|
void CFontManager::SetSubpixelRendering(const bool& hmul, const bool& vmul)
|
|
{
|
|
if (hmul)
|
|
m_nRENDER_MODE = FT_RENDER_MODE_LCD;
|
|
else if (vmul)
|
|
m_nRENDER_MODE = FT_RENDER_MODE_LCD_V;
|
|
else
|
|
m_nRENDER_MODE = FT_RENDER_MODE_NORMAL;
|
|
}
|
|
|
|
void CFontManager::GetFace(double& d0, double& d1, double& d2)
|
|
{
|
|
d0 = 2048;
|
|
d1 = 0;
|
|
d2 = 0;
|
|
|
|
if (m_pFont)
|
|
{
|
|
TT_OS2* os2 = NULL;
|
|
TT_Header* header = NULL;
|
|
if (m_pFont->m_pFace)
|
|
{
|
|
if ((header = (TT_Header*)FT_Get_Sfnt_Table(m_pFont->m_pFace, ft_sfnt_head)) != NULL)
|
|
{
|
|
d1 = header->yMax;
|
|
d2 = header->yMin;
|
|
d0 = header->Units_Per_EM;
|
|
}
|
|
|
|
if ((os2 = (TT_OS2*)FT_Get_Sfnt_Table(m_pFont->m_pFace, ft_sfnt_os2)) != NULL && os2->version != 0xFFFFU)
|
|
{
|
|
d1 = os2->usWinAscent;
|
|
d2 = -os2->usWinDescent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void CFontManager::GetLimitsY(double& dMin, double& dMax)
|
|
{
|
|
dMin = m_pFont->m_pFace->descender;
|
|
dMax = m_pFont->m_pFace->ascender;
|
|
if (FT_IS_SFNT(m_pFont->m_pFace))
|
|
{
|
|
TT_Face ttface = (TT_Face)m_pFont->m_pFace;
|
|
dMin = ttface->header.yMin;
|
|
dMax = ttface->header.yMax;
|
|
}
|
|
}
|
|
|
|
void CFontManager::SetUseCorrentFontByName(const bool& use)
|
|
{
|
|
m_bCorrectFontByName = use;
|
|
}
|
|
|
|
CFontFile* CFontManager::GetFontFileBySymbol(CFontFile* pFile, int code)
|
|
{
|
|
std::wstring sName = m_pApplication->GetFontBySymbol(code);
|
|
if (sName.empty())
|
|
return NULL;
|
|
|
|
// чтобы не зарелизить при ограниченном кэше
|
|
CFontFile* pFontOld = m_pFont;
|
|
m_pFont = NULL;
|
|
std::wstring sOldName = m_sName;
|
|
|
|
int nStyle = 0;
|
|
if (pFile->m_bNeedDoBold || pFile->IsBold())
|
|
nStyle |= 1;
|
|
if (pFile->m_bNeedDoItalic || pFile->IsItalic())
|
|
nStyle |= 2;
|
|
|
|
LoadFontByName(sName, pFile->m_dSize, nStyle, pFile->m_unHorDpi, pFile->m_unVerDpi);
|
|
|
|
if (!m_pFont)
|
|
{
|
|
m_pFont = pFontOld;
|
|
return NULL;
|
|
}
|
|
|
|
CFontFile* pFontNew = m_pFont;
|
|
m_pFont = pFontOld;
|
|
m_sName = sOldName;
|
|
|
|
memcpy(pFontNew->m_arrdTextMatrix, pFile->m_arrdTextMatrix, 6 * sizeof(double));
|
|
pFontNew->UpdateMatrix2();
|
|
|
|
return pFontNew;
|
|
}
|