mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
202 lines
5.3 KiB
C++
202 lines
5.3 KiB
C++
#include "stdafx.h"
|
|
|
|
#include <string.h>
|
|
#include "MemoryUtils.h"
|
|
#include "SMathExt.h"
|
|
#include "SGlyphBitmap.h"
|
|
#include "SFontFile.h"
|
|
#include "SFont.h"
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
struct SFontCacheTag
|
|
{
|
|
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; // Âûñîòà ñèìâîëà
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// SFont
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
SFont::SFont(SFontFile *pFontFile, double *pFontMatrix, double *pTextMatrix, BOOL bAntiAliasing)
|
|
{
|
|
m_pFontFile = pFontFile;
|
|
m_pFontFile->AddRef();
|
|
|
|
m_arrdFontMatrix[0] = pFontMatrix[0];
|
|
m_arrdFontMatrix[1] = pFontMatrix[1];
|
|
m_arrdFontMatrix[2] = pFontMatrix[2];
|
|
m_arrdFontMatrix[3] = pFontMatrix[3];
|
|
|
|
m_arrdTextMatrix[0] = pTextMatrix[0];
|
|
m_arrdTextMatrix[1] = pTextMatrix[1];
|
|
m_arrdTextMatrix[2] = pTextMatrix[2];
|
|
m_arrdTextMatrix[3] = pTextMatrix[3];
|
|
|
|
m_bAntiAliasing = bAntiAliasing;
|
|
|
|
m_pCache = NULL;
|
|
m_pCacheTags = NULL;
|
|
|
|
m_nMinX = m_nMinY = m_nMaxX = m_nMaxY = 0;
|
|
}
|
|
|
|
void SFont::InitCache()
|
|
{
|
|
// Íà ñàìîì äåëå äîëæíî áûòü (max - min + 1), íî ìû äîáàâëÿì 2 ïèêñåëÿ, ÷òîáû èçáåæàòü îøèáîê ñâÿçàííûõ ñ îêðóãëåíèåì.
|
|
m_nGlyphWidth = m_nMaxX - m_nMinX + 3;
|
|
m_nGlyphHeight = m_nMaxY - m_nMinY + 3;
|
|
|
|
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 *)MemUtilsMallocArray( m_nCacheSets * m_nCacheAssoc, m_nGlyphSize );
|
|
m_pCacheTags = (SFontCacheTag *)MemUtilsMallocArray( m_nCacheSets * m_nCacheAssoc, sizeof(SFontCacheTag) );
|
|
|
|
for ( int nIndex = 0; nIndex < m_nCacheSets * m_nCacheAssoc; ++nIndex )
|
|
{
|
|
m_pCacheTags[nIndex].nMRU = nIndex & (m_nCacheAssoc - 1);
|
|
}
|
|
}
|
|
|
|
SFont::~SFont()
|
|
{
|
|
m_pFontFile->Release();
|
|
|
|
if ( m_pCache )
|
|
{
|
|
MemUtilsFree( m_pCache );
|
|
}
|
|
if ( m_pCacheTags )
|
|
{
|
|
MemUtilsFree( m_pCacheTags );
|
|
}
|
|
}
|
|
|
|
BOOL SFont::GetGlyph(int nCode, int nFracX, int nFracY, SGlyphBitmap *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
|
|
SGlyphBitmap 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 )
|
|
{
|
|
MemUtilsFree( oNewBitmap.pData );
|
|
}
|
|
return TRUE;
|
|
}
|