Files
core/ASCOfficePDFWriter/PdfWriterLib/PdfWriterRenderer.cpp
Elen.Subbotina 12dee7dfc5 JBig2 в PdfWriter
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62533 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-21 00:02:29 +03:00

3137 lines
88 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "PdfWriterLib.h"
#if defined(_WIN32) || defined (_WIN64)
#include <atlbase.h>
#include <atlstr.h>
#else
#include "../../../Common/DocxFormat/Source/Base/ASCString.h"
#endif
#include "../../../DesktopEditor/graphics/Image.h"
//-------- Тип рендерера--------------------------------------------------------------------------
HRESULT CPdfWriterLib::get_Type (LONG *plType)
{
if ( !plType )
return S_FALSE;
*plType = c_nPDFWriter;
return S_OK;
}
//-------- Функции для работы со страницей -------------------------------------------------------
HRESULT CPdfWriterLib::NewPage ()
{
m_bStartSubPath = false;
m_bGStateChange = false;
m_bClipPath = false;
m_dCharSpace = 0.0;
m_oClipCTM.Set( 1, 0, 0, 1, 0, 0 );
m_oBaseTransform.Set( 1, 0, 0, 1, 0, 0 );
m_oPen.SetDefaultParams();
m_oFont.SetDefaultParams();
m_oBrush.SetDefaultParams();
m_oShadow.SetDefaultParams();
m_oEdgeText.SetDefaultParams();
m_oTransform.Reset();
// Заканчиваем последнее состояние
SetState( rendstateNone );
// Сбрасываем состояние
m_oRendererState.Reset();
m_bFirstMoveTo = true;
m_oContiniousText.Reset();
return AddNewPage();
}
HRESULT CPdfWriterLib::put_Height (const double & dHeight)
{
HRESULT hRes = S_OK;
hRes = SetPageHeight( (float) MMToPDFCoords( dHeight )) ;
if (hRes != S_OK)
return hRes;
return S_OK;
}
HRESULT CPdfWriterLib::get_Height (double *pdHeight)
{
HRESULT hRes = S_OK;
float fHeight = 0;
hRes = GetHeight( &fHeight ) ;
if (hRes != S_OK)
return hRes;
*pdHeight = PDFCoordsToMM( (double)fHeight );
return S_OK;
}
HRESULT CPdfWriterLib::put_Width (const double & dWidth)
{
HRESULT hRes = S_OK;
hRes = SetPageWidth( (float)MMToPDFCoords( dWidth ) );
if ( hRes != S_OK)
return hRes;
return S_OK;
}
HRESULT CPdfWriterLib::get_Width (double *pdWidth)
{
HRESULT hRes = S_OK;
float fWidth = 0;
hRes = GetWidth( &fWidth );
if ( hRes != S_OK)
return hRes;
*pdWidth = PDFCoordsToMM( (double)fWidth );
return S_OK;
}
HRESULT CPdfWriterLib::get_DpiX (double *pdDpiX)
{
*pdDpiX = 72.0;
return S_OK;
}
HRESULT CPdfWriterLib::get_DpiY (double *pdDpiY)
{
*pdDpiY = 72.0;
return S_OK;
}
//-------- Функции для работы с Pen --------------------------------------------------------------
//HRESULT CPdfWriterLib::SetPen (std::wstring bsXML)
//{
// CString strXML( bsXML );
// m_oPen.FromXmlString( strXML );
// m_bGStateChange = true;
//
// return S_OK;
//}
HRESULT CPdfWriterLib::get_PenColor (LONG *plColor)
{
*plColor = m_oPen.Color;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenColor (const LONG & lColor)
{
m_bGStateChange = true;
m_oPen.Color = lColor;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenAlpha (LONG *plAlpha)
{
*plAlpha = m_oPen.Alpha;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenAlpha (const LONG & lAlpha)
{
m_bGStateChange = true;
m_oPen.Alpha = lAlpha;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenSize (double *pdSize)
{
*pdSize = m_oPen.Size;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenSize (const double & dSize)
{
m_bGStateChange = true;
m_oPen.Size = dSize;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenDashStyle (BYTE *pnStyle)
{
*pnStyle = m_oPen.DashStyle;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenDashStyle (const BYTE & nStyle)
{
m_bGStateChange = true;
m_oPen.DashStyle = nStyle;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenLineStartCap (BYTE *pnStartCap)
{
*pnStartCap = m_oPen.LineStartCap;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenLineStartCap (const BYTE & nStartCap)
{
m_bGStateChange = true;
m_oPen.LineStartCap = nStartCap;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenLineEndCap (BYTE *pnEndCap)
{
*pnEndCap = m_oPen.LineEndCap;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenLineEndCap (const BYTE & nEndCap)
{
m_bGStateChange = true;
m_oPen.LineEndCap = nEndCap;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenLineJoin (BYTE *pnJointStyle)
{
*pnJointStyle = m_oPen.LineJoin;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenLineJoin (const BYTE & nJointStyle)
{
m_bGStateChange = true;
m_oPen.LineJoin = nJointStyle;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenDashOffset (double *pdOffset)
{
*pdOffset = m_oPen.DashOffset;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenDashOffset (const double & dOffset)
{
m_bGStateChange = true;
m_oPen.DashOffset = dOffset;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenAlign (LONG *plAlign)
{
*plAlign = m_oPen.Align;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenAlign (const LONG & lAlign)
{
m_bGStateChange = true;
m_oPen.Align = lAlign;
return S_OK;
}
HRESULT CPdfWriterLib::get_PenMiterLimit (double *pdMiterLimit)
{
*pdMiterLimit = m_oPen.MiterLimit;
return S_OK;
}
HRESULT CPdfWriterLib::put_PenMiterLimit (const double & dMiterLimit)
{
m_bGStateChange = true;
m_oPen.MiterLimit = dMiterLimit;
return S_OK;
}
HRESULT CPdfWriterLib::PenDashPattern (double * pPattern, LONG lCount)
{
m_bGStateChange = true;
m_oPen.SetDashPattern( pPattern, lCount );
return S_OK;
}
//-------- Функции для работы с Brush ------------------------------------------------------------
//HRESULT CPdfWriterLib::SetBrush (std::wstring bsXML)
//{
// CString strXML( bsXML );
// m_oBrush.FromXmlString( strXML );
// m_bGStateChange = true;
//
// return S_OK;
//}
HRESULT CPdfWriterLib::get_BrushType (LONG *plType)
{
*plType = m_oBrush.Type;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushType (const LONG & lType)
{
m_bGStateChange = true;
m_oBrush.Type = lType;
return S_OK;
}
HRESULT CPdfWriterLib::get_BrushColor1 (LONG *plColor)
{
*plColor = m_oBrush.Color1;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushColor1 (const LONG & lColor)
{
m_bGStateChange = true;
m_oBrush.Color1 = lColor;
return S_OK;
}
HRESULT CPdfWriterLib::get_BrushAlpha1 (LONG *plAlpha)
{
*plAlpha = m_oBrush.Alpha1;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushAlpha1 (const LONG & lAlpha)
{
m_bGStateChange = true;
m_oBrush.Alpha1 = lAlpha;
return S_OK;
}
HRESULT CPdfWriterLib::get_BrushColor2 (LONG *plColor)
{
*plColor = m_oBrush.Color2;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushColor2 (const LONG & lColor)
{
m_bGStateChange = true;
m_oBrush.Color2 = lColor;
return S_OK;
}
HRESULT CPdfWriterLib::get_BrushAlpha2 (LONG *plAlpha)
{
*plAlpha = m_oBrush.Alpha2;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushAlpha2 (const LONG & lAlpha)
{
m_bGStateChange = true;
m_oBrush.Alpha2 = lAlpha;
return S_OK;
}
HRESULT CPdfWriterLib::get_BrushTexturePath (std::wstring *pbsPath)
{
*pbsPath = m_oBrush.TexturePath;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushTexturePath (const std::wstring & bsPath)
{
m_bGStateChange = true;
m_oBrush.TexturePath = bsPath;
return S_OK;
}
HRESULT CPdfWriterLib::get_BrushTextureMode (LONG *plMode)
{
*plMode = m_oBrush.TextureMode;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushTextureMode (const LONG & lMode)
{
m_bGStateChange = true;
m_oBrush.TextureMode = lMode;
if (c_BrushTextureModeTile == m_oBrush.TextureMode)
m_oPatternState.SetTileMode(true);
return S_OK;
}
HRESULT CPdfWriterLib::get_BrushTextureAlpha (LONG *plTxAlpha)
{
*plTxAlpha = m_oBrush.TextureAlpha;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushTextureAlpha (const LONG & lTxAlpha)
{
m_bGStateChange = true;
m_oBrush.TextureAlpha = lTxAlpha;
return S_OK;
}
HRESULT CPdfWriterLib::get_BrushLinearAngle (double *pdAngle)
{
*pdAngle = m_oBrush.LinearAngle;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushLinearAngle (const double & dAngle)
{
m_bGStateChange = true;
m_oBrush.LinearAngle = dAngle;
return S_OK;
}
HRESULT CPdfWriterLib::BrushRect (const INT & bVal, const double & dLeft, const double & dTop, const double & dWidth, const double & dHeight)
{
m_oBrush.Rectable = bVal;
m_oBrush.Rect.X = (float)dLeft;
m_oBrush.Rect.Y = (float)dTop;
m_oBrush.Rect.Width = (float)dWidth;
m_oBrush.Rect.Height = (float)dHeight;
return S_OK;
}
HRESULT CPdfWriterLib::BrushBounds(const double& left, const double& top, const double& width, const double& height)
{
m_oBrush.Bounds.left = left;
m_oBrush.Bounds.top = top;
m_oBrush.Bounds.right = left + width;
m_oBrush.Bounds.bottom = top + height;
return S_OK;
}
//-------- Функции для работы с Шрифтом ----------------------------------------------------------
//HRESULT CPdfWriterLib::SetFont (std::wstring bsXML)
//{
// CString strXML( bsXML );
// m_oFont.FromXmlString( strXML );
//
// //if ( m_bCurFontGIDString && !m_bEncoderGID )
// //{
// // bool bNew = false;
//
// // wchar_t wsString[255];
// // for ( int nCode = 1; nCode < 256; nCode++ )
// // {
// // wsString[nCode - 1] = nCode;
// // }
// // FindEncoderForString( m_pDocument, (std::wstring)wsString ,&bNew);
// //}
// //unsigned long unRes = GdiFontToPdfFont(/*L""*/(CStringW(L"qwertyuiop[]';lkjhgfdsazxcvbnm,./QWERTYUIOP{}\":LKJHGFDSAZXCVBNM<>?ЙЦУКЕНГШЩЗХЪЭЖДЛОРПАВЫФЯЧСМИТЬБЮ,.юбьтимсчяфывапролджэъхзщшгнекуцйЁё1234567890-=+_ (*?:%;№!qwertyuiop[]';lkjhgfdsazxcvbnm,./QWERTYUIOP{}\":LKJHGFDSAZXCVBNM<>?ЙЦУКЕНГ ")).AllocSysString(), true);
// //if ( S_OK != unRes )
// // return unRes;
//
// //if ( !m_pFontEncodingList )
// // m_pFontEncodingList = ListNew( m_pDocument->oMMgr, DEF_ITEMS_PER_BLOCK );
//
// //TFontEncodingPair *pPair = new TFontEncodingPair;
// //const char *sPdfFontName = FontGetFontName( m_pCurrentFont );
// //const char *sRealFontName = FontGetFontName( m_pCurrentFont, true );
// //const char *sEncodingName = FontGetEncodingName( m_pCurrentFont );
//
// //UtilsMemCpy( (BYTE *)pPair->sPdfFontName, (BYTE *)sPdfFontName, LIMIT_MAX_NAME_LEN + 1 );
// //UtilsMemCpy( (BYTE *)pPair->sRealFontName, (BYTE *)sRealFontName, LIMIT_MAX_NAME_LEN + 1 );
// //UtilsMemCpy( (BYTE *)pPair->sEncodingName, (BYTE *)sEncodingName, LIMIT_MAX_NAME_LEN + 1 );
//
// //ListAdd( m_pFontEncodingList, pPair );
//
// return S_OK;
//
//}
HRESULT CPdfWriterLib::get_FontName (std::wstring *pbsName)
{
*pbsName = m_oFont.Name;
return S_OK;
}
HRESULT CPdfWriterLib::put_FontName (const std::wstring & bsName)
{
m_oFont.Name = bsName;
return S_OK;
}
HRESULT CPdfWriterLib::get_FontPath (std::wstring *pbsPath)
{
*pbsPath = m_oFont.Path;
return S_OK;
}
HRESULT CPdfWriterLib::put_FontPath (const std::wstring & bsName)
{
m_oFont.Path = bsName ;
//todooo переписать нужно ... типо OOX:CPath
string_replaceAll(m_oFont.Path, _T("\\\\") , _T("\\"));
string_replaceAll(m_oFont.Path, _T("\\\\") , _T("\\"));
string_replaceAll(m_oFont.Path, _T("//") , _T("/"));
string_replaceAll(m_oFont.Path, _T("//") , _T("/"));
return S_OK;
}
HRESULT CPdfWriterLib::get_FontSize (double *pdSize)
{
*pdSize = m_oFont.Size;
return S_OK;
}
HRESULT CPdfWriterLib::put_FontSize (const double & dSize)
{
m_oFont.Size = dSize;
return S_OK;
}
HRESULT CPdfWriterLib::get_FontStyle (LONG *plStyle)
{
*plStyle = m_oFont.GetStyle();
return S_OK;
}
HRESULT CPdfWriterLib::put_FontStyle (const LONG & lStyle)
{
m_oFont.SetStyle( lStyle );
return S_OK;
}
HRESULT CPdfWriterLib::get_FontStringGID (INT *pbGID)
{
*pbGID = m_oFont.StringGID;
return S_OK;
}
HRESULT CPdfWriterLib::put_FontStringGID (const INT & bGID)
{
m_oFont.StringGID = bGID;
return S_OK;
}
HRESULT CPdfWriterLib::get_FontCharSpace (double *pdSpace)
{
if ( !pdSpace )
return S_FALSE;
*pdSpace = PDFCoordsToMM( m_dCharSpace );
return S_OK;
}
HRESULT CPdfWriterLib::put_FontCharSpace (const double & dSpace)
{
m_dCharSpace = MMToPDFCoords( dSpace );
return S_OK;
}
HRESULT CPdfWriterLib::get_FontFaceIndex(int* lFaceIndex)
{
*lFaceIndex = m_oFont.FaceIndex;
return S_OK;
}
HRESULT CPdfWriterLib::put_FontFaceIndex(const int& lFaceIndex)
{
m_oFont.FaceIndex = lFaceIndex;
return S_OK;
}
HRESULT CPdfWriterLib::put_BrushGradientColors(LONG* lColors, double* pPositions, LONG nCount)
{
return S_OK;
}
//-------- Функции для работы с Shadow -----------------------------------------------------------
//HRESULT CPdfWriterLib::SetShadow (std::wstring bsXML)
//{
// CString strXML( bsXML );
// m_oShadow.FromXmlString( strXML );
//
// return S_OK;
//}
HRESULT CPdfWriterLib::get_ShadowDistanceX (double *pdX)
{
*pdX = m_oShadow.DistanceX;
return S_OK;
}
HRESULT CPdfWriterLib::put_ShadowDistanceX (const double &dX)
{
m_oShadow.DistanceX = dX;
return S_OK;
}
HRESULT CPdfWriterLib::get_ShadowDistanceY (double *pdY)
{
*pdY = m_oShadow.DistanceY;
return S_OK;
}
HRESULT CPdfWriterLib::put_ShadowDistanceY (const double &dY)
{
m_oShadow.DistanceY = dY;
return S_OK;
}
HRESULT CPdfWriterLib::get_ShadowBlurSize (double *pdSize)
{
*pdSize = m_oShadow.BlurSize;
return S_OK;
}
HRESULT CPdfWriterLib::put_ShadowBlurSize (const double &dSize)
{
m_oShadow.BlurSize = dSize;
return S_OK;
}
HRESULT CPdfWriterLib::get_ShadowColor (LONG *plColor)
{
*plColor = m_oShadow.Color;
return S_OK;
}
HRESULT CPdfWriterLib::put_ShadowColor (const LONG &lColor)
{
m_oShadow.Color = lColor;
return S_OK;
}
HRESULT CPdfWriterLib::get_ShadowAlpha (LONG *plAlpha)
{
*plAlpha = m_oShadow.Alpha;
return S_OK;
}
HRESULT CPdfWriterLib::put_ShadowAlpha (const LONG &lAlpha)
{
m_oShadow.Alpha = lAlpha;
return S_OK;
}
HRESULT CPdfWriterLib::get_ShadowVisible (bool *pbVisible)
{
*pbVisible = m_oShadow.Visible;
return S_OK;
}
HRESULT CPdfWriterLib::put_ShadowVisible (const bool &bVisible)
{
m_oShadow.Visible = bVisible;
return S_OK;
}
//-------- Функции для работы с Edge Text --------------------------------------------------------
//HRESULT CPdfWriterLib::SetEdgeText (std::wstring bsXML)
//{
// CString strXML( bsXML );
// m_oEdgeText.FromXmlString( strXML );
//
// return S_OK;
//}
HRESULT CPdfWriterLib::get_EdgeVisible (LONG *plVisible)
{
*plVisible = m_oEdgeText.Visible;
return S_OK;
}
HRESULT CPdfWriterLib::put_EdgeVisible (const LONG &lVisible)
{
m_oEdgeText.Visible = lVisible;
return S_OK;
}
HRESULT CPdfWriterLib::get_EdgeColor (LONG *plColor)
{
*plColor = m_oEdgeText.Color;
return S_OK;
}
HRESULT CPdfWriterLib::put_EdgeColor (const LONG &lColor)
{
m_oEdgeText.Color = lColor;
return S_OK;
}
HRESULT CPdfWriterLib::get_EdgeAlpha (LONG *plAlpha)
{
*plAlpha = m_oEdgeText.Alpha;
return S_OK;
}
HRESULT CPdfWriterLib::put_EdgeAlpha (const LONG &lAlpha)
{
m_oEdgeText.Alpha = lAlpha;
return S_OK;
}
HRESULT CPdfWriterLib::get_EdgeDist (double *pdDist)
{
*pdDist = m_oEdgeText.Dist;
return S_OK;
}
HRESULT CPdfWriterLib::put_EdgeDist (const double &dDist)
{
m_oEdgeText.Dist = dDist;
return S_OK;
}
//--------- Функции для вывода текста ------------------------------------------------------------
HRESULT CPdfWriterLib::CommandDrawTextCHAR(const LONG& c, const double& x, const double& y, const double& w, const double& h, const double& baselineOffset)
{
//if (c_nHyperlinkType == m_lCurrentCommandType)
// return S_OK;
//put_BrushType(c_BrushTypeSolid);
//
//_SetFont();
//Aggplus::CBrush* pBrush = CreateBrush(&m_oBrush);
//m_pRenderer->DrawStringC(c, m_pFontManager, pBrush, x, y + baselineOffset);
//
//RELEASEOBJECT(pBrush);
return S_OK;
}
HRESULT CPdfWriterLib::CommandDrawTextExCHAR(const LONG& c, const LONG& gid, const double& x, const double& y, const double& w, const double& h, const double& baselineOffset, const DWORD& lFlags)
{
if (gid >= 0)
{
m_oFont.StringGID = true;
return CommandDrawTextCHAR(gid, x, y, w, h, baselineOffset);
}
m_oFont.StringGID = false;
return CommandDrawTextCHAR(c, x, y, w, h, baselineOffset);
}
HRESULT CPdfWriterLib::CommandDrawText (const std::wstring & bsText,const double & fX,const double &fY,
const double & fWidth, const double & fHeight, const double & fBaseLineOffset)
{
HRESULT hRes = S_OK;
// Работа с сылками тоже проходит с помощью функции CommandDrawText
if ( c_nHyperlinkType == m_pCurCommand->nType )
{
SetState( rendstateNone );
hRes = MakeAnnotationFromXml( std_string2string(bsText));
if ( hRes != S_OK)
return hRes;
return S_OK;
}
if ( c_nClipType != m_pCurCommand->nType )
{
m_oContiniousText.Add( std_string2string(bsText), std_string2string(bsText),
fX, fY, fWidth, fHeight, fBaseLineOffset, false, m_oFont, m_oBrush, m_oTransform, m_dCharSpace );
SetState( rendstateText );
return S_OK;
}
else
{
SetState( rendstateClipText );
}
//CSynchAccess oSynchAccess = m_hSynchMutex;
// Работа с сылками тоже проходит с помощью функции CommandDrawText
if ( c_nHyperlinkType == m_pCurCommand->nType )
{
hRes = MakeAnnotationFromXml( std_string2string(bsText));
if ( hRes != S_OK)
return hRes;
return S_OK;
}
// Переводим в миллиметры
double fX1 = MMToPDFCoords( fX );
double fY1 = MMToPDFCoords( fY );
double fWidth1 = MMToPDFCoords( fWidth );
double fHeight1 = MMToPDFCoords( fHeight );
double fBaseLineOffset1 = MMToPDFCoords( fBaseLineOffset );
PToUnicode pToUnicode = FindToUnicodeForString( m_pDocument, bsText );
if ( !pToUnicode )
return S_OK;
std::wstring bsCodedString;
bool bResult = ToUnicodeWCharToString( pToUnicode, bsText, bsCodedString );
// Запоминаем значения Bold и Italic, потому что в функции GdiFontToPdfFont они могут измениться
bool bOldBold = m_oFont.Bold;
bool bOldItalic = m_oFont.Italic;
bool bDefaultFont = false;
CString name(pToUnicode->sName);//ansi to unicode todooo
hRes = GdiFontToPdfFont2( name , _T("") ) ;
if ( hRes != S_OK)
{
if ( AVS_OFFICEPDFWRITER_ERROR_FONT_NOT_FOUND == hRes )
{
ResetError( m_pDocument );
bsCodedString = std_string2string( bsText );
bDefaultFont = true;
}
else
{
return hRes;
}
}
long nAscent = 0;
long nDescent = 0;
long nXHeight = 0;
double dItalicAngle = 3.141592f / 12;
float fPageHeight = 0.0f;
hRes = GetHeight( &fPageHeight );
if ( hRes != S_OK)
return hRes;
if ( !m_oFont.Italic )
dItalicAngle = 0;
float fFontSize = (float)m_oFont.Size;
hRes = GetFontAscent( &nAscent );
if ( hRes != S_OK)
return hRes;
hRes = GetFontDescent( &nDescent );
if ( hRes != S_OK)
return hRes;
hRes = GetFontXHeight( &nXHeight );
if ( hRes != S_OK)
return hRes;
// Выясним как нам рисовать текст
ETextRenderingMode eRenderingMode = ETextRenderingMode::Fill; // Fill (по умолчанию)
if ( c_nStrokeTextType == m_pCurCommand->nType )
eRenderingMode = ETextRenderingMode::Stroke; // Stroke
if ( c_nClipType == m_pCurCommand->nType )
{
// ATLTRACE2( _T( "TextClip" ) );
eRenderingMode = ETextRenderingMode::Clipping; // Clip
}
float fXHeight = (float)nXHeight / 1000;
float fAscent = (float)nAscent / 1000;
float fDescent = fabs( (float)nDescent / 1000 );
long nColor1 = m_oBrush.Color1;
float fR = ( nColor1 & 0xFF ) / 255.0f;
float fG = ( ( nColor1 >> 8 ) & 0xFF ) / 255.0f;
float fB = ( nColor1 >> 16 ) / 255.0f;
float fTextWidth = 0.0f;
float fLineWidth = fFontSize / ( bOldBold ? 10.f : 15.0f );
float fOldLineWidth = 0.0f;
hRes = GetLineWidth( &fOldLineWidth );
if ( hRes != S_OK)
return hRes;
float fFillR, fFillG, fFillB, fStrokeR, fStrokeG, fStrokeB;
hRes = GetRGBFill( &fFillR, &fFillG, &fFillB );
if ( hRes != S_OK)
return hRes;
hRes = GetRGBStroke( &fStrokeR, &fStrokeG, &fStrokeB );
if ( hRes != S_OK)
return hRes;
// Рисуем тени
if ( m_oShadow.Visible )
{
//if ( S_OK != ( hRes = GRestore() ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
//ATLTRACE2( _T("GSave: DrawText - Shadow\n") );
hRes = GSave();
if ( hRes != S_OK)
return hRes;
hRes = SetLineWidth( fLineWidth );
if ( hRes != S_OK)
return hRes;
// Выставляем систему координат
hRes = UpdateCoordSpace( );
if ( hRes != S_OK)
return hRes;
double dXShadow = fX1 + MMToPDFCoords( m_oShadow.DistanceX );
double dYShadow = fY1 + MMToPDFCoords( m_oShadow.DistanceY );
long nAlpha = m_oShadow.Alpha;
long nShadowColor = m_oShadow.Color;
float fAlpha = (float)nAlpha / 255.0f;
float fBShadow = ( nShadowColor & 0xFF ) / 255.0f;
float fGShadow = ( ( nShadowColor >> 8 ) & 0xFF ) / 255.0f;
float fRShadow = ( nShadowColor >> 16 ) / 255.0f;
{
XmlUtils::CXmlWriter oWriter;
oWriter.WriteNodeBegin( _T("ExtGState") );
if ( 255 != fAlpha )
{
oWriter.WriteNodeBegin( _T("AlphaFill"), true );
oWriter.WriteAttribute( _T("value"), (double)fAlpha );
oWriter.WriteNodeEnd( _T("AlphaFill"), true, true );
}
if ( 255 != fAlpha )
{
oWriter.WriteNodeBegin( _T("AlphaStroke"), true );
oWriter.WriteAttribute( _T("value"), (double)fAlpha );
oWriter.WriteNodeEnd( _T("AlphaStroke"), true, true );
}
oWriter.WriteNodeEnd( _T("ExtGState") );
CString bsXml = oWriter.GetXmlString();
hRes = SetExtGraphicsState2( bsXml );
if ( hRes != S_OK)
return hRes;
//if ( S_OK != ( hRes = NewExtGraphicsState() ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
////if ( S_OK != ( hRes = ExtGraphicsStateSetBlendMode( EBlendMode::BMOverlay ) ) )
////{
//// ::SysFreeString( bsCodedString );
//// return hRes;
////}
//if ( S_OK != ( hRes = ExtGraphicsStateSetAlphaFill( fAlpha ) ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
//if ( S_OK != ( hRes = ExtGraphicsStateSetAlphaStroke( fAlpha ) ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
//if ( S_OK != ( hRes = SetExtGraphicsState() ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
}
// Выставляем цвет текста и линий
hRes = SetRGBFill( fRShadow, fGShadow, fBShadow );
if ( hRes != S_OK)
return hRes;
hRes = SetRGBStroke( fRShadow, fGShadow, fBShadow );
if ( hRes != S_OK)
return hRes;
hRes = BeginText();
if ( hRes != S_OK)
return hRes;
// Устанавливаем текущий фонт и размер фонта
hRes = SetFontAndSizeToGState( fFontSize ) ;
if ( hRes != S_OK)
return hRes;
// Если данный фонт не нашли с атрибутом Italic, тогда наколняем текст сами на угол dItalicAngle
hRes = SetTextMatrix( 1, (float)tan( 0.0 ), (float)tan( dItalicAngle ), 1, 0, 0 );
if ( hRes != S_OK)
return hRes;
hRes = GetTextWidth( bsCodedString, &fTextWidth );
if ( hRes != S_OK)
return hRes;
if ( eRenderingMode == ETextRenderingMode::Fill )
{
// Если данный фонт не нашли с атрибутом Bold, тогда заливаем и обводим текст, тем самым утолщяя его
if ( m_oFont.Bold )
{
hRes = SetTextRenderingMode((long)ETextRenderingMode::FillThenStroke) ;
if ( hRes != S_OK)
return hRes;
}
else
hRes = SetTextRenderingMode((long)ETextRenderingMode::Fill);
if ( hRes != S_OK)
return hRes;
}
else
{
hRes = SetTextRenderingMode( (long)eRenderingMode ) ;
if ( hRes != S_OK)
return hRes;
}
// Выводим текст
hRes = TextOut_( (float)dXShadow, fPageHeight - (float) (dYShadow + fBaseLineOffset), bsCodedString ) ;
if ( hRes != S_OK)
return hRes;
hRes = EndText() ;
if ( hRes != S_OK)
return hRes;
//// Перечеркивание текста. Текст перечеркиваем по середине буквы 'x'. (См. XHeight)
//if ( m_oFont.Strikeout )
//{
// double dItalicAdd = tan( (double)dItalicAngle ) * fXHeight * fFontSize / 2;
// if ( !m_oFont.Italic )
// dItalicAdd = 0;
// if ( S_OK != ( hRes = MoveTo( (float)dXShadow + dItalicAdd, fPageHeight - (float) ( dYShadow + fBaseLineOffset - fXHeight * fFontSize / 2 ) ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
// if ( S_OK != ( hRes = LineTo( (float)dXShadow + fTextWidth + dItalicAdd, fPageHeight - (float) ( dYShadow + fBaseLineOffset - fXHeight * fFontSize / 2 ) ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
// if ( S_OK != ( hRes = Stroke( ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
//}
//// Подчеркивание текста.
//if ( m_oFont.Underline )
//{
// float fTextWidth = 0.0f;
// float fUnderLineOffset = 3 + fLineWidth / 2;
// if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
// if ( S_OK != ( hRes = MoveTo( (float)dXShadow, fPageHeight - ( (float)dYShadow + fBaseLineOffset + fUnderLineOffset /*fDescent * fFontSize*/ ) ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
// if ( S_OK != ( hRes = LineTo( (float)dXShadow + fTextWidth, fPageHeight - ( (float)dYShadow + fBaseLineOffset + fUnderLineOffset /*fDescent * fFontSize*/ ) ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
// if ( S_OK != ( hRes = Stroke( ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
//}
// ATLTRACE2( _T("GRestore: DrawText - Shadow\n") );
hRes = GRestore();
if ( hRes != S_OK)
return hRes;
}
//if ( S_OK != ( hRes = GRestore() ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
// Дальше рисуем все, что непосредственно связанно с самим текстом
// Выставляем цвет текста и линий
if ( ETextRenderingMode::Fill == eRenderingMode )
{
hRes = SetRGBFill( fR, fG, fB ) ;
if ( hRes != S_OK)
return hRes;
hRes = SetRGBStroke( fR, fG, fB ) ;
if ( hRes != S_OK)
return hRes;
}
else
{
hRes = SetRGBFill( fR, fG, fB ) ;
if ( hRes != S_OK)
return hRes;
hRes = SetRGBStroke( fR, fG, fB ) ;
return hRes;
}
// Выставляем систему координат
if ( c_nClipType != m_pCurCommand->nType )
{
// ATLTRACE2( _T("GSave: DrawText\n") );
hRes = GSave() ;
if ( hRes != S_OK)
return hRes;
hRes = UpdateCoordSpace( ) ;
if ( hRes != S_OK)
return hRes;
float fAlphaFill = (float)m_oBrush.Alpha1 / 255.0f;
float fAlphaStroke = (float)m_oPen.Alpha / 255.0f;
m_pCurrentExtGState = GetExtGState( m_pDocument, fAlphaStroke, fAlphaFill );
if ( S_OK != ( hRes = PageSetExtGState( m_pDocument->pCurPage, m_pCurrentExtGState ) ) )
return hRes;
}
else
{
if ( S_OK != ( hRes = UpdateCoordSpace( ) ) )
{
return hRes;
}
}
if ( S_OK != ( hRes = BeginText() ) )
{
return hRes;
}
// Устанавливаем межсимвольный интервал
if ( S_OK != ( hRes = SetCharSpace( (float)m_dCharSpace ) ) )
{
return hRes;
}
// Устанавливаем текущий фонт и размер фонта
if ( S_OK != ( hRes = SetFontAndSizeToGState( fFontSize ) ) )
{
return hRes;
}
// Если шрифт не нашли, и используется стандартный шрифт, значит, ширина слов будет неверной.
// Чтобы слова не наползали друг на друга скейлим текст к его реальной ширине.
if ( bDefaultFont )
{
// Измеряем размер
float fTextWidth = 0.0f;
if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
{
return hRes;
}
float fKoef;
if ( fabs( fTextWidth ) < 0.01 )
fKoef = 1;
else
fKoef = fWidth / fTextWidth * 100; // Scale задается в процентах
if ( fKoef > 0.001 )
{
if ( S_OK != ( hRes = SetHorizontalScalling( fKoef ) ) )
{
return hRes;
}
}
}
if ( _T("AVSEmptyFont") == m_oFont.Name )
{
// Данная ветка сделана специально для конвертации Djvu -> PDF
float fVKoef;
if ( fabs( m_oFont.Size ) < 0.01 )
fVKoef = 1;
else
fVKoef = fHeight / m_oFont.Size;
// Если данный фонт не нашли с атрибутом Italic, тогда наколняем текст сами на угол dItalicAngle
if ( S_OK != ( hRes = SetTextMatrix( 1, (float)tan( 0.0 ), (float)fVKoef * tan( dItalicAngle ), fVKoef * 1, 0, 0 ) ) )
{
return hRes;
}
}
else
{
// Если данный фонт не нашли с атрибутом Italic, тогда наколняем текст сами на угол dItalicAngle
if ( S_OK != ( hRes = SetTextMatrix( 1, (float)tan( 0.0 ), (float)tan( dItalicAngle ), 1, 0, 0 ) ) )
{
return hRes;
}
}
if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
{
return hRes;
}
if ( ETextRenderingMode::Fill == eRenderingMode )
{
// Если данный фонт не нашли с атрибутом Bold, тогда заливаем и обводим текст, тем самым утолщяя его
if ( m_oFont.Bold )
{
if ( S_OK != ( hRes = SetTextRenderingMode((long)ETextRenderingMode::FillThenStroke) ) )
{
return hRes;
}
}
else
if ( S_OK != ( hRes = SetTextRenderingMode((long)ETextRenderingMode::Fill) ) )
{
return hRes;
}
}
else
{
if ( S_OK != ( hRes = SetTextRenderingMode( (long)eRenderingMode ) ) )
{
return hRes;
}
}
// Выводим текст
if ( S_OK != ( hRes = TextOut_( (float)fX, fPageHeight - (float) (fY + fBaseLineOffset), bsCodedString )))
return hRes;
if ( S_OK != ( hRes = EndText() ) )
{
return hRes;
}
//if ( S_OK != ( hRes = SetLineWidth( fLineWidth ) ) )
//{
// return hRes;
//}
//// Перечеркивание текста. Текст перечеркиваем по середине буквы 'x'. (См. XHeight)
//if ( m_oFont.Strikeout )
//{
// double dItalicAdd = tan( (double)dItalicAngle ) * fXHeight * fFontSize / 2;
// if ( !m_oFont.Italic )
// dItalicAdd = 0;
// if ( S_OK != ( hRes = MoveTo( (float)fX + dItalicAdd, fPageHeight - (float) ( fY + fBaseLineOffset - fXHeight * fFontSize / 2 ) ) ) )
// {
// return hRes;
// }
// if ( S_OK != ( hRes = LineTo( (float)fX + fTextWidth + dItalicAdd, fPageHeight - (float) ( fY + fBaseLineOffset - fXHeight * fFontSize / 2 ) ) ) )
// {
// return hRes;
// }
// if ( S_OK != ( hRes = Stroke( ) ) )
// {
// return hRes;
// }
// //MoveTo(dX, dY - fDescent * fFontSize );
// //LineTo(dX + dItalicAdd * 2, dY + fFontSize * ( 1 - fDescent ) );
// //LineTo(dX + fTextWidth + dItalicAdd * 2, dY + fFontSize * ( 1 - fDescent ) );
// //LineTo(dX + fTextWidth, dY - fDescent * fFontSize );
// //LineTo(dX, dY - fDescent * fFontSize );
// //Stroke();
//}
//// Подчеркивание текста.
//if ( m_oFont.Underline )
//{
// float fTextWidth = 0.0f;
// float fUnderLineOffset = 3 + fLineWidth / 2;
// if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
// if ( S_OK != ( hRes = MoveTo( (float)fX, fPageHeight - (float) (fY + fBaseLineOffset + fUnderLineOffset) /*fDescent * fFontSize*/ ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
// if ( S_OK != ( hRes = LineTo( (float)fX + fTextWidth, fPageHeight - (float) (fY + fBaseLineOffset + fUnderLineOffset) /*fDescent * fFontSize*/ ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
// if ( S_OK != ( hRes = Stroke( ) ) )
// {
// ::SysFreeString( bsCodedString );
// return hRes;
// }
//}
// Восстанавливаем систему координат
if ( c_nClipType != m_pCurCommand->nType )
{
// ATLTRACE2( _T("GRestore: DrawText\n") );
if ( S_OK != ( hRes = GRestore() ) )
return hRes;
}
else
{
float fDelta = m_oClipCTM.fA * m_oClipCTM.fD - m_oClipCTM.fB * m_oClipCTM.fC;
if ( 0.0f != fDelta )
{
float fIDelta = 1 / fDelta;
float fA = fIDelta * m_oClipCTM.fD;
float fB = fIDelta * ( -m_oClipCTM.fB );
float fC = fIDelta * ( -m_oClipCTM.fC );
float fD = fIDelta * m_oClipCTM.fA;
float fE = fIDelta * (m_oClipCTM.fC * m_oClipCTM.fF - m_oClipCTM.fE * m_oClipCTM.fD);
float fF = fIDelta * (m_oClipCTM.fE * m_oClipCTM.fB - m_oClipCTM.fA * m_oClipCTM.fF);
// Делаем матрицу CTM единичной
if ( S_OK != ( hRes = Concat( fA, fB, fC, fD, fE, fF ) ) )
return hRes;
}
m_oClipCTM.Set( 1, 0, 0, 1, 0, 0 );
}
// Восстанавливаем старые настройки
if ( S_OK != ( hRes = SetLineWidth( fOldLineWidth ) ) )
return hRes;
if ( S_OK != ( hRes = SetRGBFill( fFillR, fFillG, fFillB ) ) )
return hRes;
if ( S_OK != ( hRes = SetRGBStroke( fStrokeR, fStrokeG, fStrokeB ) ) )
return hRes;
m_oFont.Bold = bOldBold;
m_oFont.Italic = bOldItalic;
return S_OK;
}
HRESULT CPdfWriterLib::CommandDrawTextEx (const std::wstring & bsUnicodeText,const std::wstring & bsGidText,
/*const std::wstring & bsSrcCodeText, */const double & fX1,const double & fY1,
const double & fWidth1, const double & fHeight1, const double & fBaseLineOffset1,const DWORD & nFlags)
{
// TODO: Сделать обработку DrawTextEx тоже через Состояния рендерера
SetState( rendstateNone );
if ( bsUnicodeText.length()<1/* && !bsSrcCodeText*/ )
return S_OK;
//CSynchAccess oSynchAccess = m_hSynchMutex;
HRESULT hRes = S_OK;
// Работа с сылками тоже проходит с помощью функции CommandDrawText
if ( c_nHyperlinkType == m_pCurCommand->nType )
{
if ( S_OK != ( hRes = MakeAnnotationFromXml( std_string2string(bsUnicodeText) ) ) )
return hRes;
return S_OK;
}
// Переводим в миллиметры
double fX = MMToPDFCoords( fX1 );
double fY = MMToPDFCoords( fY1 );
double fWidth = MMToPDFCoords( fWidth1 );
double fHeight = MMToPDFCoords( fHeight1 );
double fBaseLineOffset = MMToPDFCoords( fBaseLineOffset1 );
std::wstring bsCodedString;
// Запоминаем значения Bold и Italic, потому что в функции GdiFontToPdfFont они могут измениться
bool bOldBold = m_oFont.Bold;
bool bOldItalic = m_oFont.Italic;
bool bDefaultFont = false;
//todooo непонятка с заданием имени пути к файлу bsSrcCodeText !!! ?????
// Проверяем как задан шрифт, через путь к файлу, или по имени
//if ( _T("") != m_oFont.Path )
//{
//XmlUtils::CXmlNode oNode;
//oNode.FromXmlString( CString(bsSrcCodeText) ); //?????
//// TO DO: Пока если шрифт задан путем, значит он пришел из PDF, как только
//// появится другой формат, с внедренными шрифтами, доделать тут.
//if ( _T("PDF-Text") == oNode.GetName() )
//{
// // Загружаем шрифт и кодировки
// if ( S_OK != ( hRes = FontFromFileToPdfFont() ) )
// {
// return hRes;
// }
// int nCode = 0, nCID = 0;
// if ( FontDefCID == ((FontAttr)m_pCurrentFont->pAttr)->pFontDef->eType )
// {
// int nCID;
// nCID = XmlUtils::GetInteger( oNode.GetAttribute( _T("cid") ) );
// nCode = XmlUtils::GetInteger( oNode.GetAttribute( _T("code") ) );
// int nLen = XmlUtils::GetInteger( oNode.GetAttribute( _T("len") ) );
// char pBuffer[4];
// pBuffer[0] = (char) (nCode >> 24);
// pBuffer[1] = (char) (nCode >> 16);
// pBuffer[2] = (char) (nCode >> 8);
// pBuffer[3] = (char) nCode;
// CMapEncoderStreamAddCIDtoCode( ((FontAttr)m_pCurrentFont->pAttr)->pEncoder, nCID, pBuffer ,nLen );
// bsCodedString = std::wstring(( wchar_t )(nCID));
// }
// else
// {
// nCode = XmlUtils::GetInteger( oNode.GetAttribute( _T("code") ) );
// bsCodedString = std::wstring( wchar_t(nCode) );
// }
//}
// else
// {
// return S_OK;
// }
//}
//else
{
PToUnicode pToUnicode = FindToUnicodeForString( m_pDocument, bsUnicodeText );
if ( !pToUnicode )
return S_OK;
std::wstring sCodedString;
bool bResult = ToUnicodeWCharToString( pToUnicode, bsUnicodeText, sCodedString );
CString name(pToUnicode->sName);//ansi to unicode todooo
//todooo
if ( S_OK != ( hRes = GdiFontToPdfFont2( name, _T("") ) ) )
{
if ( AVS_OFFICEPDFWRITER_ERROR_FONT_NOT_FOUND == hRes )
{
ResetError( m_pDocument );
sCodedString = std_string2string( bsUnicodeText );
bDefaultFont = true;
}
else
{
return hRes;
}
}
bsCodedString = sCodedString;
}
long nAscent = 0;
long nDescent = 0;
long nXHeight = 0;
double dItalicAngle = 3.141592f / 12;
float fPageHeight = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
{
return hRes;
}
if ( !m_oFont.Italic )
dItalicAngle = 0;
float fFontSize = (float)m_oFont.Size;
if ( S_OK != ( hRes = GetFontAscent( &nAscent ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = GetFontDescent( &nDescent ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = GetFontXHeight( &nXHeight ) ) )
{
return hRes;
}
// Выясним как нам рисовать текст
ETextRenderingMode eRenderingMode = ETextRenderingMode::Fill; // Fill (по умолчанию)
if ( c_nStrokeTextType == m_pCurCommand->nType )
eRenderingMode = ETextRenderingMode::Stroke; // Stroke
if ( c_nClipType == m_pCurCommand->nType )
{
// ATLTRACE2( _T( "TextClip" ) );
eRenderingMode = ETextRenderingMode::Clipping; // Clip
}
float fXHeight = (float)nXHeight / 1000;
float fAscent = (float)nAscent / 1000;
float fDescent = fabs( (float)nDescent / 1000 );
long nColor1 = m_oBrush.Color1;
float fR = ( nColor1 & 0xFF ) / 255.0f;
float fG = ( ( nColor1 >> 8 ) & 0xFF ) / 255.0f;
float fB = ( nColor1 >> 16 ) / 255.0f;
float fTextWidth = 0.0f;
float fLineWidth = fFontSize / ( bOldBold ? 10.f : 15.0f );
float fOldLineWidth = 0.0f;
if ( S_OK != ( hRes = GetLineWidth( &fOldLineWidth ) ) )
{
return hRes;
}
float fFillR, fFillG, fFillB, fStrokeR, fStrokeG, fStrokeB;
if ( S_OK != ( hRes = GetRGBFill( &fFillR, &fFillG, &fFillB ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = GetRGBStroke( &fStrokeR, &fStrokeG, &fStrokeB ) ) )
{
return hRes;
}
// Рисуем тени
if ( m_oShadow.Visible )
{
//if ( S_OK != ( hRes = GRestore() ) )
//{
// return hRes;
//}
// ATLTRACE2( _T("GSave: DrawText - Shadow\n") );
if ( S_OK != ( hRes = GSave() ) )
{
return hRes;
}
if ( S_OK != ( hRes = SetLineWidth( fLineWidth ) ) )
{
return hRes;
}
// Выставляем систему координат
if ( S_OK != ( hRes = UpdateCoordSpace( ) ) )
{
return hRes;
}
double dXShadow = fX + MMToPDFCoords( m_oShadow.DistanceX );
double dYShadow = fY + MMToPDFCoords( m_oShadow.DistanceY );
long nAlpha = m_oShadow.Alpha;
long nShadowColor = m_oShadow.Color;
float fAlpha = (float)nAlpha / 255.0f;
float fBShadow = ( nShadowColor & 0xFF ) / 255.0f;
float fGShadow = ( ( nShadowColor >> 8 ) & 0xFF ) / 255.0f;
float fRShadow = ( nShadowColor >> 16 ) / 255.0f;
{
XmlUtils::CXmlWriter oWriter;
oWriter.WriteNodeBegin( _T("ExtGState") );
if ( 255 != fAlpha )
{
oWriter.WriteNodeBegin( _T("AlphaFill"), true );
oWriter.WriteAttribute( _T("value"), (double)fAlpha );
oWriter.WriteNodeEnd( _T("AlphaFill"), true, true );
}
if ( 255 != fAlpha )
{
oWriter.WriteNodeBegin( _T("AlphaStroke"), true );
oWriter.WriteAttribute( _T("value"), (double)fAlpha );
oWriter.WriteNodeEnd( _T("AlphaStroke"), true, true );
}
oWriter.WriteNodeEnd( _T("ExtGState") );
CString bsXml = oWriter.GetXmlString();
if ( S_OK != ( hRes = SetExtGraphicsState2( bsXml ) ) )
{
return hRes;
}
//if ( S_OK != ( hRes = NewExtGraphicsState() ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
////if ( S_OK != ( hRes = ExtGraphicsStateSetBlendMode( EBlendMode::BMOverlay ) ) )
////{
//// ::SysFreeString( bsCodedString );
//// return hRes;
////}
//if ( S_OK != ( hRes = ExtGraphicsStateSetAlphaFill( fAlpha ) ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
//if ( S_OK != ( hRes = ExtGraphicsStateSetAlphaStroke( fAlpha ) ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
//if ( S_OK != ( hRes = SetExtGraphicsState() ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
}
// Выставляем цвет текста и линий
if ( S_OK != ( hRes = SetRGBFill( fRShadow, fGShadow, fBShadow ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = SetRGBStroke( fRShadow, fGShadow, fBShadow ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = BeginText() ) )
{
return hRes;
}
// Устанавливаем текущий фонт и размер фонта
if ( S_OK != ( hRes = SetFontAndSizeToGState( fFontSize ) ) )
{
return hRes;
}
// Если данный фонт не нашли с атрибутом Italic, тогда наколняем текст сами на угол dItalicAngle
if ( S_OK != ( hRes = SetTextMatrix( 1, (float)tan( 0.0 ), (float)tan( dItalicAngle ), 1, 0, 0 ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
{
return hRes;
}
if ( eRenderingMode == ETextRenderingMode::Fill )
{
// Если данный фонт не нашли с атрибутом Bold, тогда заливаем и обводим текст, тем самым утолщяя его
if ( m_oFont.Bold )
{
if ( S_OK != ( hRes = SetTextRenderingMode((long)ETextRenderingMode::FillThenStroke) ) )
{
return hRes;
}
}
else
if ( S_OK != ( hRes = SetTextRenderingMode((long)ETextRenderingMode::Fill) ) )
{
return hRes;
}
}
else
{
if ( S_OK != ( hRes = SetTextRenderingMode( (long)eRenderingMode ) ) )
{
return hRes;
}
}
// Выводим текст
if ( S_OK != ( hRes = TextOut_( (float)dXShadow, fPageHeight - (float) (dYShadow + fBaseLineOffset), bsCodedString ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = EndText() ) )
{
return hRes;
}
// Перечеркивание текста. Текст перечеркиваем по середине буквы 'x'. (См. XHeight)
if ( m_oFont.Strikeout )
{
double dItalicAdd = tan( (double)dItalicAngle ) * fXHeight * fFontSize / 2;
if ( !m_oFont.Italic )
dItalicAdd = 0;
if ( S_OK != ( hRes = MoveTo( (float)dXShadow + dItalicAdd, fPageHeight - (float) ( dYShadow + fBaseLineOffset - fXHeight * fFontSize / 2 ) ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = LineTo( (float)dXShadow + fTextWidth + dItalicAdd, fPageHeight - (float) ( dYShadow + fBaseLineOffset - fXHeight * fFontSize / 2 ) ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = Stroke( ) ) )
{
return hRes;
}
}
// Подчеркивание текста.
if ( m_oFont.Underline )
{
float fTextWidth = 0.0f;
float fUnderLineOffset = 3 + fLineWidth / 2;
if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = MoveTo( (float)dXShadow, fPageHeight - ( (float)dYShadow + fBaseLineOffset + fUnderLineOffset /*fDescent * fFontSize*/ ) ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = LineTo( (float)dXShadow + fTextWidth, fPageHeight - ( (float)dYShadow + fBaseLineOffset + fUnderLineOffset /*fDescent * fFontSize*/ ) ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = Stroke( ) ) )
{
return hRes;
}
}
// ATLTRACE2( _T("GRestore: DrawText - Shadow\n") );
if ( S_OK != ( hRes = GRestore() ) )
{
return hRes;
}
}
//if ( S_OK != ( hRes = GRestore() ) )
//{
// ::SysFreeString( bsCodedString );
// return hRes;
//}
// Дальше рисуем все, что непосредственно связанно с самим текстом
// Выставляем цвет текста и линий
if ( ETextRenderingMode::Fill == eRenderingMode )
{
if ( S_OK != ( hRes = SetRGBFill( fR, fG, fB ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = SetRGBStroke( fR, fG, fB ) ) )
{
return hRes;
}
}
else
{
if ( S_OK != ( hRes = SetRGBFill( fR, fG, fB ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = SetRGBStroke( fR, fG, fB ) ) )
{
return hRes;
}
}
// Выставляем систему координат
if ( c_nClipType != m_pCurCommand->nType )
{
// ATLTRACE2( _T("GSave: DrawText\n") );
if ( S_OK != ( hRes = GSave() ) )
{
return hRes;
}
if ( S_OK != ( hRes = UpdateCoordSpace( ) ) )
{
return hRes;
}
}
else
{
if ( S_OK != ( hRes = UpdateCoordSpace( ) ) )
{
return hRes;
}
}
if ( S_OK != ( hRes = BeginText() ) )
{
return hRes;
}
// Устанавливаем текущий фонт и размер фонта
if ( S_OK != ( hRes = SetFontAndSizeToGState( fFontSize ) ) )
{
return hRes;
}
// Если шрифт не нашли, и используется стандартный шрифт, значит, ширина слов будет неверной.
// Чтобы слова не наползали друг на друга скейлим текст к его реальной ширине.
if ( bDefaultFont )
{
// Измеряем размер
float fTextWidth = 0.0f;
if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
{
return hRes;
}
float fKoef = fWidth / fTextWidth * 100; // Scale задается в процентах
if ( fKoef > 0.001 )
{
if ( S_OK != ( hRes = SetHorizontalScalling( fKoef ) ) )
{
return hRes;
}
}
}
// Если данный фонт не нашли с атрибутом Italic, тогда наколняем текст сами на угол dItalicAngle
if ( S_OK != ( hRes = SetTextMatrix( 1, (float)tan( 0.0 ), (float)tan( dItalicAngle ), 1, 0, 0 ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
{
return hRes;
}
if ( ETextRenderingMode::Fill == eRenderingMode )
{
// Если данный фонт не нашли с атрибутом Bold, тогда заливаем и обводим текст, тем самым утолщяя его
if ( m_oFont.Bold )
{
if ( S_OK != ( hRes = SetTextRenderingMode((long)ETextRenderingMode::FillThenStroke) ) )
{
return hRes;
}
}
else
if ( S_OK != ( hRes = SetTextRenderingMode((long)ETextRenderingMode::Fill) ) )
{
return hRes;
}
}
else
{
if ( S_OK != ( hRes = SetTextRenderingMode( (long)eRenderingMode ) ) )
{
return hRes;
}
}
// Выводим текст
if ( S_OK != ( hRes = TextOut_( (float)fX, fPageHeight - (float) (fY + fBaseLineOffset), bsCodedString ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = EndText() ) )
{
return hRes;
}
if ( S_OK != ( hRes = SetLineWidth( fLineWidth ) ) )
{
return hRes;
}
// Перечеркивание текста. Текст перечеркиваем по середине буквы 'x'. (См. XHeight)
if ( m_oFont.Strikeout )
{
double dItalicAdd = tan( (double)dItalicAngle ) * fXHeight * fFontSize / 2;
if ( !m_oFont.Italic )
dItalicAdd = 0;
if ( S_OK != ( hRes = MoveTo( (float)fX + dItalicAdd, fPageHeight - (float) ( fY + fBaseLineOffset - fXHeight * fFontSize / 2 ) ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = LineTo( (float)fX + fTextWidth + dItalicAdd, fPageHeight - (float) ( fY + fBaseLineOffset - fXHeight * fFontSize / 2 ) ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = Stroke( ) ) )
{
return hRes;
}
//MoveTo(dX, dY - fDescent * fFontSize );
//LineTo(dX + dItalicAdd * 2, dY + fFontSize * ( 1 - fDescent ) );
//LineTo(dX + fTextWidth + dItalicAdd * 2, dY + fFontSize * ( 1 - fDescent ) );
//LineTo(dX + fTextWidth, dY - fDescent * fFontSize );
//LineTo(dX, dY - fDescent * fFontSize );
//Stroke();
}
// Подчеркивание текста.
if ( m_oFont.Underline )
{
float fTextWidth = 0.0f;
float fUnderLineOffset = 3 + fLineWidth / 2;
if ( S_OK != ( hRes = GetTextWidth( bsCodedString, &fTextWidth ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = MoveTo( (float)fX, fPageHeight - (float) (fY + fBaseLineOffset + fUnderLineOffset) /*fDescent * fFontSize*/ ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = LineTo( (float)fX + fTextWidth, fPageHeight - (float) (fY + fBaseLineOffset + fUnderLineOffset) /*fDescent * fFontSize*/ ) ) )
{
return hRes;
}
if ( S_OK != ( hRes = Stroke( ) ) )
{
return hRes;
}
}
// Восстанавливаем систему координат
if ( c_nClipType != m_pCurCommand->nType )
{
// ATLTRACE2( _T("GRestore: DrawText\n") );
if ( S_OK != ( hRes = GRestore() ) )
return hRes;
}
else
{
float fDelta = m_oClipCTM.fA * m_oClipCTM.fD - m_oClipCTM.fB * m_oClipCTM.fC;
if ( 0.0f != fDelta )
{
float fIDelta = 1 / fDelta;
float fA = fIDelta * m_oClipCTM.fD;
float fB = fIDelta * ( -m_oClipCTM.fB );
float fC = fIDelta * ( -m_oClipCTM.fC );
float fD = fIDelta * m_oClipCTM.fA;
float fE = fIDelta * (m_oClipCTM.fC * m_oClipCTM.fF - m_oClipCTM.fE * m_oClipCTM.fD);
float fF = fIDelta * (m_oClipCTM.fE * m_oClipCTM.fB - m_oClipCTM.fA * m_oClipCTM.fF);
// Делаем матрицу CTM единичной
if ( S_OK != ( hRes = Concat( fA, fB, fC, fD, fE, fF ) ) )
return hRes;
}
m_oClipCTM.Set( 1, 0, 0, 1, 0, 0 );
}
// Восстанавливаем старые настройки
if ( S_OK != ( hRes = SetLineWidth( fOldLineWidth ) ) )
return hRes;
if ( S_OK != ( hRes = SetRGBFill( fFillR, fFillG, fFillB ) ) )
return hRes;
if ( S_OK != ( hRes = SetRGBStroke( fStrokeR, fStrokeG, fStrokeB ) ) )
return hRes;
m_oFont.Bold = bOldBold;
m_oFont.Italic = bOldItalic;
return S_OK;
}
//--------- Маркеры для команд -------------------------------------------------------------------
HRESULT CPdfWriterLib::BeginCommand (const DWORD & nFlag)
{
#if defined(_WIN32) || defined(_WIN64)
wchar_t sTemp[32];
_itow(nFlag, sTemp, 10);
if (c_nPathType == nFlag)
ATLTRACE2(_T("Begin") + CString(_T(" - PathType")) + _T("\n"));
else if (c_nClipType == nFlag)
ATLTRACE2(_T("Begin") + CString(_T(" - ClipType")) + _T("\n"));
else if (c_nResetClipType == nFlag)
ATLTRACE2(_T("Begin") + CString(_T(" - ResetClipType")) + _T("\n"));
else if ( c_nPageType == nFlag )
ATLTRACE2(_T("Begin") + CString(_T(" - PageType")) + _T("\n"));
else
ATLTRACE2(_T("Begin") + CString(sTemp) + _T("\n"));
#endif
if ( nFlag == c_nTableCell || nFlag == c_nHeader || nFlag == c_nColumnCount || nFlag == c_nFootnote
|| nFlag == c_nShape || nFlag == c_nShapeGroup || nFlag == c_nShapeWrap || nFlag == c_nTable
|| nFlag == c_nTableXml || nFlag == c_nBlock || nFlag == c_nBlockHeadingLevel || nFlag == c_nBlockNumberingLevel
|| nFlag == c_nBaselineShift
)
return S_OK;
TCommandType *pNewCommand = new TCommandType();
pNewCommand->nType = nFlag;
pNewCommand->pPrev = m_pCurCommand;
m_pCurCommand = pNewCommand;
HRESULT hRes = S_OK;
if ( c_nPathType == nFlag )
{
SetState( rendstatePath );
// Сейчас начинаем рисовать Path
m_BlockCommandsStart = ((PageAttr)m_pDocument->pCurPage->pAttr)->pStream->nSize;
// ATLTRACE2( _T("GSave: PathType\n") );
if ( S_OK != ( hRes = UpdateGState() ) )
return hRes;
int c = 0;
}
else if ( c_nClipType == nFlag )
{
// Запоминаем состояние без обрезающего пата
if ( false == m_bClipPath )
{
// ATLTRACE2( _T("GSave: ClipPathType\n") );
if ( S_OK != ( hRes = GSave() ) )
return hRes;
m_bClipPath = true;
}
}
else if ( c_nResetClipType == nFlag )
{
// Откатываемся к состоянию без обрезающего пата
if ( true == m_bClipPath )
{
SetState( rendstateClipReset );
// ATLTRACE2( _T("GRestore: ClipPathType\n") );
if ( S_OK != ( hRes = GRestore() ) )
return hRes;
m_oClipCTM.Set( 1, 0, 0, 1, 0, 0 );
m_bClipPath = false;
}
}
return S_OK;
}
HRESULT CPdfWriterLib::EndCommand (const DWORD & nFlag)
{
#if defined(_WIN32) || defined(_WIN64)
wchar_t sTemp[32];
_itow(nFlag, sTemp, 10);
if (c_nPathType == nFlag)
ATLTRACE2( _T("End") + CString( _T(" - PathType") ) + _T("\n") );
else if (c_nPageType == nFlag)
ATLTRACE2( _T("End") + CString( _T(" - PageType") ) + _T("\n") );
else if (c_nResetClipType == nFlag)
ATLTRACE2( _T("End") + CString( _T(" - ResetClipType") ) + _T("\n") );
else if ( c_nClipType == nFlag )
ATLTRACE2( _T("End") + CString( _T(" - ClipType") ) + _T("\n") );
else
ATLTRACE2( _T("End") + CString( sTemp ) + _T("\n") );
#endif
if (nFlag == c_nTableCell || nFlag == c_nHeader || nFlag == c_nColumnCount || nFlag == c_nFootnote
|| nFlag == c_nShape || nFlag == c_nShapeGroup || nFlag == c_nShapeWrap || nFlag == c_nTable
|| nFlag == c_nTableXml || nFlag == c_nBlock || nFlag == c_nBlockHeadingLevel || nFlag == c_nBlockNumberingLevel || nFlag == c_nBaselineShift)
{
return S_OK;
}
if ( !m_pCurCommand || nFlag != m_pCurCommand->nType )
return AVS_OFFICEPDFWRITER_ERROR_BAD_COMMAND_TYPE;
HRESULT hRes = S_OK;
if (c_nPathType == nFlag)
{
// Если данный пат набивался как клип, тогда мы должны подать команду о завершении
if ( NULL != m_pCurCommand->pPrev && c_nClipType == m_pCurCommand->pPrev->nType )
{
if ( c_nClipRegionTypeWinding == m_pCurCommand->nFlag )
{
if ( S_OK != ( hRes = Clip() ) )
return hRes;
}
else if ( c_nClipRegionTypeEvenOdd == m_pCurCommand->nFlag )
{
if ( S_OK != ( hRes = EoClip() ) )
return hRes;
}
if ( S_OK != ( hRes = EndPath() ) )
return hRes;
float fDelta = m_oClipCTM.fA * m_oClipCTM.fD - m_oClipCTM.fB * m_oClipCTM.fC;
if ( 0.0f != fDelta )
{
float fIDelta = 1 / fDelta;
float fA = fIDelta * m_oClipCTM.fD;
float fB = fIDelta * ( -m_oClipCTM.fB );
float fC = fIDelta * ( -m_oClipCTM.fC );
float fD = fIDelta * m_oClipCTM.fA;
float fE = fIDelta * (m_oClipCTM.fC * m_oClipCTM.fF - m_oClipCTM.fE * m_oClipCTM.fD);
float fF = fIDelta * (m_oClipCTM.fE * m_oClipCTM.fB - m_oClipCTM.fA * m_oClipCTM.fF);
// Делаем матрицу CTM единичной
if ( S_OK != ( hRes = Concat( fA, fB, fC, fD, fE, fF ) ) )
return hRes;
}
}
else
{
// ATLTRACE2( _T("GRestore: PathType\n") );
if ( S_OK != ( hRes = GRestore() ) )
return hRes;
}
}
else if ( c_nPageType == nFlag )
{
SetState( rendstateNone );
}
TCommandType *pPrev = m_pCurCommand->pPrev;
delete m_pCurCommand;
m_pCurCommand = pPrev;
return S_OK;
}
//--------- Функции для работы с Graphics Path ---------------------------------------------------
HRESULT CPdfWriterLib::PathCommandStart ()
{
// ATLTRACE2( _T("Start\n") );
if ( c_BrushTypeTexture == m_oBrush.Type && m_pCurPath || (m_oPatternState.IsUse() && m_pCurPath))
m_pCurPath->StartFigure();
//std::wstring bsError;
//GetLastErrorString(&bsError);
//HRESULT hRes = S_OK;
//if ( S_OK != ( hRes = EndPath() ) )
// return hRes;
m_bStartSubPath = true;
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandEnd ()
{
// ATLTRACE2( _T("End\n") );
if (c_BrushTypeTexture == m_oBrush.Type && m_pCurPath || (m_oPatternState.IsUse() && m_pCurPath))
m_pCurPath->CloseFigure();
//HRESULT hRes = S_OK;
//if ( S_OK != ( hRes = EndPath() ) )
// return hRes;
//m_bStartSubPath = true;
// NOTE : решение хардкорное
// градиент имеет прозрачность, поэтому все команды перемещаем в форму
// TODO : переписать запись команд таким образом что бы они сыпались во временный объект
if (m_MaskWithFormCommands.GetLength())
{
if (m_XForm)
{
StreamRecPtr stream = ((PageAttr)m_pDocument->pCurPage->pAttr)->pStream;
unsigned int bufferSize = stream->nSize - m_BlockCommandsStart;
if (bufferSize && stream)
{
CStringA str;
CHAR* buffer = str.GetBuffer(bufferSize + 1);
if (buffer)
{
GRestore();
StreamSeek(stream, m_BlockCommandsStart, WhenceMode::SeekSet);
StreamRead(stream, (BYTE*)buffer, &bufferSize);
StreamSeek(stream, m_BlockCommandsStart, WhenceMode::SeekWrite);
buffer[bufferSize] = L'\0';
CString data(str);
m_XForm->SetStream(data);
// Example : q /s13 gs /x14 Do Q
// к /x объекту применяется маска /s
StreamWriteStr(stream, CStringA(m_MaskWithFormCommands));
if (m_IsStrokeShape)
{
if (m_strPatternFill.GetLength()) data.Replace(m_strPatternFill, L"");
if (m_strPatternStroke.GetLength()) data.Replace(m_strPatternStroke, L"");
data.Replace(L"B\012", L"S\012");
data.Replace(L"f\012", L"s\012");
data.Replace(L"B*\012", L"S*\012");
data.Replace(L"f*\012", L"s*\012");
if (-1 == data.Find(L"Q\012")) data += L"Q\012";
StreamWriteStr(stream, CStringA(data));
}
str.ReleaseBuffer();
}
}
}
m_BlockCommandsStart = 0;
m_XForm = NULL;
m_MaskWithFormCommands = L"";
m_IsStrokeShape = false;
m_strPatternFill = L"";
m_strPatternStroke = L"";
}
return S_OK;
}
//
HRESULT CPdfWriterLib::PathCommandMoveTo (const double &fX1, const double &fY1)
{
// ATLTRACE2( _T("Move To\n") );
HRESULT hRes = S_OK;
if ( true == m_bFirstMoveTo )
{
// Текущее состояние - Path
SetState( /*m_bClip ? rendstateClipPath :*/ rendstatePath );
m_bFirstMoveTo = false;
}
if ( !m_bStartSubPath || m_oPatternState.IsUse())
{
if ( c_BrushTypeTexture == m_oBrush.Type || m_oPatternState.IsUse())
{
if (m_oPatternState.IsUse())
{
if (NULL == m_pCurPath)
{
m_pCurPath = new Aggplus::CGraphicsPath();
m_pCurPath->StartFigure(); //create было todoooo
}
}
else
{
if (m_pCurPath)
m_pCurPath->_Close();//???? было Delete
else
m_pCurPath = new Aggplus::CGraphicsPath();
m_pCurPath->StartFigure();
}
}
}
if ( c_BrushTypeTexture == m_oBrush.Type && m_pCurPath || (m_oPatternState.IsUse() && m_pCurPath))
m_pCurPath->MoveTo( fX1, fY1 );
double fX = MMToPDFCoords( fX1 );
double fY = MMToPDFCoords( fY1 );
m_bStartSubPath = false;
float fPageHeight = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
return hRes;
if ( S_OK != ( hRes = MoveTo( fX, fPageHeight - fY ) ) )
return hRes;
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandLineTo (const double &fX1, const double &fY1)
{
// ATLTRACE2( _T("Line To\n") );
if ( c_BrushTypeTexture == m_oBrush.Type && m_pCurPath || (m_oPatternState.IsUse() && m_pCurPath))
m_pCurPath->LineTo( fX1, fY1 );
double fX = MMToPDFCoords( fX1 );
double fY = MMToPDFCoords( fY1 );
HRESULT hRes = S_OK;
float fPageHeight = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
return hRes;
if ( S_OK != ( hRes = LineTo( fX, fPageHeight - fY ) ) )
return hRes;
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandLinesTo (double* points, const int& count)
{
// ATLTRACE2( _T("Lines To\n") );
if ( c_BrushTypeTexture == m_oBrush.Type && m_pCurPath || (m_oPatternState.IsUse() && m_pCurPath))
m_pCurPath->AddLines(points, count );
HRESULT hRes = S_OK;
float fPageHeight = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
return hRes;
VARTYPE vType;
//double* pArray = (double* (pPoints)->pvData;
//int nPointsCount = (pPoints)->rgsabound->cElements / 2;
if ( m_bStartSubPath )
{
//if ( S_OK != ( hRes = GRestore() ) )
// return hRes;
if ( S_OK != ( hRes = PathCommandMoveTo( (points)[0], (points)[1] ) ) )
return hRes;
}
double *points1 = points + 2;
int count1 = count -1;
for ( int nIndex = 0; nIndex < count1; nIndex++, points1 += 2 )
if ( S_OK != ( hRes = LineTo( MMToPDFCoords( points1[0] ), fPageHeight - MMToPDFCoords( points1[1] ) ) ) )
return hRes;
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandCurveTo (const double &fX1, const double &fY1, const double &fX2, const double &fY2,
const double &fX3, const double &fY3)
{
// ATLTRACE2( _T("Curve To\n") );
if ( c_BrushTypeTexture == m_oBrush.Type && m_pCurPath|| (m_oPatternState.IsUse() && m_pCurPath) )
m_pCurPath->CurveTo( fX1, fY1, fX2, fY2, fX3, fY3 );
HRESULT hRes = S_OK;
float fPageHeight = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
return hRes;
if ( S_OK != ( hRes = CurveTo( MMToPDFCoords( fX1 ), fPageHeight - MMToPDFCoords( fY1 ), MMToPDFCoords( fX2 ), fPageHeight - MMToPDFCoords( fY2 ), MMToPDFCoords( fX3 ), fPageHeight - MMToPDFCoords( fY3 ) ) ) )
return hRes;
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandCurvesTo (double* points, const int& count)
{
// ATLTRACE2( _T("Curves To\n") );
if ( c_BrushTypeTexture == m_oBrush.Type && m_pCurPath || (m_oPatternState.IsUse() && m_pCurPath))
m_pCurPath->AddCurve( points, count );
HRESULT hRes = S_OK;
float fPageHeight = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
return hRes;
double* pArray = points;
int nPointsCount = count;
if ( m_bStartSubPath )
{
//if ( S_OK != ( hRes = GRestore() ) )
// return hRes;
if ( S_OK != ( hRes = PathCommandMoveTo( pArray[0], pArray[1] ) ) )
return hRes;
}
pArray += 2;
nPointsCount--;
for ( int nIndex = 0; nIndex < nPointsCount / 3; nIndex++, pArray += 6 )
{
if ( S_OK != ( hRes = CurveTo( MMToPDFCoords( pArray[0] ), fPageHeight - MMToPDFCoords( pArray[1] ), MMToPDFCoords( pArray[2] ), fPageHeight - MMToPDFCoords( pArray[3] ), MMToPDFCoords( pArray[4] ), fPageHeight - MMToPDFCoords( pArray[5] ) ) ) )
return hRes;
}
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandArcTo (const double &fX1, const double &fY1, const double &fWidth1, const double &fHeight1,
const double &fStartAngle, const double &fSweepAngle)
{
// ATLTRACE2( _T("Arc To\n") );
if ( c_BrushTypeTexture == m_oBrush.Type && m_pCurPath || (m_oPatternState.IsUse() && m_pCurPath))
m_pCurPath->AddArc( fX1, fY1, fWidth1, fHeight1, fStartAngle, fSweepAngle );
//todooo тока добавить ?
double fX = MMToPDFCoords( fX1 );
double fY = MMToPDFCoords( fY1 );
double fWidth = MMToPDFCoords( fWidth1 );
double fHeight = MMToPDFCoords( fHeight1 );
HRESULT hRes = S_OK;
float fPageHeight = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
return hRes;
if ( m_bStartSubPath )
{
double dStartAngle = fStartAngle * 3.141592f / 180;
float fStartX = fX + fWidth / 2.0f + fWidth / 2 * cos( AngToEllPrm( dStartAngle, fWidth / 2, fHeight / 2 ) );
float fStartY = fY + fHeight / 2.0f + fHeight / 2 * sin( AngToEllPrm ( dStartAngle, fWidth / 2, fHeight / 2 ) );
// Аналог PathCommandMoveTo, но без пересчета координат
m_bStartSubPath = false;
// В случае, когда эллипс рисуется целиком используется команда AppendEllipse, в которой команда MoveTo уже есть
if ( !( fSweepAngle >= 360 ) )
if ( S_OK != ( hRes = MoveTo( fStartX, fPageHeight - fStartY ) ) )
return hRes;
}
bool bClockDirection = false;
float fEndAngle = 360 - ( fSweepAngle + fStartAngle );
float fSrtAngle = 360 - fStartAngle;
if( fSweepAngle > 0 )
bClockDirection = true;
if( fSweepAngle >= 360 ) // Целый эллипс
{
if ( S_OK != ( hRes = AppendEllipse( fX + fWidth / 2, fPageHeight - ( fY + fHeight / 2 ), fWidth / 2, fHeight / 2 ) ) )
return hRes;
}
else // Дуга эллипса
{
if ( S_OK != ( hRes = AppendEllipseArc( fX + fWidth / 2, fPageHeight - ( fY + fHeight / 2 ), fWidth / 2, fHeight / 2, fSrtAngle, fEndAngle, bClockDirection ) ) )
return hRes;
}
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandClose ()
{
// ATLTRACE2( _T("Close\n") );
if (c_BrushTypeTexture == m_oBrush.Type && m_pCurPath || (m_oPatternState.IsUse() && m_pCurPath))
m_pCurPath->CloseFigure();
HRESULT hRes = S_OK;
if (S_OK != (hRes = ClosePath()))
return hRes;
m_bStartSubPath = true;
return S_OK;
}
//
HRESULT CPdfWriterLib::DrawPath (const LONG & nType1)
{
m_bFirstMoveTo = true;
m_IsStrokeShape = false;
// Обводка текста делается в CommandDrawText (а эта команда приходит для согласования с вьювером)
if (c_nStrokeTextType == m_pCurCommand->nType)
return S_OK;
// ATLTRACE2(_T("Draw Path\n"));
LONG nType = nType1;
// TO DO: Потом надо будет этот случай убрать
if ( 0 == nType )
nType = c_nStroke;
m_bStartSubPath = false;
bool IsBrushTexture = c_BrushTypeTexture == m_oBrush.Type;
bool IsNoStroke = c_nStroke != nType;
bool IsBrushFileExist = FileExist(std_string2string(m_oBrush.TexturePath));
HRESULT hRes = S_OK;
if (IsBrushTexture && IsNoStroke && IsBrushFileExist && (m_pCurPath || m_bUseTextureRect))
{
if (c_BrushTextureModeStretch == m_oBrush.TextureMode)
{
// Меняем текущее состояние с пата на клип по пату и добавляем данный пат к клипу
m_oRendererState.change_State(rendstateClipPath);
SetState(rendstateNone);
if (c_nWindingFillMode & nType)
{
if (S_OK != (hRes = Clip()))
return hRes;
}
else if (c_nEvenOddFillMode & nType)
{
if (S_OK != (hRes = EoClip()))
return hRes;
}
else
{
return S_FALSE;
}
if (S_OK != (hRes = EndPath()))
return hRes;
double fX = 0, fY = 0, fW = 0, fH = 0;
if (true != m_bUseTextureRect)
{
m_pCurPath->GetBounds(fX, fY, fW, fH);
}
else
{
fX = m_oBrush.Rect.X;
fY = m_oBrush.Rect.Y;
fW = m_oBrush.Rect.Width;
fH = m_oBrush.Rect.Height;
}
CString sPath = std_string2string(m_oBrush.TexturePath);
std::wstring bsPath = m_oBrush.TexturePath;
m_bUseImageTransform = false;
m_bUseImageTextureAlpha = true;
if (S_OK != (hRes = DrawImageFromFile(bsPath, fX, fY, fW, fH)))
{
ResetError(m_pDocument);
return hRes;
}
m_bUseImageTransform = true;
m_bUseImageTextureAlpha = false;
return S_OK;
}
else if (c_BrushTextureModeTile == m_oBrush.TextureMode)
{
ApplyTileFill();
}
// TODO: добавить тайловые заливки с реверсным узором
}
else if (IsBrushTexture && IsNoStroke && !IsBrushFileExist)
{
if (c_nWindingFillMode & nType)
nType = c_nWindingFillMode;
else
nType = c_nEvenOddFillMode;
}
ApplyFillGradient();
ApplyStrokeGradient();
if (c_nWindingFillMode != nType && c_nEvenOddFillMode != nType)
{
m_IsStrokeShape = true;
}
RELEASEOBJECT(m_pCurPath);
switch (nType)
{
case c_nStroke: if (S_OK != (hRes = Stroke())) { /*ATLTRACE2(_T("Stroke\n"));*/ return hRes; } break;
case c_nWindingFillMode: if (S_OK != (hRes = Fill())) { /*ATLTRACE2(_T("Fill\n"));*/ return hRes; } break;
case c_nEvenOddFillMode: if (S_OK != (hRes = EoFill())) { /*ATLTRACE2(_T("EoFill\n")); */ return hRes; } break;
case c_nStroke | c_nWindingFillMode: if (S_OK != (hRes = FillStroke())) { /*ATLTRACE2(_T("FillStroke\n"));*/ return hRes; } break;
case c_nStroke | c_nEvenOddFillMode: if (S_OK != (hRes = EoFillStroke())){ /*ATLTRACE2(_T("EoFillStroke\n"));*/ return hRes; } break;
default:
{
if (S_OK != (hRes = Stroke()))
{
// ATLTRACE2(_T("Stroke\n"));
return hRes;
}
else
return AVS_OFFICEPDFWRITER_ERROR_DRAW_PATH;
}
}
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandGetCurrentPoint (double *pfX, double *pfY)
{
// ATLTRACE2( _T("GetCurrentPoint\n") );
HRESULT hRes = S_OK;
float fPageHeight = 0.0f, fX = 0.0f, fY = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
return hRes;
if ( S_OK != ( hRes = GetCurrentPosition( &fX, &fY ) ) )
return hRes;
fY = fPageHeight - fY;
*pfX = (double)fX;
*pfY = (double)fY;
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandText (const std::wstring & bsText, const double & fX, const double & fY,
const double & fWidth, const double & fHeight, const double & fBaseLineOffset )
{
// В данная команда может прийти либо для обводки текста, либо для клипа по тексту
CommandDrawText( bsText, fX, fY, fWidth, fHeight, fBaseLineOffset );
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandTextCHAR(const LONG& c, const double& x, const double& y, const double& w, const double& h, const double& baselineOffset)
{
//if (!CheckValidate())
// return S_FALSE;
//_SetFont();
//// так как пат рисуется в миллиметрах - надо перевести пункты в миллиметры
//float fSize = (float)(0.3528 * m_oFont.Size);
//m_pPath->AddStringC(c, m_pFontManager, x, y + baselineOffset);
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandTextEx (const std::wstring& bsUnicodeText, const std::wstring& bsGidText, const double& x, const double& y, const double& w, const double& h, const double& baselineOffset, const DWORD& lFlags)
{
// В данная команда может прийти либо для обводки текста, либо для клипа по тексту
CommandDrawTextEx( bsUnicodeText, bsGidText/*, bsSrcCodeText*/, x, y, w, h, baselineOffset, lFlags );
return S_OK;
}
HRESULT CPdfWriterLib::PathCommandTextExCHAR(const LONG& c, const LONG& gid, const double& x, const double& y, const double& w, const double& h, const double& baselineOffset, const DWORD& lFlags)
{
if (gid >= 0)
{
m_oFont.StringGID = 1;
return PathCommandTextCHAR(gid, x, y, w, h, baselineOffset);
}
m_oFont.StringGID = 0;
return PathCommandTextCHAR(c, x, y, w, h, baselineOffset);
}
//--------- Функции для вывода изображений -------------------------------------------------------
HRESULT CPdfWriterLib::LoadImageFromInterface (IGrObject *pInterface , bool bAlpha)
{
Aggplus::CImage *image = dynamic_cast<Aggplus::CImage *>(pInterface);
if (image == NULL) return S_FALSE;
LONG lWidth = image->m_dwWidth;
LONG lHeight = image->m_dwHeight;
//// преобразуем к BGR формату ???? меняю !!! он и так BGRA
BYTE* pSourceBuffer = image->GetData();
BYTE* pImage = new BYTE[ lWidth * lHeight * 3];
BYTE* pAlpha = new BYTE[ lWidth * lHeight ];
BYTE* pImagePointer = pImage;
BYTE* pAlphaPointer = pAlpha;
bool bHaveAlpha = false;
// Разделяем саму картинку и альфа-канал. Одновременно с этим, посчитаем количество цветов в картинке.
std::vector<TRGBColor> arrColors;
std::map<DWORD,int> mapColors;
for ( int nIndex = 0; nIndex < lWidth * lHeight; nIndex++, pImagePointer += 3, pSourceBuffer += 4, pAlphaPointer++ )
{
pImagePointer[ 0 ] = pSourceBuffer[ 0 ];//2
pImagePointer[ 1 ] = pSourceBuffer[ 1 ];
pImagePointer[ 2 ] = pSourceBuffer[ 2 ];//0
// Картинки с количеством цветом > 256 считаем полноцветными. (формат RGB)
if ( arrColors.size() <= 256 )
{
TRGBColor oColor;
oColor.r = pImagePointer[ 2 ];//0
oColor.g = pImagePointer[ 1 ];
oColor.b = pImagePointer[ 0 ];//2
DWORD color = pImagePointer[ 0 ] << 16 + pImagePointer[ 1 ] << 8 + pImagePointer[ 2 ];
if ( mapColors.end() == mapColors.find(color) )
{
mapColors.insert(std::pair<DWORD,int>(color, arrColors.size()));
arrColors.push_back( oColor );
}
}
pAlphaPointer[ 0 ] = pSourceBuffer[ 3 ];
if ( 255 != pAlphaPointer[0] )
bHaveAlpha = true;
}
TRGBColor oBlack = { 0, 0, 0 };
TRGBColor oWhite = { 255, 255, 255 };
bool bBnW = false; // Черно-белая картинка
if ( ( ( arrColors.size() == 2 && ( ( arrColors[0] == oBlack && arrColors[1] == oWhite ) || ( arrColors[1] == oBlack && arrColors[0] == oWhite ) ) ) ||
( arrColors.size() == 1 && ( arrColors[0] == oBlack || arrColors[1] == oWhite ) ) ) && !bHaveAlpha )
bBnW = true;
unsigned long nRet = OK;
if ( !m_pXObjectList )
{
m_pXObjectList = ListNew( m_pDocument->oMMgr, DEF_ITEMS_PER_BLOCK );
if ( OK != ( nRet = ErrorGetCode( &m_pDocument->oError ) ) )
{
delete[] pAlpha;
delete[] pImage;
return nRet;
}
}
//bBnW = true; для теста записи монохрома
// Проверим нужен ли нам альфа-канал
if ( bAlpha )
{
bool bFakeAlpha = true;
for ( int nIndex = 0; nIndex < lWidth * lHeight; nIndex++ )
{
if ( 255 != pAlpha[nIndex] )
{
bFakeAlpha = false;
break;
}
}
if ( bFakeAlpha )
bAlpha = false;
}
// Проверяем, возможно, такая картинка уже есть в нашем файле
XObject pOldImage = NULL;
CRC32 oCRC;
oCRC.ProcessCRC( pImage, lWidth * lHeight * 3 );
unsigned int unImageCheckSum = oCRC.m_nCRC32;
oCRC.Init();
oCRC.ProcessCRC( pAlpha, lWidth * lHeight );
unsigned int unAlphaCheckSum = oCRC.m_nCRC32;
for ( int nIndex = 0; nIndex < m_pXObjectList->nCount; ++nIndex )
{
XObject pCurImage = (XObject)ListItemAt( m_pXObjectList, nIndex );
if ( !ImageValidate( pCurImage ) )
continue;
unsigned int unHeight = ImageGetHeight( pCurImage );
unsigned int unWidth = ImageGetWidth( pCurImage );
unsigned int unBPC = ImageGetBitsPerComponent( pCurImage );
EColorSpace eCS = ImageGetColorSpace2( pCurImage );
if ( unHeight != lHeight || unWidth != lWidth || CSDeviceRGB != eCS || 8 != unBPC )
continue;
if ( !StreamValidate( pCurImage->pStream ) )
continue;
if ( bAlpha && pAlpha )
{
XObject pSMask = ImageGetSMask( pCurImage );
if ( !ImageValidate( pSMask ) )
continue;
unsigned int unMaskHeight = ImageGetHeight( pSMask );
unsigned int unMaskWidth = ImageGetWidth( pSMask );
unsigned int unMaskBPC = ImageGetBitsPerComponent( pSMask );
EColorSpace eMaskCS = ImageGetColorSpace2( pSMask );
if ( unMaskHeight != lHeight || unMaskWidth != lWidth || CSDeviceGray != eMaskCS || 8 != unMaskBPC )
continue;
if ( !StreamValidate( pSMask->pStream ) )
continue;
if ( unAlphaCheckSum != pSMask->pStream->nCheckSum )
continue;
}
if ( unImageCheckSum != pCurImage->pStream->nCheckSum )
continue;
// Если мы дошли до этого места, значит картинки полностью совпадают и нет смысла загружать картинку заново
pOldImage = pCurImage;
break;
}
if ( pOldImage )
m_pCurrentXObject = pOldImage;
else if ( bBnW )
m_pCurrentXObject = LoadJbig2ImageFromMem( m_pDocument, pImage, lWidth, lHeight, unImageCheckSum);
else
{
//m_pCurrentXObject = LoadRawImageFromMem ( m_pDocument, pImage, lWidth, lHeight, CSDeviceRGB, 8, bAlpha, pAlpha );
m_pCurrentXObject = LoadJpegImageFromMem( m_pDocument, pImage, lWidth, lHeight, unImageCheckSum, bAlpha, pAlpha, unAlphaCheckSum );
//m_pCurrentXObject = LoadJpxImageFromMem ( m_pDocument, pImage, lWidth, lHeight, unImageCheckSum, bAlpha, pAlpha, unAlphaCheckSum );
}
if ( OK != ( nRet = ErrorGetCode( &m_pDocument->oError ) ) )
{
delete[] pAlpha;
delete[] pImage;
return nRet;
}
if ( !pOldImage )
{
if ( OK != ( nRet = ListAdd( m_pXObjectList, m_pCurrentXObject) ) )
{
delete[] pAlpha;
delete[] pImage;
return nRet;
}
}
delete[] pAlpha;
delete[]pImage;
return S_OK;
}
HRESULT CPdfWriterLib::DrawImage (IGrObject *pInterface, const double& fX1, const double& fY1, const double& fWidth1, const double& fHeight1)
{
SetState( rendstateImage );
//BeginCommand( c_nPathType );
//PathCommandMoveTo( fX, fY );
//PathCommandLineTo( fX + fWidth, fY + fHeight );
//DrawPath( c_nWindingFillMode );
//EndCommand( c_nPathType );
double fX = MMToPDFCoords( fX1 );
double fY = MMToPDFCoords( fY1 );
double fWidth = MMToPDFCoords( fWidth1 );
double fHeight = MMToPDFCoords( fHeight1 );
//if ( fWidth < 1 || fHeight < 1 )
// return S_OK;
HRESULT hRes = S_OK;
float fPageHeight = 0.0f;
if ( S_OK != ( hRes = GetHeight( &fPageHeight ) ) )
return hRes;
if ( S_OK != ( hRes = LoadImageFromInterface( pInterface, true ) ) )
return hRes;
// ATLTRACE2( _T("GSave: DrawImage\n") );
if ( S_OK != ( hRes = GSave() ) )
return hRes;
//if ( S_OK != ( hRes = UpdateCoordSpace() ) )
// return hRes;
if ( true == m_bUseImageTransform )
{
DWORD nFlags = m_oCommandParams.nFlag;
if ( !( nFlags == 16 ) )
{
double dAngle = m_oCommandParams.dAngle;
double dLeft = m_oCommandParams.dLeft;
double dHeight = m_oCommandParams.dHeight;
double dWidth = m_oCommandParams.dWidth;
double dTop = m_oCommandParams.dTop;
if ( !(0 == nFlags && 0 == dAngle) )
{
// Миллиметры -> координаты PDF (72dpi)
dLeft = MMToPDFCoords( dLeft );
dTop = MMToPDFCoords( dTop );
dWidth = MMToPDFCoords( dWidth );
dHeight = MMToPDFCoords( dHeight );
dTop = fPageHeight - dTop;
dAngle = dAngle * 3.141592f / 180;
// Высчитываем центр прямоугольника ( относительно него производится поворот )
double dX0 = dLeft + dWidth / 2;
double dY0 = dTop - dHeight / 2;
double dA = cos( dAngle );
double dB = sin( dAngle );
double dC = -sin( dAngle );
double dD = cos( dAngle );
double dE = dX0 - dX0 * cos ( dAngle ) + dY0 * sin( dAngle );
double dF = dY0 - dX0 * sin ( dAngle ) - dY0 * cos( dAngle );
bool bFlipX = nFlags & 1;
bool bFlipY = nFlags & 2;
if ( !bFlipX && !bFlipY )
{
// Ничего не делаем
}
else if ( bFlipX && !bFlipY )
{
dA = -dA;
dC = -dC;
dE = -dE + 2 * dX0;
}
else if ( !bFlipX && bFlipY )
{
dB = -dB;
dD = -dD;
dF = -dF + 2 * dY0;
}
else
{
dA = -dA;
dB = -dB;
dC = -dC;
dD = -dD;
dE = -dE + 2 * dX0;
dF = -dF + 2 * dY0;
}
if ( S_OK != ( hRes = Concat( dA, dB, dC, dD, dE, dF ) ) )
return hRes;
}
}
else
{
float fA = m_oCommandParams.oMatrix.fA;
float fB = m_oCommandParams.oMatrix.fB;
float fC = m_oCommandParams.oMatrix.fC;
float fD = m_oCommandParams.oMatrix.fD;
float fE = m_oCommandParams.oMatrix.fE;
float fF = m_oCommandParams.oMatrix.fF;
if ( S_OK != ( hRes = Concat( fA, -fB, -fC, fD, MMToPDFCoords( fE ) + fC * fPageHeight, fPageHeight - fPageHeight * fD - MMToPDFCoords( fF ) ) ) )
return hRes;
}
}
if ( S_OK != ( hRes = DrawCurrentImage( fX, fPageHeight - fY - fHeight, fWidth, fHeight ) ) )
return hRes;
// ATLTRACE2( _T("GRestore: DrawImage\n") );
if ( S_OK != ( hRes = GRestore() ) )
return hRes;
return S_OK;
}
HRESULT CPdfWriterLib::DrawImageFromFile(const std::wstring& bsFilePath, const double& fX, const double& fY, const double& fWidth, const double& fHeight, const BYTE& lAlpha)
{
NSImageExt::CImageExt oExt;
bool bRes = oExt.DrawOnRenderer(this, std_string2string(bsFilePath), fX, fY, fWidth, fHeight);
if (bRes)
return S_OK;
Aggplus::CImage image(bsFilePath);
if (image.m_Status != Aggplus::Ok) return S_FALSE;
if ((m_bUseImageTextureAlpha || m_bIsWhiteBackImage))
{
{
LONG lWidth = image.m_dwWidth;
LONG lHeight = image.m_dwHeight;
BYTE* pBuffer = image.GetData();
LONG lCountPix = lWidth * lHeight;
if ( m_bIsWhiteBackImage )
{
while (lCountPix > 0)
{
if (0 == pBuffer[3])
memset(pBuffer, 0xFF, 4);
--lCountPix;
pBuffer += 4;
}
}
else if ( m_bUseImageTextureAlpha )
{
while (lCountPix > 0)
{
pBuffer[3] *= ((double)m_oBrush.TextureAlpha / 255.0);
--lCountPix;
pBuffer += 4;
}
}
}
}
HRESULT hRes = S_OK;
if (S_OK != (hRes = DrawImage(&image, fX, fY, fWidth, fHeight)))
{
image.Destroy();
return hRes;
}
image.Destroy();
return S_OK;
}
//--------- Transform ----------------------------------------------------------------------------
HRESULT CPdfWriterLib::GetCommandParams (double *pdAngle, double *pdLeft, double *pdTop, double *pdWidth, double *pdHeight, DWORD *pnFlags )
{
*pdAngle = -m_oCommandParams.dAngle;
*pdLeft = m_oCommandParams.dLeft;
*pdHeight = m_oCommandParams.dHeight;
*pdWidth = m_oCommandParams.dWidth;
*pdTop = m_oCommandParams.dTop;
*pnFlags = m_oCommandParams.nFlag;
return S_OK;
}
HRESULT CPdfWriterLib::SetCommandParams (double dAngle, double dLeft, double dTop, double dWidth, double dHeight, DWORD nFlags )
{
// if ( 0 != nFlags )
// ATLTRACE2( _T("SetCommandParams: Flip <--------------------------------------------- \n") );
HRESULT hRes = S_OK;
m_oCommandParams.dAngle = -dAngle;
m_oCommandParams.dLeft = dLeft;
m_oCommandParams.dHeight = dHeight;
m_oCommandParams.dWidth = dWidth;
m_oCommandParams.dTop = dTop;
m_oCommandParams.nFlag = nFlags;
if ( !(0 == nFlags && 0 == dAngle) )
{
LONG lLeft = dLeft;
LONG lTop = dTop;
LONG lWidth = dWidth;
LONG lHeight = dHeight;
dAngle = dAngle * 3.141592f / 180;
// Высчитываем центр прямоугольника ( относительно него производится поворот )
double dX0 = lLeft + lWidth / 2;
double dY0 = lTop + lHeight / 2;
// Рассчитываем flip
bool bFlipX = ( 0 != ( 1 & nFlags ) );
bool bFlipY = ( 0 != ( 2 & nFlags ) );
LONG lFlipX = bFlipX ? -1 : 1;
LONG lFlipY = bFlipY ? -1 : 1;
// Наше преобразование можно записать в виде произведения матриц:
//
// | 1 0 0 | | cos(p) sin(p) 0 | | ScaleX 0 0 | | 1 0 0 |
// | 0 1 0 | * |-sin(p) cos(p) 0 | * | 0 ScaleY 0 | * | 0 1 0 |
// |-X0 -Y0 1 | | 0 0 1 | | 0 0 1 | | X0 Y0 1 |
double dCos = cos( dAngle );
double dSin = sin( dAngle );
double dA = lFlipX * dCos;
double dB = lFlipY * dSin;
double dC = -lFlipX * dSin;
double dD = lFlipY * dCos;
double dE = dX0 - lFlipX * dX0 * dCos + lFlipX * dY0 * dSin;
double dF = dY0 - lFlipY * dX0 * dSin - lFlipY * dY0 * dCos;
m_oTransform.Set( dA, dB, dC, dD, dE, dF );
}
else
{
m_oTransform.Set( 1, 0, 0, 1, 0, 0 );
}
return S_OK;
}
HRESULT CPdfWriterLib::SetTransform (const double & dA,const double & dB,const double & dC,const double & dD,
const double & dE, const double & dF)
{
// ATLTRACE2( _T("SetTransform\n") );
m_oCommandParams.nFlag = 16;
m_oCommandParams.oMatrix.fA = m_oBaseTransform.fA * dA + m_oBaseTransform.fB * dC;
m_oCommandParams.oMatrix.fC = m_oBaseTransform.fC * dA + m_oBaseTransform.fD * dC;
m_oCommandParams.oMatrix.fE = m_oBaseTransform.fE * dA + m_oBaseTransform.fF * dC + dE;
m_oCommandParams.oMatrix.fB = m_oBaseTransform.fA * dB + m_oBaseTransform.fB * dD;
m_oCommandParams.oMatrix.fD = m_oBaseTransform.fC * dB + m_oBaseTransform.fD * dD;
m_oCommandParams.oMatrix.fF = m_oBaseTransform.fE * dB + m_oBaseTransform.fF * dD + dF;
m_oTransform.Set( dA, dB, dC, dD, dE, dF );
return S_OK;
}
HRESULT CPdfWriterLib::GetTransform (double *pdA, double *pdB, double *pdC, double *pdD, double *pdE, double *pdF)
{
*pdA = (double)m_oCommandParams.oMatrix.fA;
*pdB = (double)m_oCommandParams.oMatrix.fB;
*pdC = (double)m_oCommandParams.oMatrix.fC;
*pdD = (double)m_oCommandParams.oMatrix.fD;
*pdE = (double)m_oCommandParams.oMatrix.fE;
*pdF = (double)m_oCommandParams.oMatrix.fF;
return S_OK;
}
HRESULT CPdfWriterLib::ResetTransform (void)
{
m_oCommandParams.nFlag = 16;
m_oCommandParams.oMatrix.fA = (float)1;
m_oCommandParams.oMatrix.fB = (float)0;
m_oCommandParams.oMatrix.fC = (float)0;
m_oCommandParams.oMatrix.fD = (float)1;
m_oCommandParams.oMatrix.fE = (float)0;
m_oCommandParams.oMatrix.fF = (float)0;
m_oTransform.Set( 1, 0, 0, 1, 0, 0 );
return S_OK;
}
//--------- Clip ---------------------------------------------------------------------------------
HRESULT CPdfWriterLib::get_ClipMode (LONG* plMode)
{
*plMode = 0;
if ( c_nClipType == m_pCurCommand->nType )
*plMode = m_pCurCommand->nFlag;
return S_OK;
}
HRESULT CPdfWriterLib::put_ClipMode (const LONG & lMode)
{
if ( c_nClipType == m_pCurCommand->nType )
m_pCurCommand->nFlag = lMode;
return S_OK;
}
// additiaonal params ----------------------------------------------------------------------
HRESULT CPdfWriterLib::CommandLong(const LONG& lType, const LONG& lCommand)
{
return S_OK;
}
HRESULT CPdfWriterLib::CommandDouble(const LONG& lType, const double& dCommand)
{
return S_OK;
}
HRESULT CPdfWriterLib::CommandString(const LONG& lType, const std::wstring& sCommand)
{
return S_OK;
}
//--------- for teamlab --------------------------------------------------------------------------