Files
core/ASCImageStudio3/ASCGraphics/Objects/Font/FontManager.h

1081 lines
30 KiB
C++

// FontManager.h : Declaration of the CFontManager
#pragma once
#include "resource.h" // main symbols
#include "Registration.h"
#include "Consts.h"
#include "WinFont.h"
#include "Errors.h"
#include "FontUtils.h"
#include "FontEngine.h"
#include "FT_Font.h"
#include "Path.h"
#include FT_ADVANCES_H
#include FT_GLYPH_H
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
// IFontManager
[
object,
uuid("8C0DA859-68A6-4CDB-9C48-8B6D66EFAC1F"),
dual, helpstring("IFontManager Interface"),
pointer_default(unique)
]
__interface IFontManager : IDispatch
{
//----- Îòêðûòèå/çàêðûòèå øðèôòà --------------------------------------------------------------------
[id(001)] HRESULT Initialize([in] BSTR bsXmlOptions);
[id(002)] HRESULT LoadFontFromFile([in]BSTR bsSrcPath, [in] float fEmSize, [in] unsigned int unHorDPI, [in] unsigned int unVerDPI, [in] long lFaceIndex = 0);
[id(003)] HRESULT LoadFontByName([in]BSTR bsFamilyName, [in] float fEmSize, [in] long lStyle, [in] unsigned int unHorDPI, [in]unsigned int unVerDPI);
[id(004)] HRESULT GetFontType([out, retval] BSTR *pbsType);
[id(005)] HRESULT SetDefaultFont([in] BSTR bsFamilyName);
//----- Ôóíêöèè àíàëîãè÷íûå ìåòîäàì êëàññîâ Font è FontFamily â GDI+ --------------------------------
[id(101)] HRESULT GetCellAscent([out, retval] unsigned short *pusAscent);
[id(102)] HRESULT GetCellDescent([out, retval] unsigned short *pusDescent);
[id(103)] HRESULT GetEmHeight([out, retval] unsigned short *pusEmHeight);
[id(104)] HRESULT GetFamilyName([out, retval] BSTR *pbsFamilyName);
[id(105)] HRESULT GetLineSpacing([out, retval] unsigned short *pusLineSpacing);
[id(106)] HRESULT IsStyleAvailable([in] long lStyle, [out, retval] BOOL *pbAvailable);
[id(107)] HRESULT GetHeight([in] float fDPI, [out, retval] float *pfHeight);
//----- ×òåíèå ãëîáàëüíûõ ïàðàìåòðîâ øðèôòà ---------------------------------------------------------
[id(201)] HRESULT GetFacesCount([out, retval] long *plFacesCount);
[id(202)] HRESULT GetFaceIndex([out, retval] long *plFaceIndex);
[id(203)] HRESULT GetGlyphsCount([out, retval] long *plGlyphsCount);
[id(205)] HRESULT GetStyleName([out, retval] BSTR *pbsStyleName);
[id(206)] HRESULT IsCharAvailable([in] long lUnicode, [out, retval] BOOL *pbAvailable);
[id(207)] HRESULT GetUnderlinePosition([out, retval] short *pshUnderPos);
[id(208)] HRESULT GetUnderlineThickness([out, retval] short *pshUnderThick);
[id(209)] HRESULT GetMaxAdvanceWidth([out, retval] short *pshMaxAdvWidth);
[id(210)] HRESULT GetMaxAdvanceHeight([out, retval] short *pshMaxAdvHeight);
[id(211)] HRESULT GetBBox([out] long *plMinX, [out] long *plMinY, [out] long *plMaxX, [out] long *plMaxY);
[id(212)] HRESULT IsUnicodeRangeAvailable([in] unsigned long ulBit, [in] unsigned int unLongIndex, [out ,retval] VARIANT_BOOL *pvbSuccess);
//----- Ðàáîòà ñ ãëèôàìè ----------------------------------------------------------------------------
[id(301)] HRESULT GetGlyphPath([in] long lUnicode, [out, retval] BSTR *pbsXmlPath);
[id(302)] HRESULT GetStringPath([in] BSTR bsString, [out, retval] BSTR *pbsXmlPath);
[id(303)] HRESULT GetGlyphBitmap([in] long lUnicode, [out, retval]IUnknown **ppImage);
[id(304)] HRESULT GetStringBitmap([in] BSTR bsString, [out, retval] IUnknown **ppImage);
[id(305)] HRESULT LoadString([in] BSTR bsString);
[id(306)] HRESULT GetNextChar([out] IUnknown **ppImage, [out] float *pfX, [out] float *pfY, [out, retval] VARIANT_BOOL *pvbSuccess);
[id(307)] HRESULT GetCharBBox([out] float *pfLeft, [out] float *pfTop, [out] float *pfRight, [out] float *pfBottom);
[id(308)] HRESULT MeasureString([out] float *pfLeft, [out] float *pfTop, [out] float *pfRight, [out] float *pfBottom);
[id(309)] HRESULT ApplyTransform([in] float fA, [in] float fB, [in] float fC, [in] float fD, [in] float fE, [in] float fF);
//----- Ðàáîòà ñî øðèôòàìè Windows ------------------------------------------------------------------
[id(501)] HRESULT GetWinFontsCount([out, retval] long *plCount);
[id(502)] HRESULT GetWinFont([in] long nIndex, [out] BSTR *pbsFontName, [out] BSTR *pbsFontStyle, [out] BSTR *pbsFontPath, [out] long *plIndex, [out] BOOL *pbBold, [out] BOOL *pbItalic);
};
// CFontManager
[
coclass,
default(IFontManager),
threading(apartment),
vi_progid("AVSOfficeFontManager.FontManager"),
progid("AVSOfficeFontManager.FontManager.1"),
version(1.0),
uuid("0FF37CE6-DD3C-488F-8319-13D9E392F1D8"),
helpstring("FontManager Class")
]
class ATL_NO_VTABLE CFontManager :
public IFontManager
{
public:
private:
float m_fEmSize;
long m_lUnit;
TGlyph *m_pGlyphsBuffer; // Äëÿ ðàáîòû ñî ñòðîêîé
unsigned int m_nGlyphsCount; // Êîëè÷åñòâî ñèìâîëîâ â ñòðîêå
unsigned int m_nGlyphIndex; // Íîìåð òåêóùåãî ñèìâîëà
CFontEngine *m_pFontEngine; // Êëàññ äëÿ ðàáîòû ñî øðèôòàìè (óñòàíîâëåííûå øðèôòû, êýø øðèôòîâ è ò.ä.)
CFont *m_pFont; // Òåêóùèé øðèôò
public:
CFontManager()
{
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
m_pFontEngine = NULL;
m_pFont = NULL;
m_pGlyphsBuffer = NULL;
m_nGlyphsCount = 0;
m_nGlyphIndex = -1;
return S_OK;
}
void FinalRelease()
{
if ( m_pFontEngine )
{
delete m_pFontEngine;
}
}
private:
public:
//----- Îòêðûòèå/çàêðûòèå øðèôòà --------------------------------------------------------------------
STDMETHOD(Initialize)(BSTR bsXmlOptions)
{
m_pFontEngine = new CFontEngine(TRUE);
return S_OK;
}
STDMETHOD(LoadFontFromFile)(BSTR bsSrcPath, float fEmSize, unsigned int unHorDpi, unsigned int unVerDpi, long lFaceIndex)
{
if ( !m_pFontEngine )
return S_FALSE;
CFontFile *pFontFile = NULL;
if ( !( pFontFile = m_pFontEngine->GetFontFile( bsSrcPath, lFaceIndex ) ) )
{
pFontFile = m_pFontEngine->LoadFont( bsSrcPath, lFaceIndex );
}
if ( !pFontFile )
return AVS_OFFICEFONTMANAGER_ERROR_FONT_OPEN_ERROR;
m_pFont = m_pFontEngine->GetFont( pFontFile );
if ( !m_pFont )
return S_FALSE;
UpdateStyles( m_pFont, FALSE, FALSE );
m_pFont->SetDefaultFont( m_pFontEngine->GetDefaultFont( FALSE, FALSE ) );
m_pFont->SetSizeAndDpi( fEmSize, unHorDpi, unVerDpi );
return S_OK;
}
STDMETHOD(LoadFontByName)(BSTR bsFamilyName, float fEmSize, long lStyle, unsigned int unHorDpi, unsigned int unVerDpi)
{
if ( !m_pFontEngine )
return S_FALSE;
BOOL bBold = FALSE;
BOOL bItalic = FALSE;
switch (lStyle)
{
case FontConstants::FontStyle::FontStyleRegular: bBold = FALSE; bItalic = FALSE; break;
case FontConstants::FontStyle::FontStyleItalic: bBold = FALSE; bItalic = TRUE; break;
case FontConstants::FontStyle::FontStyleBold: bBold = TRUE; bItalic = FALSE; break;
case FontConstants::FontStyle::FontStyleBoldItalic: bBold = TRUE; bItalic = TRUE; break;
}
CFontFile *pFontFile = NULL;
if ( !( pFontFile = m_pFontEngine->GetFontFile( bsFamilyName, bBold, bItalic ) ) )
{
pFontFile = m_pFontEngine->LoadFont( bsFamilyName, bBold, bItalic );
}
if ( !pFontFile )
return AVS_OFFICEFONTMANAGER_ERROR_WIN_FONT_NOT_FOUND;
m_pFont = m_pFontEngine->GetFont( pFontFile );
if ( !m_pFont )
return S_FALSE;
UpdateStyles( m_pFont, bBold, bItalic );
m_pFont->SetDefaultFont( m_pFontEngine->GetDefaultFont( bBold, bItalic ) );
m_pFont->SetSizeAndDpi( fEmSize, unHorDpi, unVerDpi );
return S_OK;
}
STDMETHOD(GetFontType)(BSTR *pbsType)
{
CStringW wsType = _T("");
if ( !m_pFont )
{
*pbsType = wsType.AllocSysString();
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
wsType = m_pFont->GetFontFormat();
*pbsType = wsType.AllocSysString();
return S_OK;
}
STDMETHOD(SetDefaultFont)(BSTR bsFamilyName)
{
if ( !m_pFontEngine )
return S_FALSE;
m_pFontEngine->SetDefaultFont( bsFamilyName );
return S_OK;
}
//----- Ôóíêöèè àíàëîãè÷íûå ìåòîäàì êëàññîâ Font è FontFamily â GDI+ --------------------------------
STDMETHOD(GetCellAscent)(unsigned short *pusAscent)
{
if ( !m_pFont )
{
*pusAscent = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
*pusAscent = m_pFont->GetAscender();
return S_OK;
}
STDMETHOD(GetCellDescent)(unsigned short *pusDescent)
{
if ( !m_pFont )
{
*pusDescent = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
*pusDescent = fabs( m_pFont->GetDescender() );
return S_OK;
}
STDMETHOD(GetEmHeight)(unsigned short *pusEmHeight)
{
if ( !m_pFont )
{
*pusEmHeight = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
*pusEmHeight = m_pFont->GetUnitsPerEm();
return S_OK;
}
STDMETHOD(GetFamilyName)(BSTR *pbsFamilyName)
{
if ( !m_pFont )
{
CString sFamilyName( _T("") );
*pbsFamilyName = sFamilyName.AllocSysString();
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
CString sFamilyName( m_pFont->GetFamilyName() );
*pbsFamilyName = sFamilyName.AllocSysString();
return S_OK;
}
STDMETHOD(GetLineSpacing)(unsigned short *pusLineSpacing)
{
if ( !m_pFont )
{
*pusLineSpacing = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
*pusLineSpacing = m_pFont->GetLineSpacing();
return S_OK;
}
STDMETHOD(IsStyleAvailable)(long lStyle, BOOL *pbAvailable)
{
if ( !m_pFontEngine || !m_pFont )
{
*pbAvailable = FALSE;
return S_OK;
}
*pbAvailable = m_pFontEngine->IsStyleAvailable( CStringW( m_pFont->GetFamilyName() ).GetBuffer(), lStyle );
return S_OK;
}
STDMETHOD(GetHeight)(float fDPI, float *pfHeight)
{
if ( !m_pFont )
{
*pfHeight = 0.0f;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
unsigned short usEmHeight = 0;
unsigned short usLineSpacing = 0;
HRESULT hRes = S_OK;
if ( FAILED( hRes = GetEmHeight( &usEmHeight ) ) || usEmHeight <= 0.0001 )
return hRes;
if ( FAILED( hRes = GetLineSpacing( &usLineSpacing ) ) )
return hRes;
float fKoef = 1.0f;
switch( m_lUnit )
{
case FontConstants::UnitPoint: fKoef = fDPI / 72; break;
case FontConstants::UnitInch: fKoef = fDPI; break;
case FontConstants::UnitDocument: fKoef = fDPI / 300; break;
case FontConstants::UnitMillimeter: fKoef = fDPI / 25.4; break;
}
*pfHeight = usLineSpacing * ( m_fEmSize / usEmHeight ) * fKoef;
return S_OK;
}
//----- ×òåíèå ãëîáàëüíûõ ïàðàìåòðîâ øðèôòà ---------------------------------------------------------
STDMETHOD(GetFacesCount)(long *plFacesCount)
{
if ( !m_pFont )
{
*plFacesCount = 0;
return S_FALSE;
}
*plFacesCount = m_pFont->GetFacesCount();
return S_OK;
}
STDMETHOD(GetFaceIndex)(long *plFaceIndex)
{
if ( !m_pFont )
{
*plFaceIndex = 0;
return S_FALSE;
}
*plFaceIndex = m_pFont->GetFaceIndex();
return S_OK;
}
STDMETHOD(GetGlyphsCount)(long *plGlyphsCount)
{
if ( !m_pFont )
{
*plGlyphsCount = 0;
return S_FALSE;
}
*plGlyphsCount = m_pFont->GetGlyphsCount();
return S_OK;
}
STDMETHOD(GetStyleName)(BSTR *pbsStyleName)
{
if ( !m_pFont )
{
CString sStyleName( _T("") );
*pbsStyleName = sStyleName.AllocSysString();
return S_FALSE;
}
CString sStyleName( m_pFont->GetStyleName() );
*pbsStyleName = sStyleName.AllocSysString();
return S_OK;
}
STDMETHOD(IsCharAvailable)(long lUnicode, BOOL *pbAvailable)
{
if ( !m_pFont )
return S_FALSE;
*pbAvailable = m_pFont->IsCharAvailable( lUnicode );
return S_OK;
}
STDMETHOD(GetUnderlinePosition)(short *pshUnderPos)
{
if ( !m_pFont )
{
*pshUnderPos = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
*pshUnderPos = m_pFont->GetUnderlinePosition();
return S_OK;
}
STDMETHOD(GetUnderlineThickness)(short *pshUnderThick)
{
if ( !m_pFont )
{
*pshUnderThick = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
*pshUnderThick = m_pFont->GetUnderlineThickness();
return S_OK;
}
STDMETHOD(GetMaxAdvanceWidth)(short *pshMaxAdvWidth)
{
if ( !m_pFont )
{
*pshMaxAdvWidth = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
*pshMaxAdvWidth = m_pFont->GetMaxAdvanceWidth();
return S_OK;
}
STDMETHOD(GetMaxAdvanceHeight)(short *pshMaxAdvHeight)
{
if ( !m_pFont )
{
*pshMaxAdvHeight = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
*pshMaxAdvHeight = m_pFont->GetMaxAdvanceHeight();
return S_OK;
}
STDMETHOD(GetBBox)(long *plMinX, long *plMinY, long *plMaxX, long *plMaxY)
{
if ( !m_pFont )
{
*plMinX = 0;
*plMinY = 0;
*plMaxX = 0;
*plMaxY = 0;
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
}
m_pFont->GetBBox( plMinX, plMinY, plMaxX, plMaxY );
return S_OK;
}
STDMETHOD(IsUnicodeRangeAvailable)(unsigned long ulBit, unsigned int unLongIndex, VARIANT_BOOL *pvbSuccess)
{
*pvbSuccess = VARIANT_FALSE;
if ( !m_pFont )
return AVS_OFFICEFONTMANAGER_ERROR_FONT_WASNT_LOAD;
if ( m_pFont->IsUnicodeRangeAvailable( ulBit, unLongIndex ) > 0 )
*pvbSuccess = VARIANT_TRUE;
return S_OK;
}
//----- Ðàáîòà ñ ãëèôàìè ----------------------------------------------------------------------------
STDMETHOD(GetGlyphPath)(long lUnicode, BSTR *pbsXmlPath)
{
if ( !m_pFont )
{
CString sXml( _T("") );
*pbsXmlPath = sXml.AllocSysString();
return S_FALSE;
}
CPath *pPath = m_pFont->GetGlyphPath( lUnicode );
if ( !pPath )
return S_FALSE;
*pbsXmlPath = pPath->ToXmlString().AllocSysString();
return S_OK;
}
STDMETHOD(GetStringPath)(BSTR bsString, BSTR *pbsXmlPath)
{
if ( !m_pFont )
{
CString sXml( _T("") );
*pbsXmlPath = sXml.AllocSysString();
return S_FALSE;
}
CStringW wsString( bsString );
CPath *pPath = m_pFont->GetStringPath( wsString.GetBuffer(), wsString.GetLength() );
if ( !pPath )
return S_FALSE;
*pbsXmlPath = pPath->ToXmlString().AllocSysString();
return S_OK;
}
STDMETHOD(GetGlyphBitmap)(long lUnicode, IUnknown **ppImage)
{
if ( !m_pFont )
return S_FALSE;
TGlyphBitmap oBitmap;
m_pFont->GetGlyph( lUnicode, 0, 0, &oBitmap );
// Ïîäãîòàâëèâàåì pInterface
IUnknown **pInterface = (IUnknown**)ppImage;
if ( !pInterface )
return S_FALSE;
// create result interface
*pInterface = NULL;
HRESULT hRes = CoCreateInstance( MediaCore::CLSID_CAVSUncompressedVideoFrame, NULL, CLSCTX_ALL, MediaCore::IID_IAVSUncompressedVideoFrame, (void**)pInterface );
if ( hRes != S_OK || NULL == *pInterface )
return S_FALSE;
MediaCore::IAVSUncompressedVideoFrame* pMediaData = (MediaCore::IAVSUncompressedVideoFrame*)*pInterface;
int nWidth = oBitmap.nWidth;
int nHeight = oBitmap.nHeight;
int nBufferSize = 4 * nWidth * nHeight;
if ( nBufferSize < 1 )
return S_FALSE;
pMediaData->put_ColorSpace( ( 1 << 6) || ( 1 << 31 ) ); // CPS_BGRA | CPS_FLIP
pMediaData->put_Width( nWidth );
pMediaData->put_Height( nHeight );
pMediaData->put_AspectRatioX( nWidth );
pMediaData->put_AspectRatioY( nHeight );
pMediaData->put_Interlaced( VARIANT_FALSE );
pMediaData->put_Stride( 0, 4 * nWidth );
pMediaData->AllocateBuffer( nBufferSize );
unsigned char *pBufferPtr = NULL;
long nCreatedBufferSize = 0;
pMediaData->get_Buffer( &pBufferPtr );
pMediaData->get_BufferSize( &nCreatedBufferSize );
pMediaData->put_Plane( 0, pBufferPtr );
if ( !pBufferPtr || nCreatedBufferSize != nBufferSize )
return S_FALSE;
*pInterface = pMediaData;
// Ïèøåì äàííûå â pBufferPtr
for ( int nY = 0; nY < nHeight; nY++ )
{
for ( int nX = 0; nX < nWidth; nX++ )
{
unsigned char nG = 255 - oBitmap.pData[nWidth * nY + nX ];
pBufferPtr[0] = nG;
pBufferPtr[1] = nG;
pBufferPtr[2] = nG;
pBufferPtr[3] = 255;
pBufferPtr += 4;
}
}
return S_OK;
}
STDMETHOD(GetStringBitmap)(BSTR bsString, IUnknown **ppImage)
{
if ( !m_pFont )
return S_FALSE;
CStringW wsString( bsString );
TGlyphBitmap *pBitmaps = new TGlyphBitmap[ wsString.GetLength() ];
if ( !pBitmaps )
return S_FALSE;
int nHeight = 0;
int nWidth = 0;
for ( int nIndex = 0; nIndex < wsString.GetLength(); nIndex++ )
{
long lUnicode = wsString.GetAt( nIndex );
m_pFont->GetGlyph( lUnicode, 0, 0, &(pBitmaps[nIndex]) );
if ( nHeight < pBitmaps[nIndex].nHeight )
nHeight = pBitmaps[nIndex].nHeight;
nWidth += pBitmaps[nIndex].nWidth;
}
// Ïîäãîòàâëèâàåì pInterface
IUnknown **pInterface = (IUnknown**)ppImage;
if ( !pInterface )
return S_FALSE;
// create result interface
*pInterface = NULL;
HRESULT hRes = CoCreateInstance( MediaCore::CLSID_CAVSUncompressedVideoFrame, NULL, CLSCTX_ALL, MediaCore::IID_IAVSUncompressedVideoFrame, (void**)pInterface );
if ( hRes != S_OK || NULL == *pInterface )
return S_FALSE;
MediaCore::IAVSUncompressedVideoFrame* pMediaData = (MediaCore::IAVSUncompressedVideoFrame*)*pInterface;
int nBufferSize = 4 * nWidth * nHeight;
if ( nBufferSize < 1 )
return S_FALSE;
pMediaData->put_ColorSpace( ( 1 << 6) ); // CPS_BGRA
pMediaData->put_Width( nWidth );
pMediaData->put_Height( nHeight );
pMediaData->put_AspectRatioX( nWidth );
pMediaData->put_AspectRatioY( nHeight );
pMediaData->put_Interlaced( VARIANT_FALSE );
pMediaData->put_Stride( 0, 4 * nWidth );
pMediaData->AllocateBuffer( nBufferSize );
unsigned char *pBufferPtr = NULL;
long nCreatedBufferSize = 0;
pMediaData->get_Buffer( &pBufferPtr );
pMediaData->get_BufferSize( &nCreatedBufferSize );
pMediaData->put_Plane( 0, pBufferPtr );
if ( !pBufferPtr || nCreatedBufferSize != nBufferSize )
return S_FALSE;
*pInterface = pMediaData;
// Ïèøåì äàííûå â pBufferPtr
int nShiftX = 0;
for ( int nGlyphIndex = 0; nGlyphIndex < wsString.GetLength(); nGlyphIndex++ )
{
for ( int nY = 0; nY < nHeight; nY++ )
{
if ( nHeight - nY < pBitmaps[nGlyphIndex].nHeight )
{
for ( int nX = 0; nX < pBitmaps[nGlyphIndex].nWidth; nX++ )
{
int nCurY = nY - ( nHeight - pBitmaps[nGlyphIndex].nHeight );
unsigned char nG = 255 - pBitmaps[nGlyphIndex].pData[pBitmaps[nGlyphIndex].nWidth * nCurY + nX ];
int nIndex = (nX + nShiftX + nY * nWidth) * 4;
pBufferPtr[nIndex + 0] = nG;
pBufferPtr[nIndex + 1] = nG;
pBufferPtr[nIndex + 2] = nG;
pBufferPtr[nIndex + 3] = 255;
}
}
else
{
for ( int nX = 0; nX < pBitmaps[nGlyphIndex].nWidth; nX++ )
{
int nIndex = (nX + nShiftX + nY * nWidth) * 4;
pBufferPtr[nIndex + 0] = 255;
pBufferPtr[nIndex + 1] = 255;
pBufferPtr[nIndex + 2] = 255;
pBufferPtr[nIndex + 3] = 255;
}
}
}
nShiftX += pBitmaps[nGlyphIndex].nWidth;
}
delete []pBitmaps;
return S_OK;
}
STDMETHOD(LoadString)(BSTR bsString)
{
if ( !m_pFont )
return FALSE;
CStringW wsBuffer = CStringW( bsString );
m_nGlyphsCount = wsBuffer.GetLength();
if ( m_pGlyphsBuffer )
delete []m_pGlyphsBuffer;
m_pGlyphsBuffer = new TGlyph[m_nGlyphsCount];
m_nGlyphIndex = -1;
for ( int nIndex = 0; nIndex < m_nGlyphsCount; nIndex++ )
{
m_pGlyphsBuffer[nIndex].lUnicode = wsBuffer.GetAt( nIndex );
}
m_pFont->GetString( m_pGlyphsBuffer, m_nGlyphsCount );
return S_OK;
}
STDMETHOD(GetNextChar)(IUnknown **ppImage, float *pfX, float *pfY, VARIANT_BOOL *pvbSuccess)
{
*pvbSuccess = VARIANT_FALSE;
m_nGlyphIndex++;
if ( m_nGlyphIndex >= m_nGlyphsCount )
{
*ppImage = NULL;
*pfX = -0xFFFF;
*pfY = -0xFFFF;
return S_OK;
}
if ( !m_pFont || !m_pGlyphsBuffer )
return S_FALSE;
if ( glyphstateNormal == m_pGlyphsBuffer[m_nGlyphIndex].eState || ( glyphstateDeafault == m_pGlyphsBuffer[m_nGlyphIndex].eState && NULL != m_pFont->GetDefaultFont() ) )
{
long lUnicode = m_pGlyphsBuffer[m_nGlyphIndex].lUnicode;
TGlyphBitmap oBitmap;
CFont *pCurFont = NULL;
if ( glyphstateNormal == m_pGlyphsBuffer[m_nGlyphIndex].eState )
pCurFont = m_pFont;
else
pCurFont = m_pFont->GetDefaultFont();
pCurFont->GetGlyph( lUnicode, 0, 0, &oBitmap );
if ( oBitmap.nWidth > 0 && oBitmap.nHeight > 0 )
{
// Ïîäãîòàâëèâàåì pInterface
IUnknown **pInterface = (IUnknown**)ppImage;
if ( !pInterface )
return S_FALSE;
// create result interface
*pInterface = NULL;
HRESULT hRes = CoCreateInstance( MediaCore::CLSID_CAVSUncompressedVideoFrame, NULL, CLSCTX_ALL, MediaCore::IID_IAVSUncompressedVideoFrame, (void**)pInterface );
if ( hRes != S_OK || NULL == *pInterface )
return S_FALSE;
MediaCore::IAVSUncompressedVideoFrame* pMediaData = (MediaCore::IAVSUncompressedVideoFrame*)*pInterface;
int nWidth = oBitmap.nWidth;
int nHeight = oBitmap.nHeight;
if ( pCurFont->GetBold() )
nWidth++;
int nBufferSize = 4 * nWidth * nHeight;
if ( nBufferSize < 1 )
return S_FALSE;
pMediaData->put_ColorSpace( 1 << 6 ); // CPS_BGRA
pMediaData->put_Width( nWidth );
pMediaData->put_Height( nHeight );
pMediaData->put_AspectRatioX( nWidth );
pMediaData->put_AspectRatioY( nHeight );
pMediaData->put_Interlaced( VARIANT_FALSE );
pMediaData->put_Stride( 0, 4 * nWidth );
pMediaData->AllocateBuffer( nBufferSize );
unsigned char *pBufferPtr = NULL;
long nCreatedBufferSize = 0;
pMediaData->get_Buffer( &pBufferPtr );
pMediaData->get_BufferSize( &nCreatedBufferSize );
pMediaData->put_Plane( 0, pBufferPtr );
if ( !pBufferPtr || nCreatedBufferSize != nBufferSize )
return S_FALSE;
*pInterface = pMediaData;
// Ïèøåì äàííûå â pBufferPtr
if ( !pCurFont->GetBold() )
{
for ( int nY = 0; nY < nHeight; nY++ )
{
for ( int nX = 0; nX < nWidth; nX++ )
{
unsigned char nG = 255 - oBitmap.pData[nWidth * nY + nX ];
//pBufferPtr[0] = nG;
//pBufferPtr[1] = nG;
//pBufferPtr[2] = nG;
//pBufferPtr[3] = 255;
pBufferPtr[0] = 0;//nG;
pBufferPtr[1] = 0;//nG;
pBufferPtr[2] = 0;//nG;
pBufferPtr[3] = 255 - nG;
pBufferPtr += 4;
}
}
}
else
{
// Çäåñü (nWidth = oBitmap.nWidth + 1)
for ( int nY = 0; nY < nHeight; nY++ )
{
for ( int nX = nWidth - 1; nX >= 0; nX-- )
{
int nDstIndex = nY * nWidth * 4 + nX * 4;
int nSrcIndex = nY * oBitmap.nWidth + nX;
if ( 0 != nX )
{
int nFirstByte, nSecondByte;
if ( nWidth - 1 == nX )
nFirstByte = 255;
else
nFirstByte = 255 - oBitmap.pData[nSrcIndex];
nSecondByte = 255 - oBitmap.pData[nSrcIndex - 1];
pBufferPtr[nDstIndex + 0] = 0;//nG;
pBufferPtr[nDstIndex + 1] = 0;//nG;
pBufferPtr[nDstIndex + 2] = 0;//nG;
pBufferPtr[nDstIndex + 3] = min( 255, 510 - (nFirstByte + nSecondByte) );
}
else
{
pBufferPtr[nDstIndex + 0] = 0;
pBufferPtr[nDstIndex + 1] = 0;
pBufferPtr[nDstIndex + 2] = 0;
pBufferPtr[nDstIndex + 3] = oBitmap.pData[nSrcIndex];
}
}
}
}
}
else
{
*ppImage = NULL;
}
*pfX = m_pGlyphsBuffer[m_nGlyphIndex].fX + oBitmap.nX;
*pfY = m_pGlyphsBuffer[m_nGlyphIndex].fY + oBitmap.nY - oBitmap.nHeight; // Îòäàåì êîîðäèíàòó ëåâîãî âåðõíåãî óãëà
}
else
{
// Ñèìâîë íå íàéäåí, íè÷åãî íå ðèñóåì
*ppImage = NULL;
*pfX = m_pGlyphsBuffer[m_nGlyphIndex].fX;
*pfY = m_pGlyphsBuffer[m_nGlyphIndex].fY;
}
*pvbSuccess = VARIANT_TRUE;
return S_OK;
}
STDMETHOD(GetCharBBox)(float *pfLeft, float *pfTop, float *pfRight, float *pfBottom)
{
if ( !m_pGlyphsBuffer || m_nGlyphsCount <= 0 || m_nGlyphIndex < 0 || m_nGlyphIndex >= m_nGlyphsCount )
{
*pfBottom = 0;
*pfRight = 0;
*pfLeft = 0;
*pfTop = 0;
return S_FALSE;
}
*pfBottom = m_pGlyphsBuffer[m_nGlyphIndex].fBottom;
*pfRight = m_pGlyphsBuffer[m_nGlyphIndex].fRight + m_pGlyphsBuffer[m_nGlyphIndex].fX;
*pfLeft = m_pGlyphsBuffer[m_nGlyphIndex].fLeft + m_pGlyphsBuffer[m_nGlyphIndex].fX;
*pfTop = m_pGlyphsBuffer[m_nGlyphIndex].fTop;
return S_OK;
}
STDMETHOD(GetNextChar2)(BSTR *pbsTempPath, float *pfX, float *pfY, VARIANT_BOOL *pvbSuccess)
{
*pvbSuccess = VARIANT_FALSE;
if ( m_nGlyphIndex >= m_nGlyphsCount )
{
CStringW wsTemp = _T("");
*pbsTempPath = wsTemp.AllocSysString();
*pfX = -0xFFFF;
*pfY = -0xFFFF;
return S_OK;
}
if ( !m_pFont || !m_pGlyphsBuffer )
return S_FALSE;
long lUnicode = m_pGlyphsBuffer[m_nGlyphIndex].lUnicode;
int nX = (int)floor( (double)m_pGlyphsBuffer[m_nGlyphIndex].fX );
int nFracX = (int)floor( (double)(m_pGlyphsBuffer[m_nGlyphIndex].fX - nX) * FONT_FRACTION );
int nY = (int)floor( (double)m_pGlyphsBuffer[m_nGlyphIndex].fY );
int nFracY = (int)floor( (double)(m_pGlyphsBuffer[m_nGlyphIndex].fY - nY) * FONT_FRACTION );
TGlyphBitmap oBitmap;
m_pFont->GetGlyph( lUnicode, nFracX, nFracY, &oBitmap );
int nWidth = oBitmap.nWidth;
int nHeight = oBitmap.nHeight;
CStringW wsFileName = _T( "C:\\Temp.bmp" );
*pbsTempPath = wsFileName.AllocSysString();
FILE *pFile = NULL;
if ( !( pFile = ::_wfopen( wsFileName, _T("wb") ) ) )
return S_FALSE;
int nSize = 0, nStride;
BYTE *pBuffer = NULL, *pBufPointer;
BITMAPFILEHEADER oFileHeader;
BITMAPINFOHEADER oInfoHeader;
oFileHeader.bfType = 'M' * 256 + 'B';
oFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nHeight * nWidth * 4;
oFileHeader.bfReserved1 = 0;
oFileHeader.bfReserved2 = 0;
oFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
oInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
oInfoHeader.biWidth = nWidth;
oInfoHeader.biHeight = nHeight;
oInfoHeader.biPlanes = 1;
oInfoHeader.biBitCount = 32;
oInfoHeader.biCompression = BI_RGB;
oInfoHeader.biSizeImage = nHeight * nWidth * 4;
oInfoHeader.biXPelsPerMeter = 0;
oInfoHeader.biYPelsPerMeter = 0;
oInfoHeader.biClrUsed = 0;
oInfoHeader.biClrImportant = 0;
::fwrite( &oFileHeader, 1, sizeof(BITMAPFILEHEADER), pFile );
::fwrite( &oInfoHeader, 1, sizeof(BITMAPINFOHEADER), pFile );
nSize = nHeight * nWidth * 4;
pBuffer = new BYTE[nSize];
if ( !pBuffer )
{
return S_FALSE;
}
pBufPointer = pBuffer;
for ( int nY = 0; nY < nHeight; nY++ )
{
for ( int nX = 0; nX < nWidth; nX++, pBufPointer += 4 )
{
unsigned char nG = oBitmap.pData[nWidth * nY + nX ];
float fAlpha = nG / 255.f;
pBufPointer[0] = ( 1 - fAlpha ) * 216;
pBufPointer[1] = ( 1 - fAlpha ) * 236;
pBufPointer[2] = ( 1 - fAlpha ) * 236;
pBufPointer[3] = 255 * fAlpha;
}
}
pBufPointer = pBuffer;
nStride = nWidth * 4;
pBufPointer += (nHeight - 1) * nStride;
nStride = -nStride;
for( int nRow = nHeight; nRow > 0 ; --nRow, pBufPointer += nStride )
{
::fwrite( pBufPointer, 1, abs( nStride ), pFile );
}
delete []pBuffer;
fclose( pFile );
*pfX = m_pGlyphsBuffer[m_nGlyphIndex].fX - oBitmap.nX;
*pfY = m_pGlyphsBuffer[m_nGlyphIndex].fY - oBitmap.nY;
m_nGlyphIndex++;
*pvbSuccess = VARIANT_TRUE;
return S_OK;
}
STDMETHOD(MeasureString)(float *pfLeft, float *pfTop, float *pfRight, float *pfBottom)
{
if ( !m_pGlyphsBuffer || m_nGlyphsCount <= 0 )
{
*pfBottom = 0;
*pfRight = 0;
*pfLeft = 0;
*pfTop = 0;
return S_FALSE;
}
// Ó÷èòûâàåì, ÷òî ìû èñïîëüçóåì ïåðåâåðíóòþ ñèñòåìó (ò.å. ìàòðèöà ïðåîáðàçîâàíèÿ áûë [1 0 0 -1 0 0])
// È òî ÷òî ñàìà ñèñòåìà êîîðäèíàò òîæå ïåðåâåðíóòà
float fTop = -0xFFFF, fBottom = 0xFFFF, fLeft = 0xFFFF, fRight = -0xFFFF;
for ( int nIndex = 0; nIndex < m_nGlyphsCount; nIndex++ )
{
if ( fBottom > m_pGlyphsBuffer[nIndex].fBottom )
fBottom = m_pGlyphsBuffer[nIndex].fBottom;
if ( fTop < m_pGlyphsBuffer[nIndex].fTop )
fTop = m_pGlyphsBuffer[nIndex].fTop;
}
fLeft = m_pGlyphsBuffer[0].fLeft;
fRight = m_pGlyphsBuffer[m_nGlyphsCount - 1].fRight + m_pGlyphsBuffer[m_nGlyphsCount - 1].fX;
*pfBottom = fBottom;
*pfRight = fRight;
*pfLeft = fLeft;
*pfTop = fTop;
return S_OK;
}
STDMETHOD(ApplyTransform)(float fA, float fB, float fC, float fD, float fE, float fF)
{
if ( !m_pFont )
{
return S_FALSE;
}
m_pFont->ResetTransform();
m_pFont->ApplyTransform( fA, fB, fC, fD, fE, fF );
return S_OK;
}
//----- Ðàáîòà ñî øðèôòàìè Windows ------------------------------------------------------------------
STDMETHOD(GetWinFontsCount)(long *plCount)
{
if ( !m_pFontEngine )
{
*plCount = 0;
return S_OK;
}
*plCount = m_pFontEngine->GetInstalledFontsCount();
return S_OK;
}
STDMETHOD(GetWinFont)(long nIndex, BSTR *pbsFontName, BSTR *pbsFontStyle, BSTR *pbsFontPath, long *plIndex, BOOL *pbBold, BOOL *pbItalic)
{
if ( !m_pFontEngine )
{
*pbsFontName = CStringW( _T("") ).AllocSysString();
*pbsFontStyle = CStringW( _T("") ).AllocSysString();
*pbsFontPath = CStringW( _T("") ).AllocSysString();
*plIndex = 0;
return S_OK;
}
CWinFontInfo *pFontInfo = m_pFontEngine->GetInstalledFont( nIndex );
*pbsFontName = CStringW( pFontInfo->m_wsFontName ).AllocSysString();
*pbsFontStyle = CStringW( pFontInfo->m_wsStyle ).AllocSysString();
*pbsFontPath = CStringW( pFontInfo->m_wsFontPath ).AllocSysString();
*plIndex = pFontInfo->m_lIndex;
*pbBold = pFontInfo->m_bBold;
*pbItalic = pFontInfo->m_bItalic;
return S_OK;
}
};