mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
2161 lines
60 KiB
C++
2161 lines
60 KiB
C++
#include "stdafx.h"
|
||
#include "PDFWriter.h"
|
||
|
||
HRESULT CPDFWriter::OnlineWordToPdf (BSTR sPathXml, BSTR sDstFile, BSTR sHtmlPlace, LONG nReg)
|
||
{
|
||
using namespace NOnlineOfficeBinToPdf;
|
||
bool hRes = S_OK;
|
||
|
||
NOnlineOfficeBinToPdf::CommandType eCommand = NOnlineOfficeBinToPdf::ctError;
|
||
CString sTempLogo;
|
||
|
||
AVSGraphics::IAVSWinFonts *piWinFonts = NULL;
|
||
|
||
try
|
||
{
|
||
hRes = CoCreateInstance (AVSGraphics::CLSID_CAVSWinFonts, NULL, CLSCTX_ALL, AVSGraphics::IID_IAVSWinFonts, (void **) &piWinFonts);
|
||
if (S_OK != hRes)
|
||
throw "Can't create IAVSWinFonts object!";
|
||
|
||
hRes = CreatePDF();
|
||
if (FAILED (hRes))
|
||
throw "CreatePDF failed!";
|
||
|
||
hRes = SetPDFCompressionMode(15);
|
||
if (FAILED (hRes))
|
||
throw "SetPDFCompressionMode(15) failed!";
|
||
|
||
bool bIsPathOpened = false;
|
||
|
||
int nCountPages = 0;
|
||
CString sHypers;
|
||
sHypers.Append(_T("<linker>"));
|
||
|
||
// read file
|
||
CString sOpenPathName;
|
||
LPTSTR pOpenPathName = sOpenPathName.GetBufferSetLength (MAX_PATH);
|
||
GetLongPathName (sPathXml, pOpenPathName, MAX_PATH);
|
||
sOpenPathName.ReleaseBuffer();
|
||
|
||
//FILE *pFile = _wfopen (sOpenPathName, L"r, ccs=UTF-8");
|
||
HANDLE hFile = ::CreateFile (sOpenPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
if (INVALID_HANDLE_VALUE == hFile)
|
||
throw "OnlineWordToPdf: Opening input file failed!";
|
||
|
||
|
||
DWORD dwFileSize = ::GetFileSize(hFile, NULL);
|
||
CStringA aFileContent;
|
||
LPSTR pFileContent = aFileContent.GetBufferSetLength (dwFileSize);
|
||
DWORD dwRead;
|
||
BOOL bReadRes = ::ReadFile (hFile, pFileContent, dwFileSize, &dwRead, NULL);
|
||
aFileContent.ReleaseBuffer();
|
||
::CloseHandle (hFile);
|
||
if (dwRead != dwFileSize)
|
||
{
|
||
throw "OnlineWordToPdf: wrong file read";
|
||
}
|
||
|
||
CAtlArray<CStringA> asResFile;
|
||
|
||
// here we can to divide file into some lines of text (divided by '\r' symbol)
|
||
asResFile.Add (aFileContent);
|
||
aFileContent.Empty();
|
||
|
||
for (size_t nLine = 0; nLine < asResFile.GetCount(); ++nLine)
|
||
{
|
||
CPDFWriter &oWriter = *this;
|
||
|
||
DWORD len (0);
|
||
BYTE *dstArray = NULL;
|
||
|
||
if (DecodeBase64 (asResFile[nLine], &dstArray, &len)
|
||
&& (NULL != dstArray))
|
||
{
|
||
ATLTRACE2 ("** new Base64line ***\n");
|
||
if (true)
|
||
{
|
||
int curindex = 0;
|
||
|
||
INT32* m = NULL;
|
||
USHORT* ms = NULL;
|
||
int _sLen = 0;
|
||
CString s;
|
||
INT32 gradientType = 0;
|
||
|
||
double m1 = 0;
|
||
double m2 = 0;
|
||
double m3 = 0;
|
||
double m4 = 0;
|
||
double m5 = 0;
|
||
double m6 = 0;
|
||
|
||
BYTE* p = dstArray;
|
||
{
|
||
BYTE* current = p;
|
||
while (curindex < len)
|
||
{
|
||
eCommand = (CommandType)(*current);
|
||
current++;
|
||
curindex++;
|
||
switch (eCommand)
|
||
{
|
||
case ctPageWidth:
|
||
ATLTRACE2 ("CommandType::ctPageWidth:\n");
|
||
m = (INT32*) current;
|
||
current += 4;
|
||
curindex += 4;
|
||
oWriter.put_Width ((*m) / 100000.0);
|
||
break;
|
||
case ctPageHeight:
|
||
ATLTRACE2 ("CommandType::ctPageHeight:\n");
|
||
m = (INT32*)current;
|
||
current += 4;
|
||
curindex += 4;
|
||
oWriter.put_Height ((*m) / 100000.0);
|
||
break;
|
||
case ctPageStart:
|
||
ATLTRACE2 ("\nCommandType::ctPageStart:\n");
|
||
oWriter.NewPage();
|
||
oWriter.BeginCommand(1);
|
||
++nCountPages;
|
||
break;
|
||
case ctPageEnd:
|
||
ATLTRACE2 ("CommandType::ctPageEnd:\n");
|
||
if (bIsPathOpened)
|
||
{
|
||
oWriter.PathCommandEnd();
|
||
oWriter.EndCommand(4);
|
||
}
|
||
|
||
bIsPathOpened = false;
|
||
|
||
if (!nReg)
|
||
{
|
||
double ww;
|
||
oWriter.get_Width(&ww);
|
||
double wh;
|
||
oWriter.get_Height(&wh);
|
||
|
||
double dR = ww - 13;
|
||
double dB = wh - 5;
|
||
double k = 1.0;
|
||
|
||
if (ww <= wh)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
double k1 = ww / 210;
|
||
double k2 = wh / 297;
|
||
k = min(k1, k2);
|
||
}
|
||
else
|
||
{
|
||
double k1 = ww / 297;
|
||
double k2 = wh / 210;
|
||
k = min(k1, k2);
|
||
}
|
||
double dW = 46 * k;
|
||
double dH = 15 * k;
|
||
|
||
double dKoef = 72 / 25.4;
|
||
|
||
CString sTempHyper;
|
||
sTempHyper.Format(_T("<link><source x=\"%i\" y=\"%i\" width=\"%i\" height=\"%i\" page=\"%i\"/>"), (int)((dR - dW) * dKoef), (int)((dB - dH) * dKoef), (int)(dW * dKoef), (int)(dH * dKoef), nCountPages - 1);
|
||
|
||
sHypers += sTempHyper;
|
||
sHypers += _T("<target url=\"www.yourdocs.com\"/></link>");
|
||
|
||
oWriter.ResetTransform();
|
||
|
||
BOOL bWriteTextFile = TRUE;
|
||
if (sTempLogo.IsEmpty())
|
||
{
|
||
sTempLogo = GetTempFileName();
|
||
bWriteTextFile = WriteFile (sTempLogo, (BYTE*) cpLogo1);
|
||
}
|
||
if (bWriteTextFile)
|
||
{
|
||
BSTR bstrTempLogo = sTempLogo.AllocSysString();
|
||
DrawImageFromFile (bstrTempLogo, dR - dW, dB - dH, dW, dH);
|
||
SysFreeString (bstrTempLogo);
|
||
}
|
||
}
|
||
|
||
oWriter.EndCommand(1);
|
||
break;
|
||
case ctPenColor:
|
||
ATLTRACE2 ("CommandType::ctPenColor:\n");
|
||
m = (INT32*)current;
|
||
oWriter.put_PenColor (*m);
|
||
current += 4;
|
||
curindex += 4;
|
||
break;
|
||
case ctPenAlpha:
|
||
ATLTRACE2 ("CommandType::ctPenAlpha:\n");
|
||
oWriter.put_PenAlpha (*current);
|
||
current++;
|
||
curindex++;
|
||
break;
|
||
case ctPenSize:
|
||
ATLTRACE2 ("CommandType::ctPenSize:\n");
|
||
m = (INT32*)current;
|
||
oWriter.put_PenSize (*m / 100000.0);
|
||
current += 4;
|
||
curindex += 4;
|
||
break;
|
||
case ctPenLineJoin:
|
||
ATLTRACE2 ("CommandType::ctPenLineJoin:\n");
|
||
oWriter.put_PenLineJoin (*current);
|
||
current++;
|
||
curindex++;
|
||
break;
|
||
case ctBrushType:
|
||
ATLTRACE2 ("CommandType::ctBrushType:\n");
|
||
m = (INT32*)current;
|
||
oWriter.put_BrushType (*m);
|
||
current += 4;
|
||
curindex += 4;
|
||
break;
|
||
case ctBrushColor1:
|
||
ATLTRACE2 ("CommandType::ctBrushColor1:\n");
|
||
m = (INT32*)current;
|
||
oWriter.put_BrushColor1 (*m);
|
||
current += 4;
|
||
curindex += 4;
|
||
break;
|
||
case ctBrushAlpha1:
|
||
ATLTRACE2 ("CommandType::ctBrushAlpha1:\n");
|
||
oWriter.put_BrushAlpha1 (*current);
|
||
current++;
|
||
curindex++;
|
||
break;
|
||
case ctBrushColor2:
|
||
ATLTRACE2 ("CommandType::ctBrushColor2:\n");
|
||
m = (INT32*)current;
|
||
oWriter.put_BrushColor1 (*m);
|
||
current += 4;
|
||
curindex += 4;
|
||
break;
|
||
case ctBrushAlpha2:
|
||
ATLTRACE2 ("CommandType::ctBrushAlpha2:\n");
|
||
oWriter.put_BrushAlpha2 (*current);
|
||
current++;
|
||
curindex++;
|
||
break;
|
||
case ctBrushRectable:
|
||
ATLTRACE2 ("CommandType::ctBrushRectable:\n");
|
||
|
||
m = (INT32*)current;
|
||
current += 4 * 4;
|
||
curindex += 4 * 4;
|
||
|
||
m1 = (*m++) / 100000.0;
|
||
m2 = (*m++) / 100000.0;
|
||
m3 = (*m++) / 100000.0;
|
||
m4 = (*m++) / 100000.0;
|
||
|
||
oWriter.BrushRect(0, m1, m2, m3, m4);
|
||
break;
|
||
case ctBrushRectableEnabled:
|
||
{
|
||
ATLTRACE2 ("CommandType::ctBrushRectableEnabled:\n");
|
||
|
||
VARIANT bEn;
|
||
bEn.vt = VT_BOOL;
|
||
bEn.boolVal = (1 == *current) ? VARIANT_TRUE : VARIANT_FALSE;
|
||
|
||
oWriter.SetAdditionalParam(L"BrushFillBoundsEnable", bEn);
|
||
|
||
current += 1;
|
||
curindex += 1;
|
||
}
|
||
break;
|
||
case ctBrushTexturePath:
|
||
{
|
||
ATLTRACE2 ("CommandType::ctBrushTexturePath:\n");
|
||
|
||
ms = (USHORT*)current;
|
||
current += 2;
|
||
curindex += 2;
|
||
|
||
_sLen = (int)(*ms);
|
||
CStringW sTempStr;
|
||
sTempStr.Append((WCHAR*)current, _sLen);
|
||
s = sTempStr;
|
||
#ifdef _DEBUG
|
||
// only for test
|
||
//s = L"X:\\AVS\\Sources\\AVSOfficeStudio\\AVSOfficePDFWriter\\Tests\\TestSvgToPDF\\bin\\files\\coffe.jpg";
|
||
#endif
|
||
CString imgPath = s;
|
||
|
||
if (0 != s.Find(_T("http:")) &&
|
||
0 != s.Find(_T("https:")) &&
|
||
0 != s.Find(_T("ftp:")) &&
|
||
0 != s.Find(_T("file:")))
|
||
{
|
||
if (CString(sHtmlPlace).GetLength())
|
||
imgPath = CComBSTR (sHtmlPlace) + _T("/") + s;
|
||
else
|
||
imgPath = s;
|
||
|
||
imgPath.Replace( _T("\\"), _T("/") );
|
||
}
|
||
|
||
if (0 == s.Find(_T("file:///")))
|
||
{
|
||
imgPath.Replace(_T("file:///"), _T(""));
|
||
imgPath.Replace( _T("\\"), _T("/") );
|
||
}
|
||
|
||
CString base64TempFile;
|
||
if (0 == s.Find(_T("data:")))
|
||
{
|
||
try
|
||
{
|
||
int nFind = s.Find(_T(","));
|
||
s = s.Right(s.GetLength() - (nFind + 1));
|
||
|
||
base64TempFile = GetTempFileName();
|
||
CStringA sBase64MultyByte;
|
||
sBase64MultyByte = s;
|
||
BYTE *byteIm = NULL;
|
||
DWORD nBuffLen = 0;
|
||
bool bDecoderRes = DecodeBase64 (sBase64MultyByte, &byteIm, &nBuffLen);
|
||
if (bDecoderRes)
|
||
{
|
||
WriteFile (base64TempFile, byteIm);
|
||
imgPath = base64TempFile;
|
||
}
|
||
else throw;
|
||
}
|
||
catch (...)
|
||
{
|
||
ATLTRACE2 ("CommandType::ctBrushTexturePath:base64Decoder failed!\n");
|
||
}
|
||
}
|
||
|
||
current += 2 * _sLen;
|
||
curindex += 2 * _sLen;
|
||
|
||
BSTR bstrImgPath = imgPath.AllocSysString();
|
||
oWriter.put_BrushTexturePath(bstrImgPath);
|
||
SysFreeString (bstrImgPath);
|
||
|
||
if (!base64TempFile.IsEmpty())
|
||
{
|
||
DeleteFile(base64TempFile);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case ctBrushGradient:
|
||
{
|
||
current++;
|
||
curindex++;
|
||
|
||
CString strAttrMain = L"";
|
||
CString strColors = L"";
|
||
BOOL bIsLinear = TRUE;
|
||
|
||
while (TRUE)
|
||
{
|
||
BYTE _command = *current;
|
||
current++;
|
||
curindex++;
|
||
|
||
if (251 == _command)
|
||
break;
|
||
|
||
switch (_command)
|
||
{
|
||
case 0:
|
||
{
|
||
current += 5;
|
||
curindex += 5;
|
||
|
||
m = (INT32*)current;
|
||
current += 4 * 4;
|
||
curindex += 4 * 4;
|
||
|
||
double d1 = (*m++) / 100000.0;
|
||
double d2 = (*m++) / 100000.0;
|
||
double d3 = (*m++) / 100000.0;
|
||
double d4 = (*m++) / 100000.0;
|
||
|
||
strAttrMain.Format (L"x1 = '%f' y1 = '%f' x2 = '%f' y2 = '%f' gradientUnits='userSpaceOnUse' ", d1, d2, d3, d4);
|
||
break;
|
||
}
|
||
case 1:
|
||
{
|
||
bIsLinear = false;
|
||
|
||
current++;
|
||
curindex++;
|
||
|
||
m = (INT32*)current;
|
||
current += 6 * 4;
|
||
curindex += 6 * 4;
|
||
|
||
double d1 = (*m++) / 100000.0;
|
||
double d2 = (*m++) / 100000.0;
|
||
double d3 = (*m++) / 100000.0;
|
||
double d4 = (*m++) / 100000.0;
|
||
double d5 = (*m++) / 100000.0;
|
||
double d6 = (*m++) / 100000.0;
|
||
|
||
strAttrMain.Format (L"cx = '%f' cy = '%f' r0 = '%f' r1 = '%f' rx = '%f' ry = '%f' gradientUnits='userSpaceOnUse' ", d1, d2, d5, d6, d1, d2);
|
||
break;
|
||
}
|
||
case 2:
|
||
{
|
||
int nCountColors = *((INT32*)current);
|
||
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
for (int nI = 0; nI < nCountColors; ++nI)
|
||
{
|
||
int pos = *((INT32*)current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
double dPos = pos / 100000.0;
|
||
byte _r = *current++;
|
||
byte _g = *current++;
|
||
byte _b = *current++;
|
||
byte _a = *current++;
|
||
|
||
curindex += 4;
|
||
|
||
int _color = ((_b << 16) & 0xFF0000) | ((_g << 8) & 0xFF00) | _r;
|
||
|
||
CString sColor;
|
||
sColor.Format (L"<stop stop-color='%d' stop-opacity='%f' offset='%f' />", _color, _a / 255.0, dPos);
|
||
strColors += sColor;
|
||
}
|
||
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
};
|
||
}
|
||
|
||
CString strXml = L"";
|
||
|
||
if (bIsLinear)
|
||
{
|
||
strXml = L"<linearGradient " + strAttrMain + L">" + strColors + L"</linearGradient>";
|
||
|
||
VARIANT oVar;
|
||
oVar.vt = VT_BSTR;
|
||
oVar.bstrVal = CComBSTR(strXml);
|
||
oWriter.SetAdditionalParam(L"Fill-LinearGradient", oVar);
|
||
}
|
||
else
|
||
{
|
||
strXml = L"<radialGradient " + strAttrMain + L">" + strColors + L"</radialGradient>";
|
||
|
||
VARIANT oVar;
|
||
oVar.vt = VT_BSTR;
|
||
oVar.bstrVal = CComBSTR(strXml);
|
||
oWriter.SetAdditionalParam(L"Fill-RadialGradient", oVar);
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case ctBrushTextureMode:
|
||
{
|
||
ATLTRACE2 ("CommandType::ctBrushTextureMode:\n");
|
||
|
||
LONG mode = (LONG)(*current);
|
||
oWriter.put_BrushTextureMode(mode);
|
||
|
||
current += 1;
|
||
curindex += 1;
|
||
}
|
||
break;
|
||
case ctBrushTextureAlpha:
|
||
{
|
||
ATLTRACE2 ("CommandType::ctBrushTextureAlpha:\n");
|
||
|
||
LONG txalpha = (LONG)(*current);
|
||
oWriter.put_BrushTextureAlpha(txalpha);
|
||
|
||
current += 1;
|
||
curindex += 1;
|
||
}
|
||
break;
|
||
case ctSetTransform:
|
||
ATLTRACE2 ("CommandType::ctSetTransform:\n");
|
||
m = (INT32*)current;
|
||
current += 6 * 4;
|
||
curindex += 6 * 4;
|
||
|
||
m1 = (*m++) / 100000.0;
|
||
m2 = (*m++) / 100000.0;
|
||
m3 = (*m++) / 100000.0;
|
||
m4 = (*m++) / 100000.0;
|
||
m5 = (*m++) / 100000.0;
|
||
m6 = (*m++) / 100000.0;
|
||
|
||
oWriter.SetTransform(m1, m2, m3, m4, m5, m6);
|
||
break;
|
||
case ctPathCommandStart:
|
||
ATLTRACE2 ("CommandType::ctPathCommandStart:\n");
|
||
if (bIsPathOpened)
|
||
{
|
||
oWriter.PathCommandEnd();
|
||
oWriter.EndCommand(4);
|
||
oWriter.BeginCommand(4);
|
||
oWriter.PathCommandStart();
|
||
}
|
||
else
|
||
{
|
||
oWriter.BeginCommand(4);
|
||
oWriter.PathCommandStart();
|
||
}
|
||
bIsPathOpened = true;
|
||
break;
|
||
case ctPathCommandMoveTo:
|
||
ATLTRACE2 ("CommandType::ctPathCommandMoveTo:\n");
|
||
m = (INT32*)current;
|
||
current += 2 * 4;
|
||
curindex += 2 * 4;
|
||
|
||
m1 = (*m++) / 100000.0;
|
||
m2 = (*m++) / 100000.0;
|
||
oWriter.PathCommandMoveTo(m1, m2);
|
||
break;
|
||
case ctPathCommandLineTo:
|
||
ATLTRACE2 ("CommandType::ctPathCommandLineTo:\n");
|
||
m = (INT32*)current;
|
||
current += 2 * 4;
|
||
curindex += 2 * 4;
|
||
|
||
m1 = (*m++) / 100000.0;
|
||
m2 = (*m++) / 100000.0;
|
||
oWriter.PathCommandLineTo(m1, m2);
|
||
break;
|
||
case ctPathCommandCurveTo:
|
||
ATLTRACE2 ("CommandType::ctPathCommandCurveTo:\n");
|
||
m = (INT32*)current;
|
||
current += 6 * 4;
|
||
curindex += 6 * 4;
|
||
|
||
m1 = (*m++) / 100000.0;
|
||
m2 = (*m++) / 100000.0;
|
||
m3 = (*m++) / 100000.0;
|
||
m4 = (*m++) / 100000.0;
|
||
m5 = (*m++) / 100000.0;
|
||
m6 = (*m++) / 100000.0;
|
||
|
||
oWriter.PathCommandCurveTo(m1, m2, m3, m4, m5, m6);
|
||
break;
|
||
case ctPathCommandClose:
|
||
ATLTRACE2 ("CommandType::ctPathCommandClose:\n");
|
||
oWriter.PathCommandClose();
|
||
break;
|
||
case ctDrawPath:
|
||
ATLTRACE2 ("CommandType::ctDrawPath\n");
|
||
m = (INT32*)current;
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
oWriter.DrawPath(*m);
|
||
break;
|
||
case ctDrawImageFromFile:
|
||
{
|
||
ATLTRACE2 ("CommandType::ctDrawImageFromFile:\n");
|
||
m = (INT32*)current;
|
||
current += 2;
|
||
curindex += 2;
|
||
|
||
_sLen = (int)(*m);
|
||
CStringW sTempStr;
|
||
sTempStr.Append((WCHAR*)current, _sLen);
|
||
s = sTempStr;
|
||
|
||
CString imgPath = s;
|
||
|
||
if (0 != s.Find(_T("http:")) &&
|
||
0 != s.Find(_T("https:")) &&
|
||
0 != s.Find(_T("ftp:")) &&
|
||
0 != s.Find(_T("file:")))
|
||
{
|
||
if (CString(sHtmlPlace).GetLength())
|
||
imgPath = CComBSTR (sHtmlPlace) + _T("/") + s;
|
||
else
|
||
imgPath = s;
|
||
|
||
imgPath.Replace( _T("\\"), _T("/") );
|
||
}
|
||
|
||
if (0 == s.Find(_T("file:///")))
|
||
{
|
||
imgPath.Replace(_T("file:///"), _T(""));
|
||
imgPath.Replace( _T("\\"), _T("/") );
|
||
}
|
||
|
||
CString base64TempFile;
|
||
if (0 == s.Find(_T("data:")))
|
||
{
|
||
try
|
||
{
|
||
int nFind = s.Find(_T(","));
|
||
s = s.Right(s.GetLength() - (nFind + 1));
|
||
|
||
base64TempFile = GetTempFileName();
|
||
CStringA sBase64MultyByte;
|
||
sBase64MultyByte = s;
|
||
BYTE *byteIm = NULL;
|
||
DWORD nBuffLen = 0;
|
||
bool bDecoderRes = DecodeBase64 (sBase64MultyByte, &byteIm, &nBuffLen);
|
||
if (bDecoderRes)
|
||
{
|
||
WriteFile (base64TempFile, byteIm);
|
||
imgPath = base64TempFile;
|
||
}
|
||
else throw;
|
||
}
|
||
catch (...)
|
||
{
|
||
ATLTRACE2 ("CommandType::ctDrawImageFromFile:base64Decoder failed!\n");
|
||
}
|
||
}
|
||
|
||
current += _sLen;
|
||
curindex += _sLen;
|
||
|
||
m = (INT32*)current;
|
||
current += 4 * 4;
|
||
curindex += 4 * 4;
|
||
|
||
m1 = (*m++) / 100000.0;
|
||
m2 = (*m++) / 100000.0;
|
||
m3 = (*m++) / 100000.0;
|
||
m4 = (*m++) / 100000.0;
|
||
|
||
try
|
||
{
|
||
BSTR bstrImgPath = imgPath.AllocSysString();
|
||
oWriter.DrawImageFromFile(bstrImgPath, m1, m2, m3, m4);
|
||
SysFreeString (bstrImgPath);
|
||
}
|
||
catch (...)
|
||
{
|
||
ATLTRACE2 ("oWriter.DrawImageFromFile failed!\n");
|
||
}
|
||
|
||
if (!base64TempFile.IsEmpty())
|
||
{
|
||
DeleteFile(base64TempFile);
|
||
}
|
||
}
|
||
break;
|
||
case ctFontName:
|
||
{
|
||
ATLTRACE2 ("CommandType::ctFontName\n");
|
||
ms = (USHORT*)current;
|
||
current += 2;
|
||
curindex += 2;
|
||
|
||
_sLen = (int)(*ms);
|
||
CStringW sTempFontNameW;
|
||
sTempFontNameW.Append((WCHAR*)current, _sLen);
|
||
s = sTempFontNameW;
|
||
|
||
current += 2 * _sLen;
|
||
curindex += 2 * _sLen;
|
||
BSTR bstrFontName = s.AllocSysString();
|
||
oWriter.put_FontName (bstrFontName);
|
||
SysFreeString (bstrFontName);
|
||
}
|
||
break;
|
||
case ctFontSize:
|
||
ATLTRACE2 ("CommandType::ctFontSize:\n");
|
||
m = (INT32*)current;
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
m1 = (*m++) / 100000.0;
|
||
oWriter.put_FontSize (m1);
|
||
break;
|
||
case ctFontStyle:
|
||
ATLTRACE2 ("CommandType::ctFontStyle:\n");
|
||
m = (INT32*)current;
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
oWriter.put_FontStyle (*m);
|
||
break;
|
||
case ctDrawText:
|
||
{
|
||
ms = (USHORT*)current;
|
||
current += 2;
|
||
curindex += 2;
|
||
|
||
_sLen = (int)(*ms);
|
||
CStringW sTempDrawText;
|
||
sTempDrawText.Append ((WCHAR*)current, _sLen);
|
||
s = sTempDrawText;
|
||
|
||
//CStringA aDebugText;
|
||
//aDebugText = sTempDrawText;
|
||
//ATLTRACE2 ("CommandType::ctDrawText: %s\n", aDebugText);
|
||
|
||
current += 2 * _sLen;
|
||
curindex += 2 * _sLen;
|
||
|
||
m = (INT32*)current;
|
||
current += 2 * 4;
|
||
curindex += 2 * 4;
|
||
|
||
m1 = (*m++) / 100000.0;
|
||
m2 = (*m++) / 100000.0;
|
||
|
||
BSTR bstrText = s.AllocSysString();
|
||
oWriter.CommandDrawText(bstrText, m1, m2, 0, 0, 0);
|
||
SysFreeString (bstrText);
|
||
}
|
||
break;
|
||
case ctBeginCommand:
|
||
ATLTRACE2 ("CommandType::ctBeginCommand:\n");
|
||
m = (INT32*)current;
|
||
current += 4;
|
||
curindex += 4;
|
||
if (bIsPathOpened)
|
||
{
|
||
oWriter.PathCommandEnd();
|
||
oWriter.EndCommand(4);
|
||
bIsPathOpened = false;
|
||
}
|
||
oWriter.BeginCommand((DWORD)(*m));
|
||
break;
|
||
case ctGradientFill:
|
||
{
|
||
gradientType = (INT32)(*current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
CString sXml, sXmlStop;
|
||
|
||
if (0 == gradientType) // linearGradient
|
||
{
|
||
m = (INT32*)current;
|
||
current += 4 * 4;
|
||
curindex += 4 * 4;
|
||
|
||
double x1 = (*m++) / 100000.0;
|
||
double x2 = (*m++) / 100000.0;
|
||
double y1 = (*m++) / 100000.0;
|
||
double y2 = (*m++) / 100000.0;
|
||
|
||
int stops = (INT32)(*current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
sXml.Format(_T("<linearGradient x1='%f' x2='%f' y1='%f' y2='%f'>"), x1, x2, y1, y2);
|
||
|
||
for (int i = 0; i < stops; ++i)
|
||
{
|
||
INT32 color = static_cast<INT32>(*current);
|
||
double opacity = static_cast<double>(static_cast<INT32>(*(current + 1))) / 255.0;
|
||
double offset = static_cast<double>(static_cast<INT32>(*(current + 2))) / 255.0;
|
||
|
||
current += 6 * 4; // 4 + 1 + 1
|
||
curindex += 6 * 4;
|
||
|
||
sXmlStop.Format(_T("<stop stop-color='%d' offset='%f' stop-opacity='%f' />"), color, offset);
|
||
sXml += sXmlStop;
|
||
}
|
||
|
||
sXml += _T("</linearGradient>");
|
||
|
||
if (stops)
|
||
{
|
||
VARIANT oVar;
|
||
oVar.vt = VT_BSTR;
|
||
oVar.bstrVal = CComBSTR(sXml);
|
||
oWriter.SetAdditionalParam(L"Fill-LinearGradient", oVar);
|
||
}
|
||
}
|
||
else if (1 == gradientType)
|
||
{
|
||
m = (INT32*)current;
|
||
current += 5 * 4;
|
||
curindex += 5 * 4;
|
||
|
||
double cx = (*m++) / 100000.0;
|
||
double cy = (*m++) / 100000.0;
|
||
double r = (*m++) / 100000.0;
|
||
double fx = (*m++) / 100000.0;
|
||
double fy = (*m++) / 100000.0;
|
||
|
||
int stops = (INT32)(*current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
sXml.Format(_T("<radialGradient cx='%f' cy='%f' r='%f' fx='%f' fy='%f' >"), cx, cy, r, fx, fy);
|
||
|
||
for (int i = 0; i < stops; ++i)
|
||
{
|
||
INT32 color = static_cast<INT32>(*current);
|
||
double opacity = static_cast<double>(static_cast<INT32>(*(current + 1))) / 255.0;
|
||
double offset = static_cast<double>(static_cast<INT32>(*(current + 2))) / 255.0;
|
||
|
||
current += 6 * 4; // 4 + 1 + 1
|
||
curindex += 6 * 4;
|
||
|
||
sXmlStop.Format(_T("<stop stop-color='%d' offset='%f' stop-opacity='%f' />"), color, offset);
|
||
sXml += sXmlStop;
|
||
}
|
||
|
||
sXml += _T("</radialGradient>");
|
||
|
||
if (stops)
|
||
{
|
||
VARIANT oVar;
|
||
oVar.vt = VT_BSTR;
|
||
oVar.bstrVal = CComBSTR(sXml);
|
||
oWriter.SetAdditionalParam(L"Fill-RadialGradient", oVar);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case ctGradientFillXML:
|
||
{
|
||
gradientType = (INT32)(*current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
m = (INT32*)current;
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
_sLen = (int)(*m);
|
||
CStringW sTempStr;
|
||
sTempStr.Append((WCHAR*)current, _sLen * 0.5);
|
||
s = sTempStr;
|
||
|
||
if (0 == gradientType) // linearGradient
|
||
CreateLinearGradientFromSvgXml(s, TRUE);
|
||
else if (1 == gradientType) // radialGradient
|
||
CreateRadialGradientFromSvgXml(s, TRUE);
|
||
}
|
||
break;
|
||
case ctGradientStroke:
|
||
{
|
||
gradientType = (INT32)(*current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
CString sXml, sXmlStop;
|
||
|
||
if (0 == gradientType) // linearGradient
|
||
{
|
||
m = (INT32*)current;
|
||
current += 4 * 4;
|
||
curindex += 4 * 4;
|
||
|
||
double x1 = (*m++) / 100000.0;
|
||
double x2 = (*m++) / 100000.0;
|
||
double y1 = (*m++) / 100000.0;
|
||
double y2 = (*m++) / 100000.0;
|
||
|
||
int stops = (INT32)(*current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
sXml.Format(_T("<linearGradient x1='' x2='' y1='' y2=''>"), x1, x2, y1, y2);
|
||
|
||
for (int i = 0; i < stops; ++i)
|
||
{
|
||
INT32 color = static_cast<INT32>(*current);
|
||
double opacity = static_cast<double>(static_cast<INT32>(*(current + 1))) / 255.0;
|
||
double offset = static_cast<double>(static_cast<INT32>(*(current + 2))) / 255.0;
|
||
|
||
current += 6 * 4; // 4 + 1 + 1
|
||
curindex += 6 * 4;
|
||
|
||
sXmlStop.Format(_T("<stop stop-color='%d' offset='%f' stop-opacity='%f' />"), color, offset);
|
||
sXml += sXmlStop;
|
||
}
|
||
|
||
sXml += _T("</linearGradient>");
|
||
|
||
if (stops)
|
||
{
|
||
VARIANT oVar;
|
||
oVar.vt = VT_BSTR;
|
||
oVar.bstrVal = CComBSTR(sXml);
|
||
oWriter.SetAdditionalParam(L"Stroke-LinearGradient", oVar);
|
||
}
|
||
}
|
||
else if (1 == gradientType)
|
||
{
|
||
m = (INT32*)current;
|
||
current += 5 * 4;
|
||
curindex += 5 * 4;
|
||
|
||
double cx = (*m++) / 100000.0;
|
||
double cy = (*m++) / 100000.0;
|
||
double r = (*m++) / 100000.0;
|
||
double fx = (*m++) / 100000.0;
|
||
double fy = (*m++) / 100000.0;
|
||
|
||
int stops = (INT32)(*current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
sXml.Format(_T("<radialGradient cx='%f' cy='%f' r='%f' fx='%f' fy='%f' >"), cx, cy, r, fx, fy);
|
||
|
||
for (int i = 0; i < stops; ++i)
|
||
{
|
||
INT32 color = static_cast<INT32>(*current);
|
||
double opacity = static_cast<double>(static_cast<INT32>(*(current + 1))) / 255.0;
|
||
double offset = static_cast<double>(static_cast<INT32>(*(current + 2))) / 255.0;
|
||
|
||
current += 6 * 4; // 4 + 1 + 1
|
||
curindex += 6 * 4;
|
||
|
||
sXmlStop.Format(_T("<stop stop-color='%d' offset='%f' stop-opacity='%f' />"), color, offset);
|
||
sXml += sXmlStop;
|
||
}
|
||
|
||
sXml += _T("</radialGradient>");
|
||
|
||
if (stops)
|
||
{
|
||
VARIANT oVar;
|
||
oVar.vt = VT_BSTR;
|
||
oVar.bstrVal = CComBSTR(sXml);
|
||
oWriter.SetAdditionalParam(L"Stroke-RadialGradient", oVar);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case ctGradientStrokeXML:
|
||
{
|
||
gradientType = (INT32)(*current);
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
m = (INT32*)current;
|
||
current += 4;
|
||
curindex += 4;
|
||
|
||
_sLen = (int)(*m);
|
||
CStringW sTempStr;
|
||
sTempStr.Append((WCHAR*)current, _sLen * 0.5);
|
||
s = sTempStr;
|
||
|
||
if (0 == gradientType) // linearGradient
|
||
CreateLinearGradientFromSvgXml(s, FALSE);
|
||
else if (1 == gradientType) // radialGradient
|
||
CreateRadialGradientFromSvgXml(s, FALSE);
|
||
}
|
||
break;
|
||
|
||
case ctEndCommand:
|
||
ATLTRACE2 ("CommandType::ctEndCommand:\n");
|
||
m = (INT32*)current;
|
||
current += 4;
|
||
curindex += 4;
|
||
if (bIsPathOpened)
|
||
{
|
||
oWriter.PathCommandEnd();
|
||
oWriter.EndCommand(4);
|
||
bIsPathOpened = false;
|
||
}
|
||
oWriter.EndCommand((DWORD)(*m));
|
||
oWriter.PathCommandEnd();
|
||
break;
|
||
default:
|
||
ATLTRACE2 ("CommandType:DEFAULT!\n");
|
||
break;
|
||
}; // switch (eCommand)
|
||
} // while (curindex < len)
|
||
} // BYTE* p = dstArray;
|
||
delete [] dstArray;
|
||
} // if (TRUE == bDecoderResult)
|
||
|
||
|
||
sHypers += _T("</linker>");
|
||
|
||
if (nReg)
|
||
{
|
||
oWriter.BeginCommand(8);
|
||
BSTR strHypers = sHypers.AllocSysString();
|
||
oWriter.CommandDrawText(strHypers, 0, 0, 0, 0, 0);
|
||
SysFreeString (strHypers);
|
||
oWriter.EndCommand(8);
|
||
}
|
||
|
||
if (sTempLogo != "")
|
||
{
|
||
DeleteFile (sTempLogo);
|
||
}
|
||
|
||
oWriter.SaveToFile(sDstFile);
|
||
|
||
} // if (NULL != dstArray)
|
||
|
||
} // for (size_t nLine = 0; nLine < asResFile.GetCount(); ++nLine)
|
||
} // try
|
||
catch (char *pcError)
|
||
{
|
||
ATLTRACE2 (pcError);
|
||
}
|
||
if (NULL != piWinFonts)
|
||
{
|
||
piWinFonts->Release();
|
||
piWinFonts = NULL;
|
||
}
|
||
|
||
return hRes;
|
||
}
|
||
|
||
// help functions
|
||
|
||
inline static PDF::Matrix BuildFromSvgMatrix(CString sXml)
|
||
{
|
||
if (sXml.GetLength())
|
||
{
|
||
int st = 0;
|
||
int del = sXml.Tokenize(_T("("), st).GetLength();
|
||
|
||
CString sTransform = sXml.Mid(del + 1, sXml.GetLength() - del - 2);
|
||
if (sTransform.GetLength())
|
||
{
|
||
CAtlArray<double> numbers;
|
||
if (ParseUtils::DoubleValues(sTransform, numbers))
|
||
{
|
||
if (6 == numbers.GetCount())
|
||
{
|
||
return PDF::Matrix(numbers[0], numbers[1], numbers[4], numbers[2], numbers[3], numbers[5], 0, 0, 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return PDF::Matrix();
|
||
}
|
||
|
||
BOOL CPDFWriter::ApplyFillGradient()
|
||
{
|
||
PDF::Rect pageBounds = PageBounds();
|
||
PDF::Rect pathBounds = PathBounds();
|
||
|
||
PDF::XForm* form = NULL;
|
||
int maskRefId = -1;
|
||
CString formName = L"";
|
||
CString stateName = L"";
|
||
CString alphaExt = L"";
|
||
|
||
PDF::Pattern* pattern = m_oPatternState.GetFill();
|
||
if (pattern)
|
||
{
|
||
// % fill
|
||
|
||
// /Pattern cs
|
||
// /P12345 scn
|
||
|
||
CString sVal;
|
||
sVal.Format(L"/P%d scn\012", pattern->GetRefIndex());
|
||
|
||
if (PDF::ShadingPatternType == pattern->GetType())
|
||
{
|
||
// NOTE! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
if (m_pCurrentExtGState)
|
||
{
|
||
ExtGState disableAlpha = CreateExtGState(m_pDocument);
|
||
if (disableAlpha)
|
||
{
|
||
disableAlpha->sBuffer = new CString(L"<< /Type /ExtGState\012 /CA 1\012 /ca 1\012>>");
|
||
alphaExt = CString(PageGetExtGStateName(m_pDocument->pCurPage, disableAlpha));
|
||
}
|
||
}
|
||
|
||
PDF::Shading* shading = (static_cast<PDF::ShadingPattern*>(pattern))->GetTopShading();
|
||
if (shading)
|
||
{
|
||
shading->SetTransform(PDF::Matrix(m_oCommandParams.oMatrix.fA, m_oCommandParams.oMatrix.fC, MMToPDFCoords(m_oCommandParams.oMatrix.fE),
|
||
m_oCommandParams.oMatrix.fB, m_oCommandParams.oMatrix.fD, MMToPDFCoords(m_oCommandParams.oMatrix.fF),
|
||
0, 0, 1));
|
||
|
||
shading->CalculateCoords(pathBounds, pageBounds.Height);
|
||
}
|
||
|
||
PDF::Pattern* alpha = pattern->GetAlphaPattern();
|
||
if (alpha)
|
||
{
|
||
if (PDF::ShadingPatternType == alpha->GetType())
|
||
{
|
||
PDF::Shading* shading = (static_cast<PDF::ShadingPattern*>(alpha))->GetTopShading();
|
||
if (shading)
|
||
{
|
||
shading->SetTransform(PDF::Matrix(m_oCommandParams.oMatrix.fA, m_oCommandParams.oMatrix.fC, MMToPDFCoords(m_oCommandParams.oMatrix.fE),
|
||
m_oCommandParams.oMatrix.fB, m_oCommandParams.oMatrix.fD, MMToPDFCoords(m_oCommandParams.oMatrix.fF),
|
||
0, 0, 1));
|
||
|
||
shading->CalculateCoords(pathBounds, pageBounds.Height);
|
||
|
||
PDF::PatternAlphaGroup* alpha = m_oPatterns.GetAlphaGroupTop();
|
||
if (alpha)
|
||
{
|
||
form = new PDF::XForm();
|
||
if (form)
|
||
{
|
||
ExtGState smask = CreateExtGState(m_pDocument);
|
||
if (smask)
|
||
{
|
||
CString str; str.Format(L"<< /Type /ExtGState\012 /SMask %d 0 R\012 /ca 1\012>>", alpha->GetMask()->GetId());
|
||
smask->sBuffer = new CString(str);
|
||
|
||
stateName = CString(PageGetExtGStateName(m_pDocument->pCurPage, smask));
|
||
|
||
Proxy proxyForm = GenXRef<PDF::XForm>(form, OCLASS_XFORM);
|
||
|
||
form->SetBound(pageBounds);
|
||
|
||
alpha->SetFormId(form->GetId());
|
||
alpha->GetMask()->SetStateId(smask->pHeader.nObjId & (~OTYPE_INDIRECT));
|
||
|
||
m_oPatterns.AddXForm(form);
|
||
|
||
XrefEntry entry = XrefGetEntry(m_pDocument->pXref, m_pDocument->pXref->pEntries->nCount - 1);
|
||
if (entry)
|
||
{
|
||
XObject obj = (XObject)entry->pObj;
|
||
if (obj)
|
||
{
|
||
formName = CString(PageGetXObjectName(m_pDocument->pCurPage, obj));
|
||
}
|
||
}
|
||
|
||
RebuildResources();
|
||
|
||
maskRefId = alpha->GetMask()->GetStateId();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
PageAttr attr = (PageAttr)m_pDocument->pCurPage->pAttr;
|
||
if (attr)
|
||
{
|
||
m_strPatternFill = CString (L"/Pattern cs\012") + sVal;
|
||
if (alphaExt.GetLength())
|
||
{
|
||
m_strPatternFill = L"/" + alphaExt + L" gs \012" + m_strPatternFill;
|
||
}
|
||
|
||
StreamWriteStr(attr->pStream, CStringA(m_strPatternFill));
|
||
}
|
||
|
||
if (form)
|
||
{
|
||
// q /s13 gs /x14 Do Q
|
||
// <20> x-N <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> s-N
|
||
|
||
m_MaskWithFormCommands.Format(L"q\012/%s gs /%s Do\012Q\012", stateName, formName);
|
||
|
||
m_XForm = form;
|
||
}
|
||
|
||
m_oPatternState.SetFill(NULL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
BOOL CPDFWriter::ApplyStrokeGradient()
|
||
{
|
||
PDF::Rect pageBounds = PageBounds();
|
||
PDF::Rect pathBounds = PathBounds();
|
||
|
||
PDF::XForm* form = NULL;
|
||
int maskRefId = -1;
|
||
CString formName = L"";
|
||
CString stateName = L"";
|
||
CString alphaExt = L"";
|
||
|
||
PDF::Pattern* pattern = m_oPatternState.GetStroke();
|
||
if (pattern)
|
||
{
|
||
// % stroke
|
||
|
||
// /Pattern CS
|
||
// /P12345 SCN
|
||
|
||
CString sVal;
|
||
sVal.Format(L"/P%d SCN\012", pattern->GetRefIndex());
|
||
|
||
if (PDF::ShadingPatternType == pattern->GetType())
|
||
{
|
||
// NOTE! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
if (m_pCurrentExtGState)
|
||
{
|
||
ExtGState disableAlpha = CreateExtGState(m_pDocument);
|
||
if (disableAlpha)
|
||
{
|
||
disableAlpha->sBuffer = new CString(L"<< /Type /ExtGState\012 /CA 1\012 /ca 1\012>>");
|
||
alphaExt = CString(PageGetExtGStateName(m_pDocument->pCurPage, disableAlpha));
|
||
}
|
||
}
|
||
|
||
|
||
PDF::Shading* shading = (static_cast<PDF::ShadingPattern*>(pattern))->GetTopShading();
|
||
if (shading)
|
||
{
|
||
shading->SetTransform(PDF::Matrix(m_oCommandParams.oMatrix.fA, m_oCommandParams.oMatrix.fC, MMToPDFCoords(m_oCommandParams.oMatrix.fE),
|
||
m_oCommandParams.oMatrix.fB, m_oCommandParams.oMatrix.fD, MMToPDFCoords(m_oCommandParams.oMatrix.fF),
|
||
0, 0, 1));
|
||
|
||
shading->CalculateCoords(pathBounds, pageBounds.Height);
|
||
}
|
||
|
||
PDF::Pattern* alpha = pattern->GetAlphaPattern();
|
||
if (alpha)
|
||
{
|
||
if (PDF::ShadingPatternType == alpha->GetType())
|
||
{
|
||
PDF::Shading* shading = (static_cast<PDF::ShadingPattern*>(alpha))->GetTopShading();
|
||
if (shading)
|
||
{
|
||
shading->SetTransform(PDF::Matrix(m_oCommandParams.oMatrix.fA, m_oCommandParams.oMatrix.fC, MMToPDFCoords(m_oCommandParams.oMatrix.fE),
|
||
m_oCommandParams.oMatrix.fB, m_oCommandParams.oMatrix.fD, MMToPDFCoords(m_oCommandParams.oMatrix.fF),
|
||
0, 0, 1));
|
||
|
||
shading->CalculateCoords(pathBounds, pageBounds.Height);
|
||
|
||
PDF::PatternAlphaGroup* alpha = m_oPatterns.GetAlphaGroupTop();
|
||
if (alpha)
|
||
{
|
||
form = new PDF::XForm();
|
||
if (form)
|
||
{
|
||
ExtGState smask = CreateExtGState(m_pDocument);
|
||
if (smask)
|
||
{
|
||
CString str; str.Format(L"<< /Type /ExtGState\012 /SMask %d 0 R\012 /ca 1\012>>", alpha->GetMask()->GetId());
|
||
smask->sBuffer = new CString(str);
|
||
|
||
stateName = CString(PageGetExtGStateName(m_pDocument->pCurPage, smask));
|
||
|
||
Proxy proxyForm = GenXRef<PDF::XForm>(form, OCLASS_XFORM);
|
||
|
||
form->SetBound(pageBounds);
|
||
|
||
alpha->SetFormId(form->GetId());
|
||
alpha->GetMask()->SetStateId(smask->pHeader.nObjId & (~OTYPE_INDIRECT));
|
||
|
||
m_oPatterns.AddXForm(form);
|
||
|
||
XrefEntry entry = XrefGetEntry(m_pDocument->pXref, m_pDocument->pXref->pEntries->nCount - 1);
|
||
if (entry)
|
||
{
|
||
XObject obj = (XObject)entry->pObj;
|
||
if (obj)
|
||
{
|
||
formName = CString(PageGetXObjectName(m_pDocument->pCurPage, obj));
|
||
}
|
||
}
|
||
|
||
RebuildResources();
|
||
|
||
maskRefId = alpha->GetMask()->GetStateId();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
PageAttr attr = (PageAttr)m_pDocument->pCurPage->pAttr;
|
||
if (attr)
|
||
{
|
||
m_strPatternStroke = CString (L"/Pattern CS\012") + sVal;
|
||
if (alphaExt.GetLength())
|
||
{
|
||
m_strPatternFill = L"/" + alphaExt + L" gs \012" + m_strPatternStroke;
|
||
}
|
||
|
||
StreamWriteStr(attr->pStream, CStringA(m_strPatternStroke));
|
||
}
|
||
|
||
if (form)
|
||
{
|
||
// q /s13 gs /x14 Do Q
|
||
// <20> x-N <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> s-N
|
||
|
||
m_MaskWithFormCommands.Format(L"q /%s gs /%s Do Q", stateName, formName);
|
||
|
||
m_XForm = form;
|
||
}
|
||
|
||
m_oPatternState.SetStroke(NULL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
BOOL CPDFWriter::ApplyTileFill()
|
||
{
|
||
IUnknown* pImage = ImageUtils::LoadImage(m_oBrush.TexturePath);
|
||
if (pImage)
|
||
{
|
||
LONG width = 0;
|
||
LONG height = 0;
|
||
|
||
m_bUseImageTextureAlpha = TRUE;
|
||
|
||
if ((m_bUseImageTextureAlpha || m_bIsWhiteBackImage) && (NULL != pImage))
|
||
{
|
||
MediaCore::IAVSUncompressedVideoFrame* pFrame = NULL;
|
||
if (SUCCEEDED(pImage->QueryInterface(&pFrame)))
|
||
{
|
||
if (pFrame)
|
||
{
|
||
BYTE* buffer = NULL;
|
||
|
||
pFrame->get_Width(&width);
|
||
pFrame->get_Height(&height);
|
||
pFrame->get_Buffer(&buffer);
|
||
|
||
LONG lCountPix = width * height;
|
||
|
||
if (m_bIsWhiteBackImage)
|
||
{
|
||
while (lCountPix > 0)
|
||
{
|
||
if (0 == buffer[3])
|
||
memset(buffer, 0xFF, 4);
|
||
|
||
--lCountPix;
|
||
buffer += 4;
|
||
}
|
||
}
|
||
else if (m_bUseImageTextureAlpha)
|
||
{
|
||
double alpha = ((double)m_oBrush.TextureAlpha / 255.0);
|
||
|
||
while (lCountPix > 0)
|
||
{
|
||
buffer[3] *= alpha;
|
||
--lCountPix;
|
||
buffer += 4;
|
||
}
|
||
}
|
||
|
||
RELEASEINTERFACE(pFrame);
|
||
}
|
||
}
|
||
}
|
||
|
||
m_bUseImageTextureAlpha = FALSE;
|
||
|
||
if (SUCCEEDED(LoadImageFromInterface(&pImage, TRUE)))
|
||
{
|
||
if (m_pCurrentXObject)
|
||
{
|
||
int RefImageId = m_pCurrentXObject->pHeader.nObjId;
|
||
|
||
PDF::Rect pageBounds = PageBounds();
|
||
PDF::Rect pathBounds = PathBounds();
|
||
|
||
PDF::TilePattern* shading = new PDF::TilePattern();
|
||
if (shading)
|
||
{
|
||
// create pdf ref index
|
||
|
||
Proxy ref = GenXRef<PDF::TilePattern>(shading, OCLASS_PATTERN_REF);
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
shading->SetRefIdX(RefImageId & (~OTYPE_INDIRECT));
|
||
shading->SetBox(PDF::Rect(0.0f, 0.0f, floor ( MMToPDFCoords(PxToMM(width)) ), floor ( MMToPDFCoords(PxToMM(height))) ) );
|
||
shading->SetId(ref->pHeader.nObjId & (~OTYPE_INDIRECT));
|
||
shading->SetTransform(PDF::Matrix(m_oCommandParams.oMatrix.fA, m_oCommandParams.oMatrix.fC,
|
||
MMToPDFCoords(m_oCommandParams.oMatrix.fE),
|
||
m_oCommandParams.oMatrix.fB, m_oCommandParams.oMatrix.fD,
|
||
MMToPDFCoords(m_oCommandParams.oMatrix.fF),
|
||
0, 0, 1));
|
||
|
||
shading->CalculateCoords(pathBounds, pageBounds.Height);
|
||
|
||
m_oPatternState.SetTiling(shading);
|
||
m_oPatterns.Add(shading);
|
||
|
||
RebuildResources();
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
CString sVal;
|
||
sVal.Format(L"/P%d scn\012", shading->GetRefIndex());
|
||
|
||
PageAttr attr = (PageAttr)m_pDocument->pCurPage->pAttr;
|
||
if (attr)
|
||
{
|
||
StreamWriteStr(attr->pStream, "/Pattern cs\012");
|
||
StreamWriteStr(attr->pStream, CStringA(sVal));
|
||
}
|
||
|
||
m_oPatternState.SetFill(NULL);
|
||
|
||
RELEASEINTERFACE(pImage);
|
||
|
||
return TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
RELEASEINTERFACE(pImage);
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOL CPDFWriter::CreateLinearGradientFromSvgXml(const CString& sXml, BOOL fill)
|
||
{
|
||
int FormId = -1;
|
||
|
||
XrefEntry entry = XrefGetEntry(m_pDocument->pXref, m_pDocument->pXref->pEntries->nCount - 2);
|
||
if (entry)
|
||
{
|
||
XObject obj = (XObject)entry->pObj;
|
||
if (obj)
|
||
{
|
||
FormId = (obj->pHeader.nObjId & (~OTYPE_INDIRECT));
|
||
}
|
||
}
|
||
|
||
XmlUtils::CXmlNode oXml;
|
||
if (oXml.FromXmlString(sXml))
|
||
{
|
||
PDF::ShadingPattern* alphaShading = NULL;
|
||
|
||
PDF::ShadingPattern* shading = new PDF::ShadingPattern();
|
||
if (shading)
|
||
{
|
||
PDF::AxialShading* axial = new PDF::AxialShading();
|
||
if (axial)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||
|
||
BOOL userSpaceOnUse = (L"userSpaceOnUse" == oXml.GetAttribute(L"gradientUnits"));
|
||
BOOL isSvgElement = (L"svg" == oXml.GetAttribute(L"sourceType"));
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
double x1 = _wtof(oXml.GetAttributeOrValue(L"x1", L"0"));
|
||
double y1 = _wtof(oXml.GetAttributeOrValue(L"y1", L"0"));
|
||
double x2 = _wtof(oXml.GetAttributeOrValue(L"x2", L"1"));
|
||
double y2 = _wtof(oXml.GetAttributeOrValue(L"y2", L"0"));
|
||
|
||
if (FALSE == isSvgElement)
|
||
{
|
||
if (userSpaceOnUse)
|
||
{
|
||
x1 = MMToPDFCoords(x1);
|
||
y1 = MMToPDFCoords(y1);
|
||
x2 = MMToPDFCoords(x2);
|
||
y2 = MMToPDFCoords(y2);
|
||
}
|
||
}
|
||
|
||
axial->SetGradientVector(PDF::float4(x1, y1, x2, y2), !userSpaceOnUse);
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
PDF::Matrix matrix = BuildFromSvgMatrix(oXml.GetAttributeOrValue(L"gradientTransform"));
|
||
axial->SetTransform(matrix);
|
||
|
||
float width = 0.0f; GetWidth(&width);
|
||
float height = 0.0f; GetHeight(&height);
|
||
|
||
GenXRef<PDF::ShadingPattern>(shading, OCLASS_PATTERN_REF);
|
||
|
||
XmlUtils::CXmlNodes oNodes;
|
||
if (oXml.GetNodes(L"stop", oNodes))
|
||
{
|
||
CAtlArray<PDF::ExponentialInterpolationFunction*> functions;
|
||
|
||
CAtlArray<PDF::float3> colors;
|
||
CAtlArray<float> offsets;
|
||
CAtlArray<float> opacity;
|
||
|
||
BOOL alphaPatternEnable = FALSE;
|
||
|
||
for (int i = 0; i < oNodes.GetCount(); ++i)
|
||
{
|
||
XmlUtils::CXmlNode oNode;
|
||
if(oNodes.GetAt(i, oNode))
|
||
{
|
||
long color = _wtol(oNode.GetAttributeOrValueBase(L"stop-color", L"0"));
|
||
float off = (float)(_wtof(oNode.GetAttributeOrValueBase(L"offset", L"0")));
|
||
float alpha = (float)(min(max(_wtof(oNode.GetAttributeOrValueBase(L"stop-opacity", L"1")), 0.0f), 1.0));
|
||
|
||
colors.Add(PDF::float3((0xFF & color) / 255.0f, (0xFF & (color >> 8)) / 255.0f, (0xFF & (color >> 16)) / 255.0f));
|
||
offsets.Add(min(max(off, 0.0f), 1.0));
|
||
opacity.Add(alpha);
|
||
|
||
if (fabs(alpha - 1.0) > DBL_EPSILON)
|
||
{
|
||
alphaPatternEnable = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (colors.GetCount())// && FALSE == isSvgElement)
|
||
{
|
||
if (offsets[0] > DBL_EPSILON)
|
||
{
|
||
PDF::float3 color = colors[0];
|
||
float alpha = opacity[0];
|
||
|
||
colors.InsertAt(0, color);
|
||
offsets.InsertAt(0, 0.0f);
|
||
opacity.InsertAt(0, alpha);
|
||
}
|
||
|
||
long count = offsets.GetCount() - 1;
|
||
|
||
if (fabs(offsets[count] - 1.0) > DBL_EPSILON)
|
||
{
|
||
PDF::float3 color = colors[count];
|
||
float alpha = opacity[count];
|
||
|
||
colors.Add(color);
|
||
offsets.Add(1.0f);
|
||
opacity.Add(alpha);
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
if (2 == colors.GetCount() && 2 == offsets.GetCount())
|
||
{
|
||
PDF::ExponentialInterpolationFunction* func = new PDF::ExponentialInterpolationFunction();
|
||
if (func)
|
||
{
|
||
func->AddC(3, colors[0].f1, colors[0].f2, colors[0].f3);
|
||
func->AddC(3, colors[1].f1, colors[1].f2, colors[1].f3);
|
||
|
||
func->AddOffset(PDF::float2(offsets[0], offsets[1]));
|
||
func->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
func->AddN(1);
|
||
|
||
GenXRef<PDF::ExponentialInterpolationFunction>(func, OCLASS_FUNC_REF);
|
||
|
||
axial->AddFunc(func);
|
||
|
||
if (alphaPatternEnable)
|
||
{
|
||
alphaShading = new PDF::ShadingPattern();
|
||
if (alphaShading)
|
||
{
|
||
PDF::AxialShading* alphaAxial = new PDF::AxialShading();
|
||
if (alphaAxial)
|
||
{
|
||
alphaAxial->SetColorSpace(L"DeviceGray");
|
||
alphaAxial->SetGradientVector(PDF::float4(x1, y1, x2, y2), !userSpaceOnUse);
|
||
alphaAxial->SetTransform(matrix);
|
||
|
||
PDF::ExponentialInterpolationFunction* alphaFunc = new PDF::ExponentialInterpolationFunction();
|
||
if (alphaFunc)
|
||
{
|
||
alphaFunc->AddC(1, opacity[0]);
|
||
alphaFunc->AddC(1, opacity[1]);
|
||
|
||
alphaFunc->AddOffset(PDF::float2(offsets[0], offsets[1]));
|
||
alphaFunc->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
alphaFunc->AddN(1);
|
||
|
||
GenXRef<PDF::ShadingPattern>(alphaShading, OCLASS_PATTERN_REF);
|
||
GenXRef<PDF::ExponentialInterpolationFunction>(alphaFunc, OCLASS_FUNC_REF);
|
||
|
||
alphaAxial->AddFunc(alphaFunc);
|
||
alphaShading->AddShading(alphaAxial);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
PDF::StitchFunction* stitch = new PDF::StitchFunction();
|
||
if (stitch)
|
||
{
|
||
stitch->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
|
||
for (size_t i = 0; i < colors.GetCount() - 1; ++i)
|
||
{
|
||
PDF::ExponentialInterpolationFunction* func = new PDF::ExponentialInterpolationFunction();
|
||
if (func)
|
||
{
|
||
func->AddC(3, colors[i].f1, colors[i].f2, colors[i].f3);
|
||
func->AddC(3, colors[i + 1].f1, colors[i + 1].f2, colors[i + 1].f3);
|
||
|
||
func->AddOffset(PDF::float2(offsets[i], offsets[i + 1]));
|
||
func->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
func->AddN(1);
|
||
|
||
GenXRef<PDF::ExponentialInterpolationFunction>(func, OCLASS_FUNC_REF);
|
||
|
||
axial->AddFunc(func);
|
||
|
||
stitch->AddFunc(func);
|
||
stitch->AddEncode(PDF::float2(0.0f, 1.0f));
|
||
|
||
if (i >= 1)
|
||
{
|
||
stitch->AddBounds(offsets[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (stitch->IsValid())
|
||
{
|
||
GenXRef<PDF::StitchFunction>(stitch, OCLASS_FUNC_REF);
|
||
axial->AddFunc(stitch);
|
||
|
||
if (alphaPatternEnable)
|
||
{
|
||
alphaShading = new PDF::ShadingPattern();
|
||
if (alphaShading)
|
||
{
|
||
PDF::AxialShading* alphaAxial = new PDF::AxialShading();
|
||
if (alphaAxial)
|
||
{
|
||
alphaAxial->SetColorSpace(L"DeviceGray");
|
||
alphaAxial->SetGradientVector(PDF::float4(x1, y1, x2, y2), !userSpaceOnUse);
|
||
alphaAxial->SetTransform(matrix);
|
||
|
||
PDF::StitchFunction* alphaStitch = new PDF::StitchFunction();
|
||
if (alphaStitch)
|
||
{
|
||
alphaStitch->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
|
||
int count = opacity.GetCount();
|
||
for (size_t i = 0; i < count - 1; ++i)
|
||
{
|
||
PDF::ExponentialInterpolationFunction* alphaFunc = new PDF::ExponentialInterpolationFunction();
|
||
if (alphaFunc)
|
||
{
|
||
alphaFunc->AddC(1, opacity[i]);
|
||
alphaFunc->AddC(1, opacity[(i + 1)]);
|
||
|
||
alphaFunc->AddOffset(PDF::float2(offsets[i], offsets[i + 1]));
|
||
alphaFunc->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
alphaFunc->AddN(1);
|
||
|
||
GenXRef<PDF::ExponentialInterpolationFunction>(alphaFunc, OCLASS_FUNC_REF);
|
||
|
||
alphaAxial->AddFunc(alphaFunc);
|
||
|
||
alphaStitch->AddFunc(alphaFunc);
|
||
alphaStitch->AddEncode(PDF::float2(0.0f, 1.0f));
|
||
|
||
if (i >= 1)
|
||
{
|
||
alphaStitch->AddBounds(offsets[i]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
GenXRef<PDF::StitchFunction>(alphaStitch, OCLASS_FUNC_REF);
|
||
alphaAxial->AddFunc(alphaStitch);
|
||
|
||
GenXRef<PDF::ShadingPattern>(alphaShading, OCLASS_PATTERN_REF);
|
||
alphaShading->AddShading(alphaAxial);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
RELEASEOBJECT(stitch);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
shading->AddShading(axial);
|
||
|
||
if (fill)
|
||
m_oPatternState.SetFill(shading);
|
||
else
|
||
m_oPatternState.SetStroke(shading);
|
||
|
||
m_oPatterns.Add(shading);
|
||
|
||
if (alphaShading)
|
||
{
|
||
shading->SetAlphaPattern(alphaShading);
|
||
|
||
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ( <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20>.<2E> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> )
|
||
|
||
PDF::PatternAlphaGroup* mask = new PDF::PatternAlphaGroup();
|
||
if (mask)
|
||
{
|
||
mask->SetFillId(alphaShading->GetId());
|
||
mask->SetBound(PDF::Rect(0, 0, width, height));
|
||
mask->SetFormId(FormId);
|
||
|
||
GenXRef<PDF::PatternAlphaGroup>(mask, OCLASS_MASK_FORM);
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
if (mask->GetMask())
|
||
{
|
||
GenXRef<PDF::SoftMask>(mask->GetMask(), OCLASS_MASK_REF);
|
||
mask->GetMask()->SetGroupId(mask->GetId());
|
||
}
|
||
|
||
m_oPatterns.AddMask(mask);
|
||
}
|
||
|
||
m_oPatterns.Add(alphaShading);
|
||
}
|
||
|
||
RebuildResources();
|
||
|
||
return TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
BOOL CPDFWriter::CreateRadialGradientFromSvgXml(const CString& sXml, BOOL fill)
|
||
{
|
||
int FormId = -1;
|
||
|
||
XrefEntry entry = XrefGetEntry(m_pDocument->pXref, m_pDocument->pXref->pEntries->nCount - 2);
|
||
if (entry)
|
||
{
|
||
XObject obj = (XObject)entry->pObj;
|
||
if (obj)
|
||
{
|
||
FormId = (obj->pHeader.nObjId & (~OTYPE_INDIRECT));
|
||
}
|
||
}
|
||
|
||
XmlUtils::CXmlNode oXml;
|
||
if (oXml.FromXmlString(sXml))
|
||
{
|
||
PDF::ShadingPattern* alphaShading = NULL;
|
||
|
||
PDF::ShadingPattern* shading = new PDF::ShadingPattern();
|
||
if (shading)
|
||
{
|
||
PDF::RadialShading* radial = new PDF::RadialShading();
|
||
if (radial)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||
|
||
BOOL userSpaceOnUse = (L"userSpaceOnUse" == oXml.GetAttribute(L"gradientUnits"));
|
||
BOOL isSvgElement = (L"svg" == oXml.GetAttribute(L"sourceType"));
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
double cx = _wtof(oXml.GetAttributeOrValue(L"cx", L"0"));
|
||
double cy = _wtof(oXml.GetAttributeOrValue(L"cy", L"0"));
|
||
double r = _wtof(oXml.GetAttributeOrValue(L"r", L"0"));
|
||
double r0 = _wtof(oXml.GetAttributeOrValue(L"r1", L"0"));
|
||
double r1 = _wtof(oXml.GetAttributeOrValue(L"r0", L"0"));
|
||
double fx = _wtof(oXml.GetAttributeOrValue(L"fx", L"0"));
|
||
double fy = _wtof(oXml.GetAttributeOrValue(L"fy", L"0"));
|
||
|
||
if (oXml.GetAttribute(L"rx").GetLength())
|
||
fx = _wtof(oXml.GetAttributeOrValue(L"rx", L"0"));
|
||
if (oXml.GetAttribute(L"ry").GetLength())
|
||
fy = _wtof(oXml.GetAttributeOrValue(L"ry", L"0"));
|
||
|
||
if (FALSE == isSvgElement)
|
||
{
|
||
if (userSpaceOnUse)
|
||
{
|
||
cx = MMToPDFCoords(cx);
|
||
cy = MMToPDFCoords(cy);
|
||
r = MMToPDFCoords(r);
|
||
r0 = MMToPDFCoords(r0);
|
||
r1 = MMToPDFCoords(r1);
|
||
fx = MMToPDFCoords(fx);
|
||
fy = MMToPDFCoords(fy);
|
||
}
|
||
|
||
if (oXml.GetAttribute(L"r0").GetLength() && oXml.GetAttribute(L"r1").GetLength())
|
||
{
|
||
if (fabs(r0 - r1) < 0.0001)
|
||
r1 = r0 + 0.0001;
|
||
|
||
radial->SetGradientCircles(PDF::float2(cx, cy), PDF::float2(fx, fy), PDF::float2(r1 , r0),!userSpaceOnUse);
|
||
}
|
||
else
|
||
{
|
||
radial->SetGradientCircles(PDF::float2(cx, cy), PDF::float2(fx, fy), PDF::float2(r * 0.5, r * 0.5 * 2),!userSpaceOnUse);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
radial->SetGradientCircles(PDF::float2(cx, cy), PDF::float2(fx, fy), PDF::float2(0, r),!userSpaceOnUse);
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
PDF::Matrix matrix = BuildFromSvgMatrix(oXml.GetAttributeOrValue(L"gradientTransform"));
|
||
radial->SetTransform(matrix);
|
||
|
||
float width = 0.0f; GetWidth(&width);
|
||
float height = 0.0f; GetHeight(&height);
|
||
|
||
GenXRef<PDF::ShadingPattern>(shading, OCLASS_PATTERN_REF);
|
||
|
||
XmlUtils::CXmlNodes oNodes;
|
||
if (oXml.GetNodes(L"stop", oNodes))
|
||
{
|
||
CAtlArray<PDF::ExponentialInterpolationFunction*> functions;
|
||
|
||
CAtlArray<PDF::float3> colors;
|
||
CAtlArray<float> offsets;
|
||
CAtlArray<float> opacity;
|
||
|
||
BOOL alphaPatternEnable = FALSE;
|
||
|
||
for (int i = 0; i < oNodes.GetCount(); ++i)
|
||
{
|
||
XmlUtils::CXmlNode oNode;
|
||
if (oNodes.GetAt(i, oNode))
|
||
{
|
||
long color = _wtol(oNode.GetAttributeOrValueBase(L"stop-color", L"0"));
|
||
double offset = min(max(_wtof(oNode.GetAttributeOrValueBase(L"offset", L"0")), 0.0f), 1.0);
|
||
float alpha = (float)(min(max(_wtof(oNode.GetAttributeOrValueBase(L"stop-opacity", L"1")), 0.0f), 1.0));
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
if (offset < DBL_EPSILON && colors.GetCount())
|
||
{
|
||
colors.RemoveAll();
|
||
offsets.RemoveAll();
|
||
opacity.RemoveAll();
|
||
}
|
||
|
||
colors.Add(PDF::float3((0xFF & color) / 255.0f, (0xFF & (color >> 8)) / 255.0f, (0xFF & (color >> 16)) / 255.0f));
|
||
offsets.Add(min(max(_wtof(oNode.GetAttributeOrValueBase(L"offset", L"0")), 0.0f), 1.0));
|
||
opacity.Add(alpha);
|
||
|
||
if (fabs(alpha - 1.0) > DBL_EPSILON)
|
||
{
|
||
alphaPatternEnable = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (colors.GetCount())
|
||
{
|
||
if (offsets[0] > DBL_EPSILON)
|
||
{
|
||
PDF::float3 color = colors[0];
|
||
float alpha = opacity[0];
|
||
|
||
colors.InsertAt(0, color);
|
||
offsets.InsertAt(0, 0.0f);
|
||
opacity.InsertAt(0, alpha);
|
||
}
|
||
|
||
long count = offsets.GetCount() - 1;
|
||
|
||
if (fabs(offsets[count] - 1.0) > DBL_EPSILON)
|
||
{
|
||
PDF::float3 color = colors[count];
|
||
float alpha = opacity[count];
|
||
|
||
colors.Add(color);
|
||
offsets.Add(1.0f);
|
||
opacity.Add(alpha);
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
if (2 == colors.GetCount() && 2 == offsets.GetCount())
|
||
{
|
||
PDF::ExponentialInterpolationFunction* func = new PDF::ExponentialInterpolationFunction();
|
||
if (func)
|
||
{
|
||
func->AddC(3, colors[0].f1, colors[0].f2, colors[0].f3);
|
||
func->AddC(3, colors[1].f1, colors[1].f2, colors[1].f3);
|
||
|
||
func->AddOffset(PDF::float2(offsets[0], offsets[1]));
|
||
func->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
func->AddN(1);
|
||
|
||
GenXRef<PDF::ExponentialInterpolationFunction>(func, OCLASS_FUNC_REF);
|
||
|
||
radial->AddFunc(func);
|
||
}
|
||
|
||
if (alphaPatternEnable)
|
||
{
|
||
alphaShading = new PDF::ShadingPattern();
|
||
if (alphaShading)
|
||
{
|
||
PDF::RadialShading* alphaRadial = new PDF::RadialShading();
|
||
if (alphaRadial)
|
||
{
|
||
alphaRadial->SetColorSpace(L"DeviceGray");
|
||
alphaRadial->SetGradientCircles(radial->GetC0(), radial->GetC1(), radial->GetR(), !userSpaceOnUse);
|
||
alphaRadial->SetTransform(matrix);
|
||
|
||
PDF::ExponentialInterpolationFunction* alphaFunc = new PDF::ExponentialInterpolationFunction();
|
||
if (alphaFunc)
|
||
{
|
||
alphaFunc->AddC(1, offsets[0]);
|
||
alphaFunc->AddC(1, offsets[1]);
|
||
|
||
alphaFunc->AddOffset(PDF::float2(offsets[0], offsets[1]));
|
||
alphaFunc->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
alphaFunc->AddN(1);
|
||
|
||
GenXRef<PDF::ShadingPattern>(alphaShading, OCLASS_PATTERN_REF);
|
||
GenXRef<PDF::ExponentialInterpolationFunction>(alphaFunc, OCLASS_FUNC_REF);
|
||
|
||
alphaRadial->AddFunc(alphaFunc);
|
||
alphaShading->AddShading(alphaRadial);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
PDF::StitchFunction* stitch = new PDF::StitchFunction();
|
||
if (stitch)
|
||
{
|
||
stitch->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
|
||
for (size_t i = 0; i < colors.GetCount() - 1; ++i)
|
||
{
|
||
PDF::ExponentialInterpolationFunction* func = new PDF::ExponentialInterpolationFunction();
|
||
if (func)
|
||
{
|
||
func->AddC(3, colors[i].f1, colors[i].f2, colors[i].f3);
|
||
func->AddC(3, colors[i + 1].f1, colors[i + 1].f2, colors[i + 1].f3);
|
||
|
||
func->AddOffset(PDF::float2(offsets[i], offsets[i + 1]));
|
||
func->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
func->AddN(1);
|
||
|
||
GenXRef<PDF::ExponentialInterpolationFunction>(func, OCLASS_FUNC_REF);
|
||
|
||
radial->AddFunc(func);
|
||
|
||
stitch->AddFunc(func);
|
||
stitch->AddEncode(PDF::float2(0.0f, 1.0f));
|
||
|
||
if (i >= 1)
|
||
{
|
||
stitch->AddBounds(offsets[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (stitch->IsValid())
|
||
{
|
||
GenXRef<PDF::StitchFunction>(stitch, OCLASS_FUNC_REF);
|
||
radial->AddFunc(stitch);
|
||
|
||
if (alphaPatternEnable)
|
||
{
|
||
alphaShading = new PDF::ShadingPattern();
|
||
if (alphaShading)
|
||
{
|
||
PDF::RadialShading* alphaRadial = new PDF::RadialShading();
|
||
if (alphaRadial)
|
||
{
|
||
alphaRadial->SetColorSpace(L"DeviceGray");
|
||
alphaRadial->SetGradientCircles(radial->GetC0(), radial->GetC1(), radial->GetR(), !userSpaceOnUse);
|
||
alphaRadial->SetTransform(matrix);
|
||
|
||
PDF::StitchFunction* alphaStitch = new PDF::StitchFunction();
|
||
if (alphaStitch)
|
||
{
|
||
alphaStitch->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
|
||
int count = opacity.GetCount();
|
||
for (size_t i = 0; i < count - 1; ++i)
|
||
{
|
||
PDF::ExponentialInterpolationFunction* alphaFunc = new PDF::ExponentialInterpolationFunction();
|
||
if (alphaFunc)
|
||
{
|
||
alphaFunc->AddC(1, opacity[i]);
|
||
alphaFunc->AddC(1, opacity[(i + 1)]);
|
||
|
||
alphaFunc->AddOffset(PDF::float2(offsets[i], offsets[i + 1]));
|
||
alphaFunc->AddDomain(PDF::float2(0.0f, 1.0f));
|
||
alphaFunc->AddN(1);
|
||
|
||
GenXRef<PDF::ExponentialInterpolationFunction>(alphaFunc, OCLASS_FUNC_REF);
|
||
|
||
alphaRadial->AddFunc(alphaFunc);
|
||
|
||
alphaStitch->AddFunc(alphaFunc);
|
||
alphaStitch->AddEncode(PDF::float2(0.0f, 1.0f));
|
||
|
||
if (i >= 1)
|
||
{
|
||
alphaStitch->AddBounds(offsets[i]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
GenXRef<PDF::StitchFunction>(alphaStitch, OCLASS_FUNC_REF);
|
||
alphaRadial->AddFunc(alphaStitch);
|
||
|
||
GenXRef<PDF::ShadingPattern>(alphaShading, OCLASS_PATTERN_REF);
|
||
alphaShading->AddShading(alphaRadial);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
RELEASEOBJECT(stitch);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
shading->AddShading(radial);
|
||
|
||
if (fill)
|
||
m_oPatternState.SetFill(shading);
|
||
else
|
||
m_oPatternState.SetStroke(shading);
|
||
|
||
m_oPatterns.Add(shading);
|
||
|
||
if (alphaShading)
|
||
{
|
||
shading->SetAlphaPattern(alphaShading);
|
||
|
||
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ( <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20>.<2E> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> )
|
||
|
||
PDF::PatternAlphaGroup* mask = new PDF::PatternAlphaGroup();
|
||
if (mask)
|
||
{
|
||
mask->SetFillId(alphaShading->GetId());
|
||
mask->SetBound(PDF::Rect(0, 0, width, height));
|
||
mask->SetFormId(FormId);
|
||
|
||
GenXRef<PDF::PatternAlphaGroup>(mask, OCLASS_MASK_FORM);
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
if (mask->GetMask())
|
||
{
|
||
GenXRef<PDF::SoftMask>(mask->GetMask(), OCLASS_MASK_REF);
|
||
mask->GetMask()->SetGroupId(mask->GetId());
|
||
}
|
||
|
||
m_oPatterns.AddMask(mask);
|
||
}
|
||
|
||
m_oPatterns.Add(alphaShading);
|
||
}
|
||
|
||
RebuildResources();
|
||
|
||
return TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOL CPDFWriter::RebuildResources()
|
||
{
|
||
Dict element = (Dict)(GetElement(m_pDocument->pCurPage, "Resources")->pValue);
|
||
if (element)
|
||
{
|
||
Dict patternDict = DictNew(m_pDocument->oMMgr);
|
||
if (patternDict)
|
||
{
|
||
|
||
DictAdd(element, "Pattern", patternDict);
|
||
|
||
RELEASEOBJECT(patternDict->sBuffer);
|
||
patternDict->sBuffer = new CString(m_oPatterns.Defines());
|
||
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
template <typename T> Proxy CPDFWriter::GenXRef(T* object, int Type)
|
||
{
|
||
Proxy ref = ProxyNew(m_pDocument->oMMgr, object);
|
||
if (ref)
|
||
{
|
||
ref->pHeader.nObjClass = Type;
|
||
XrefAdd(m_pDocument->pXref, ref);
|
||
object->SetId(ref->pHeader.nObjId & (~OTYPE_INDIRECT));
|
||
}
|
||
|
||
return ref;
|
||
}
|
||
|
||
PDF::Rect CPDFWriter::PathBounds()
|
||
{
|
||
PDF::Rect rect;
|
||
|
||
if (m_pCurPath)
|
||
{
|
||
m_pCurPath->GetBounds(&rect.X, &rect.Y, &rect.Width, &rect.Height);
|
||
|
||
rect.X = MMToPDFCoords(rect.X);
|
||
rect.Y = MMToPDFCoords(rect.Y);
|
||
rect.Width = MMToPDFCoords(rect.Width);
|
||
rect.Height = MMToPDFCoords(rect.Height);
|
||
}
|
||
|
||
if (m_bUseTextureRect)
|
||
{
|
||
rect.X = MMToPDFCoords(m_oBrush.Rect.X);
|
||
rect.Y = MMToPDFCoords(m_oBrush.Rect.Y);
|
||
rect.Width = MMToPDFCoords(m_oBrush.Rect.Width) + rect.X * 2;
|
||
rect.Height = MMToPDFCoords(m_oBrush.Rect.Height)+ rect.Y * 2;
|
||
|
||
rect.X = 0;
|
||
rect.Y = 0;
|
||
}
|
||
|
||
return rect;
|
||
}
|
||
PDF::Rect CPDFWriter::PageBounds()
|
||
{
|
||
PDF::Rect rect;
|
||
|
||
GetHeight(&rect.Height);
|
||
GetWidth(&rect.Width);
|
||
|
||
return rect;
|
||
} |