mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 14:00:32 +08:00
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62634 954022d7-b5bf-4e40-9824-e11837661b57
238 lines
5.6 KiB
C++
238 lines
5.6 KiB
C++
#include "stdafx.h"
|
|
|
|
#include <string.h>
|
|
#include "FontFile.h"
|
|
#include "Font.h"
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
struct TFontCacheTag
|
|
{
|
|
int nCode;
|
|
short nFracX; // Äëÿ ðàáîòû ñ ðàöèîíàëüíûìè êîîðäèíàòàìè. ×èñëèòåëü
|
|
short nFracY; // ðàöèîíàëüíîãî ñäâèãà ïî x è y îòíîñèòåëüíî êîîðäèíàòû â int
|
|
int nMRU; // Valid bit (0x80000000) è íîìåð MRU
|
|
|
|
int nX; // Ñäâèã ïî X íà÷àëüíîé òî÷êè äëÿ ðèñîâàíèÿ ñèìâîëà
|
|
int nY; // Ñäâèã ïî Y íà÷àëüíîé òî÷êè äëÿ ðèñîâàíèÿ ñèìâîëà
|
|
int nWidth; // Øèðèíà ñèìâîëà
|
|
int nHeight; // Âûñîòà ñèìâîëà
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// CFont
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
CFont::CFont(CFontFile *pFontFile, BOOL bAntiAliasing, BOOL bUseKerning)
|
|
{
|
|
m_pFontFile = pFontFile;
|
|
m_pFontFile->AddRef();
|
|
|
|
m_arrdFontMatrix[0] = 1;
|
|
m_arrdFontMatrix[1] = 0;
|
|
m_arrdFontMatrix[2] = 0;
|
|
m_arrdFontMatrix[3] = 1;
|
|
|
|
m_arrdTextMatrix[0] = 1;
|
|
m_arrdTextMatrix[1] = 0;
|
|
m_arrdTextMatrix[2] = 0;
|
|
m_arrdTextMatrix[3] = 1;
|
|
|
|
m_bAntiAliasing = bAntiAliasing;
|
|
m_bUseKerning = bUseKerning;
|
|
|
|
m_pCache = NULL;
|
|
m_pCacheTags = NULL;
|
|
|
|
m_nMinX = m_nMinY = m_nMaxX = m_nMaxY = 0;
|
|
|
|
m_fSize = 1.0f;
|
|
|
|
m_fCharSpacing = 0.0;
|
|
|
|
m_unHorDpi = 72;
|
|
m_unVerDpi = 72;
|
|
|
|
m_bNeedDoItalic = FALSE;
|
|
m_bNeedDoBold = FALSE;
|
|
|
|
m_pDefaultFont = NULL;
|
|
m_bUseDefaultFont = FALSE;
|
|
}
|
|
|
|
void CFont::InitCache()
|
|
{
|
|
// Íà ñàìîì äåëå äîëæíî áûòü (max - min + 1), íî ìû äîáàâëÿì 2 ïèêñåëÿ, ÷òîáû èçáåæàòü îøèáîê ñâÿçàííûõ ñ îêðóãëåíèåì.
|
|
m_nGlyphWidth = m_nMaxX - m_nMinX + 3;
|
|
m_nGlyphHeight = m_nMaxY - m_nMinY + 3;
|
|
|
|
if ( m_nGlyphHeight > 1000 || m_nGlyphWidth > 1000 )
|
|
{
|
|
m_nGlyphSize = 0;
|
|
m_nCacheSets = 0;
|
|
m_nCacheAssoc = 0;
|
|
m_pCache = NULL;
|
|
m_pCacheTags = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
if ( m_bAntiAliasing )
|
|
{
|
|
m_nGlyphSize = m_nGlyphWidth * m_nGlyphHeight; // 24 áèòíûé êàíàë
|
|
}
|
|
else
|
|
{
|
|
m_nGlyphSize = ((m_nGlyphWidth + 7) >> 3) * m_nGlyphHeight; // 1 áèòíûé êàíàë
|
|
}
|
|
|
|
m_nCacheAssoc = 8;
|
|
if ( m_nGlyphSize <= 256 )
|
|
{
|
|
m_nCacheSets = 8;
|
|
}
|
|
else if ( m_nGlyphSize <= 512 )
|
|
{
|
|
m_nCacheSets = 4;
|
|
}
|
|
else if ( m_nGlyphSize <= 1024 )
|
|
{
|
|
m_nCacheSets = 2;
|
|
}
|
|
else
|
|
{
|
|
m_nCacheSets = 1;
|
|
}
|
|
m_pCache = (unsigned char *)malloc( m_nCacheSets * m_nCacheAssoc * m_nGlyphSize );
|
|
m_pCacheTags = (TFontCacheTag *)malloc( m_nCacheSets * m_nCacheAssoc * sizeof(TFontCacheTag) );
|
|
|
|
for ( int nIndex = 0; nIndex < m_nCacheSets * m_nCacheAssoc; ++nIndex )
|
|
{
|
|
m_pCacheTags[nIndex].nMRU = nIndex & (m_nCacheAssoc - 1);
|
|
}
|
|
}
|
|
void CFont::ClearCache()
|
|
{
|
|
if ( m_pCache )
|
|
{
|
|
free( m_pCache );
|
|
}
|
|
if ( m_pCacheTags )
|
|
{
|
|
free( m_pCacheTags );
|
|
}
|
|
|
|
InitCache();
|
|
}
|
|
|
|
CFont::~CFont()
|
|
{
|
|
m_pFontFile->Release();
|
|
|
|
if ( m_pCache )
|
|
{
|
|
free( m_pCache );
|
|
}
|
|
if ( m_pCacheTags )
|
|
{
|
|
free( m_pCacheTags );
|
|
}
|
|
}
|
|
|
|
BOOL CFont::GetGlyph(int nCode, int nFracX, int nFracY, TGlyphBitmap *pBitmap)
|
|
{
|
|
// Äëÿ áîëüøèõ èëè non-anti-aliased ñèìâîëîâ íå íàäî ðàáîòàòü ñ ðàöèîíàëüíûìè êîîðäèíàòàìè(äîñòàòî÷íî öåëûõ)
|
|
if ( !m_bAntiAliasing || m_nGlyphHeight > 50 )
|
|
{
|
|
nFracX = nFracY = 0;
|
|
}
|
|
|
|
// Èùåì â êýøå
|
|
int nI = ( nCode & (m_nCacheSets - 1) ) * m_nCacheAssoc;
|
|
for ( int nJ = 0; nJ < m_nCacheAssoc; ++nJ )
|
|
{
|
|
if ( ( m_pCacheTags[nI + nJ].nMRU & 0x80000000 ) && m_pCacheTags[nI + nJ].nCode == nCode && (int)m_pCacheTags[nI + nJ].nFracX == nFracX && (int)m_pCacheTags[nI + nJ].nFracY == nFracY )
|
|
{
|
|
pBitmap->nX = m_pCacheTags[nI + nJ].nX;
|
|
pBitmap->nY = m_pCacheTags[nI + nJ].nY;
|
|
pBitmap->nWidth = m_pCacheTags[nI + nJ].nWidth;
|
|
pBitmap->nHeight = m_pCacheTags[nI + nJ].nHeight;
|
|
|
|
for ( int nK = 0; nK < m_nCacheAssoc; ++nK )
|
|
{
|
|
if ( nK != nJ && ( m_pCacheTags[nI + nK].nMRU & 0x7fffffff ) < ( m_pCacheTags[nI + nJ].nMRU & 0x7fffffff ) )
|
|
{
|
|
++m_pCacheTags[nI + nK].nMRU;
|
|
}
|
|
}
|
|
|
|
m_pCacheTags[nI + nJ].nMRU = 0x80000000;
|
|
|
|
pBitmap->bAA = m_bAntiAliasing;
|
|
pBitmap->pData = m_pCache + (nI + nJ) * m_nGlyphSize;
|
|
pBitmap->bFreeData = FALSE;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// Ñîçäàåì íîâûé GlyphBitmap
|
|
TGlyphBitmap oNewBitmap;
|
|
if ( !MakeGlyph( nCode, nFracX, nFracY, &oNewBitmap ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Åñëè Glyph íå ïîìåùàåòñÿ â BBox, âîçâðàùàåì âðåìåííûé íåêýøèðîâàííûé Bitmap
|
|
if ( oNewBitmap.nWidth > m_nGlyphWidth || oNewBitmap.nHeight > m_nGlyphHeight )
|
|
{
|
|
*pBitmap = oNewBitmap;
|
|
return TRUE;
|
|
}
|
|
|
|
// Äîáàâëÿåì GlyphBitmap â êýø
|
|
int nSize = 0;
|
|
if ( m_bAntiAliasing )
|
|
{
|
|
nSize = oNewBitmap.nWidth * oNewBitmap.nHeight;
|
|
}
|
|
else
|
|
{
|
|
nSize = ((oNewBitmap.nWidth + 7) >> 3) * oNewBitmap.nHeight;
|
|
}
|
|
|
|
unsigned char *pBuffer = NULL;
|
|
for ( int nJ = 0; nJ < m_nCacheAssoc; ++nJ )
|
|
{
|
|
if ( ( m_pCacheTags[nI + nJ].nMRU & 0x7fffffff ) == m_nCacheAssoc - 1 )
|
|
{
|
|
m_pCacheTags[nI + nJ].nMRU = 0x80000000;
|
|
m_pCacheTags[nI + nJ].nCode = nCode;
|
|
m_pCacheTags[nI + nJ].nFracX = (short)nFracX;
|
|
m_pCacheTags[nI + nJ].nFracY = (short)nFracY;
|
|
m_pCacheTags[nI + nJ].nX = oNewBitmap.nX;
|
|
m_pCacheTags[nI + nJ].nY = oNewBitmap.nY;
|
|
m_pCacheTags[nI + nJ].nWidth = oNewBitmap.nWidth;
|
|
m_pCacheTags[nI + nJ].nHeight = oNewBitmap.nHeight;
|
|
|
|
pBuffer = m_pCache + (nI + nJ) * m_nGlyphSize;
|
|
memcpy( pBuffer, oNewBitmap.pData, nSize );
|
|
}
|
|
else
|
|
{
|
|
++m_pCacheTags[nI + nJ].nMRU;
|
|
}
|
|
}
|
|
|
|
*pBitmap = oNewBitmap;
|
|
|
|
pBitmap->pData = pBuffer;
|
|
pBitmap->bFreeData = FALSE;
|
|
|
|
if ( oNewBitmap.bFreeData )
|
|
{
|
|
free( oNewBitmap.pData );
|
|
}
|
|
return TRUE;
|
|
}
|
|
|