Files
core/ASCOfficePDFWriter/PdfWriterLib/PageOperations.cpp
Elen.Subbotina 2276da418e правки под Linux после исправлений под iOs . BOOL -> bool (TRUE->true, FALSE->false)
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62078 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-20 23:57:10 +03:00

2562 lines
92 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 "PageOperations.h"
static const float c_fKappa = 0.552F;
static char* QuarterCircleA (char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fRad)
{
pBufPointer = UtilsFToA( pBufPointer, fX - fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX - fRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fRad, pEndBufPointer);
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
static char* QuarterCircleB (char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fRad)
{
pBufPointer = UtilsFToA( pBufPointer, fX + fRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX + fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX + fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
static char* QuarterCircleC (char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fRad)
{
pBufPointer = UtilsFToA( pBufPointer, fX + fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX + fRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fRad, pEndBufPointer);
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
static char* QuarterCircleD (char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fRad)
{
pBufPointer = UtilsFToA( pBufPointer, fX - fRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX - fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX - fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
static char* QuarterEllipseA(char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fXRad, float fYRad)
{
pBufPointer = UtilsFToA( pBufPointer, fX - fXRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fYRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX - fXRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fYRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fYRad, pEndBufPointer);
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
static char* QuarterEllipseB(char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fXRad, float fYRad)
{
pBufPointer = UtilsFToA( pBufPointer, fX + fXRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fYRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX + fXRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY + fYRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX + fXRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
static char* QuarterEllipseC(char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fXRad, float fYRad)
{
pBufPointer = UtilsFToA( pBufPointer, fX + fXRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fYRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX + fXRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fYRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fYRad, pEndBufPointer);
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
static char* QuarterEllipseD(char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fXRad, float fYRad)
{
pBufPointer = UtilsFToA( pBufPointer, fX - fXRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fYRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX - fXRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY - fYRad * c_fKappa, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX - fXRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
static unsigned long InternalShowTextNextLine(Page pPage, const BYTE *sText, unsigned int nLen, unsigned int *pCIDs, unsigned int nLenCID)
{
unsigned long nRet = OK;
PageAttr pAttr = (PageAttr)pPage->pAttr;
FontAttr pFontAttr = (FontAttr)pAttr->pGState->pFont->pAttr;
if ( FontType0TT == pFontAttr->eType || FontType0CID == pFontAttr->eType )
{
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "<" ) ) )
return nRet;
if ( OK != ( nRet = StreamWriteBinary( pAttr->pStream, (BYTE*)sText, nLen, NULL ) ) )
return nRet;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, ">" ) ) )
return nRet;
}
else if ( OK != ( nRet = StreamWriteEscapeText2( pAttr->pStream, sText, nLen ) ) )
return nRet;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " \'\012" ) ) )
return nRet;
float fTextWidth = PageTextWidth( pPage, sText, nLen, pCIDs, nLenCID );
pAttr->oTextMatrix.fX -= pAttr->pGState->fTextLeading * pAttr->oTextMatrix.fC;
pAttr->oTextMatrix.fY -= pAttr->pGState->fTextLeading * pAttr->oTextMatrix.fD;
pAttr->oTextPos.fX = pAttr->oTextMatrix.fX;
pAttr->oTextPos.fY = pAttr->oTextMatrix.fY;
if ( WModeHorizontal == pAttr->pGState->eWritingMode )
{
pAttr->oTextPos.fX += fTextWidth * pAttr->oTextMatrix.fA;
pAttr->oTextPos.fY += fTextWidth * pAttr->oTextMatrix.fB;
}
else
{
pAttr->oTextPos.fX -= fTextWidth * pAttr->oTextMatrix.fB;
pAttr->oTextPos.fY -= fTextWidth * pAttr->oTextMatrix.fA;
}
return nRet;
}
static unsigned long InternalWriteText(PageAttr pAttr, const BYTE *sText, unsigned int nLen)
{
FontAttr pFontAttr = (FontAttr)pAttr->pGState->pFont->pAttr;
unsigned long nRet = OK;
if ( FontType0TT == pFontAttr->eType || FontType0CID == pFontAttr->eType || FontDefCID == pFontAttr->pFontDef->eType )
{
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "<" ) ) )
return nRet;
if ( OK != ( nRet = StreamWriteBinary( pAttr->pStream, sText, nLen, NULL ) ) )
return nRet;
return StreamWriteStr( pAttr->pStream, ">" );
}
return StreamWriteEscapeText( pAttr->pStream, sText, nLen );
}
static unsigned long InternalArc (Page pPage, float fX, float fY, float fRay, float fAng1, float fAng2, bool bContFlag)
{
const float fPIE = 3.14159F;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
unsigned long nRet = 0;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
double dDeltaAngle = (90 - (double)(fAng1 + fAng2) / 2) / 180 * fPIE;
double dNewAngle = (double)(fAng2 - fAng1) / 2 / 180 * fPIE;
double dRX0 = fRay * cos(dNewAngle);
double dRY0 = fRay * sin(dNewAngle);
double dRX2 = ( fRay * 4.0 - dRX0 ) / 3.0;
double dRY2 = ( ( fRay * 1.0 - dRX0 ) * ( dRX0 - fRay * 3.0 ) ) / (3.0 * dRY0);
double dRX1 = dRX2;
double dRY1 = -dRY2;
double dRX3 = dRX0;
double dRY3 = -dRY0;
double dX0 = dRX0 * cos (dDeltaAngle) - dRY0 * sin (dDeltaAngle) + fX;
double dY0 = dRX0 * sin (dDeltaAngle) + dRY0 * cos (dDeltaAngle) + fY;
double dX1 = dRX1 * cos (dDeltaAngle) - dRY1 * sin (dDeltaAngle) + fX;
double dY1 = dRX1 * sin (dDeltaAngle) + dRY1 * cos (dDeltaAngle) + fY;
double dX2 = dRX2 * cos (dDeltaAngle) - dRY2 * sin (dDeltaAngle) + fX;
double dY2 = dRX2 * sin (dDeltaAngle) + dRY2 * cos (dDeltaAngle) + fY;
double dX3 = dRX3 * cos (dDeltaAngle) - dRY3 * sin (dDeltaAngle) + fX;
double dY3 = dRX3 * sin (dDeltaAngle) + dRY3 * cos (dDeltaAngle) + fY;
if ( !bContFlag )
{
pBufPointer = UtilsFToA( pBufPointer, (float)dX0, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, (float)dY0, pEndBufPointer);
pBufPointer = (char*)UtilsStrCpy( pBufPointer, " m\012", pEndBufPointer);
}
pBufPointer = UtilsFToA( pBufPointer, (float)dX1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, (float)dY1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, (float)dX2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, (float)dY2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, (float)dX3, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, (float)dY3, pEndBufPointer);
UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = (float)dX3;
pAttr->oCurPos.fY = (float)dY3;
pAttr->oStrPos = pAttr->oCurPos;
pAttr->nGMode = GMODE_PATH_OBJECT;
return nRet;
}
static char* EllipseArc (char *pBufPointer, char *pEndBufPointer, float fX, float fY, float fXRad, float fYRad, double dAngle1, double dAngle2, float *pfXCur, float *pfYCur, bool bClockDirection = false)
{
// Рассчитаем начальную, конечную и контрольные точки
float fX1 = 0.0f, fX2 = 0.0f, fY1 = 0.0f, fY2 = 0.0f;
float fCX1 = 0.0f, fCX2 = 0.0f, fCY1 = 0.0f, fCY2 = 0.0f;
float fAlpha = sin( dAngle2 - dAngle1 ) * ( sqrt( 4.0 + 3.0 * tan( (dAngle2 - dAngle1) / 2.0 ) * tan( (dAngle2 - dAngle1) / 2.0 ) ) - 1.0 ) / 3.0;
float fKoef = 1;
fX1 = fX + fXRad * cos( dAngle1 );
fY1 = fY + fYRad * sin( dAngle1 );
fX2 = fX + fXRad * cos( dAngle2 );
fY2 = fY + fYRad * sin( dAngle2 );
fCX1 = fX1 - fAlpha * fXRad * sin ( dAngle1 );
fCY1 = fY1 + fAlpha * fYRad * cos ( dAngle1 );
fCX2 = fX2 + fAlpha * fXRad * sin ( dAngle2 );
fCY2 = fY2 - fAlpha * fYRad * cos ( dAngle2 );
if ( !bClockDirection )
{
pBufPointer = UtilsFToA( pBufPointer, fCX1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fCY1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fCX2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fCY2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY2, pEndBufPointer);
*pfXCur = fX2;
*pfYCur = fY2;
}
else
{
pBufPointer = UtilsFToA( pBufPointer, fCX2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fCY2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fCX1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fCY1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY1, pEndBufPointer);
*pfXCur = fX1;
*pfYCur = fY1;
}
return (char*)UtilsStrCpy( pBufPointer, " c\012", pEndBufPointer);
}
float AngToEllPrm(float fAngle, float fXRad, float fYRad)
{
// Функция для перевода реального угла в параметрическое задание эллписа
// т.е. x= a cos(t) y = b sin(t) - параметрическое задание эллписа.
// x = r cos(p), y = r sin(p) => t = atan2( sin(p) / b, cos(p) / a );
return atan2( sin( fAngle ) / fYRad, cos( fAngle ) / fXRad );
}
///////////////////////////////////////////////////////////////////////////////////
//--- General graphics state --------------------------------------------------------------------------
// Operator : w
// Descriprion: устанавливаем толщину линии
unsigned long PageSetLineWidth (Page pPage, float fLineWidth)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( fLineWidth < 0 )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fLineWidth ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " w\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fLineWidth = fLineWidth;
return nRet;
}
// Operator : J
// Descriprion: устанавливаем вид окончания линии (LineCapStyle)
unsigned long PageSetLineCap (Page pPage, LineCapStyle eLineCap)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
if ( eLineCap < 0 || eLineCap >= LineCapEOF)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, (unsigned long)eLineCap);
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteInt( pAttr->pStream, (unsigned int)eLineCap ) ) )
return nRet;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " J\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->eLineCap = eLineCap;
return nRet;
}
// Operator : j
// Descriprion: устанавливаем вид соединения линий (LineJoinStyle)
unsigned long PageSetLineJoin (Page pPage, LineJoinStyle eLineJoin)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
if ( eLineJoin < 0 || eLineJoin >= LineJoinEOF )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, (unsigned long)eLineJoin );
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteInt( pAttr->pStream, (unsigned int)eLineJoin ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " j\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->eLineJoin = eLineJoin;
return nRet;
}
// Operator : M
// Descriprion: устанавливаем MiterLimit - константа, относящаяся к виду соединения линий
unsigned long PageSetMiterLimit (Page pPage, float fMiterLimit)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( fMiterLimit < 1 )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0 );
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fMiterLimit ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " M\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fMiterLimit = fMiterLimit;
return nRet;
}
// Operator : d
// Descriprion: устанавливаем вид линий (DashMode)
unsigned long PageSetDash (Page pPage, const double *pdDashPtn, unsigned int nNumParam, float fPhase)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
const double *pdTempDashPtn = pdDashPtn;
//if ( 1 != nNumParam && (nNumParam / 2) * 2 != nNumParam )
// return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_PARAM_COUNT, nNumParam);
if ( 0 == nNumParam && fPhase > 0)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, fPhase);
if ( !pdDashPtn && nNumParam > 0)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PARAMETER, nNumParam);
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
*pBufPointer++ = '[';
bool bFalseDash = true;
for ( unsigned int nIndex = 0; nIndex < nNumParam; nIndex++)
{
if ( 0 != pdTempDashPtn[nIndex] )
{
bFalseDash = false;
break;
}
}
if ( !bFalseDash )
{
for ( unsigned int nIndex = 0; nIndex < nNumParam; nIndex++)
{
if ( /*0 == *pnTempDashPtn ||*/ *pdTempDashPtn > MAX_DASH_PATTERN )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
pBufPointer = UtilsFToA( pBufPointer, *pdTempDashPtn, pEndBufPointer);
*pBufPointer++ = ' ';
pdTempDashPtn++;
}
}
else
{
int k = 10;
}
*pBufPointer++ = ']';
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fPhase, pEndBufPointer);
UtilsStrCpy( pBufPointer, " d\012", pEndBufPointer);
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->pGState->oDashMode = c_oInitDashMode;
pAttr->pGState->oDashMode.nNumPoints = nNumParam;
pAttr->pGState->oDashMode.fPhase = fPhase;
pdTempDashPtn = pdDashPtn;
for ( unsigned int nIndex = 0; nIndex < nNumParam; nIndex++)
{
pAttr->pGState->oDashMode.afPtn[nIndex] = (float)*pdTempDashPtn;
pdTempDashPtn++;
}
return nRet;
}
// TO DO: ri
// Operator : i
// Descriprion: устанавливаем порог ошибки линии (Flatness tolerance)
unsigned long PageSetFlat (Page pPage, float fFlatness)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( fFlatness > 100 || fFlatness < 0 )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fFlatness ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " i\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fFlatness = fFlatness;
return nRet;
}
// Operator : gs
// Description: устанавливаем сразу все настройки данного графического состояния(ExtGState)
unsigned long PageSetExtGState (Page pPage, ExtGState pExtGState)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
if ( !ExtGStateValidate( pExtGState ) )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_OBJECT, 0);
// проверяем принадлежность объекта pExtGState
if ( pPage->oMMgr != pExtGState->oMMgr )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_EXT_GSTATE, 0);
PageAttr pAttr = (PageAttr)pPage->pAttr;
const char *sLocalName = PageGetExtGStateName( pPage, pExtGState);
if ( !sLocalName )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteEscapeName( pAttr->pStream, sLocalName ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " gs\012" ) ) )
return CheckError( pPage->oError );
// меняем класс объекта на readonly
pExtGState->pHeader.nObjClass = (OSUBCLASS_EXT_GSTATE_R | OCLASS_DICT);
return nRet;
}
//--- Special graphic state operator ------------------------------------------------------------------
// Operator : q
// Description: сохраняем текущий GState в графическом стеке
unsigned long PageGSave (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
GState pNewGState = GStateNew( pPage->oMMgr, pAttr->pGState );
if ( !pNewGState )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "q\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState = pNewGState;
return nRet;
}
// Operator : Q
// Description: Восстанавливаем GState, удаляя самый последний GState, и делаем данный GState текущим
unsigned long PageGRestore (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
// предыдущего состояния нет :)
if ( !pAttr->pGState->pPrev )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_CANNOT_RESTORE_GSTATE, 0);
GState pNewGState = GStateFree( pPage->oMMgr, pAttr->pGState );
pAttr->pGState = pNewGState;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "Q\012" ) ) )
return CheckError( pPage->oError );
return nRet;
}
// Operator : cm
// Description: меняем матрицу преобразований (CTM - Current Transformation Matrix)
unsigned long PageConcat (Page pPage, float fA, float fB, float fC, float fD, float fX, float fY)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fA, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fB, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fC, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fD, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
UtilsStrCpy( pBufPointer, " cm\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
TransMatrix oCTM = pAttr->pGState->oTransMatrix;
// перемножаем матрицы oCTM(новая)= oCTM(преобразования(которая параметрами задана)) x oCTM(старая)
// должно быть:
//pAttr->pGState->oTransMatrix.fA = oCTM.fA * fA + oCTM.fC * fB;
//pAttr->pGState->oTransMatrix.fB = oCTM.fB * fA + oCTM.fD * fB;
//pAttr->pGState->oTransMatrix.fC = oCTM.fA * fC + oCTM.fC * fD;
//pAttr->pGState->oTransMatrix.fD = oCTM.fB * fC + oCTM.fD * fD;
//pAttr->pGState->oTransMatrix.fX = oCTM.fX + fX * oCTM.fA + fY * oCTM.fC;
//pAttr->pGState->oTransMatrix.fY = oCTM.fY + fX * oCTM.fB + fY * oCTM.fD;
pAttr->pGState->oTransMatrix.fA = oCTM.fA * fA + oCTM.fB * fC;
pAttr->pGState->oTransMatrix.fB = oCTM.fA * fB + oCTM.fB * fD;
pAttr->pGState->oTransMatrix.fC = oCTM.fC * fA + oCTM.fD * fC;
pAttr->pGState->oTransMatrix.fD = oCTM.fC * fB + oCTM.fD * fD;
pAttr->pGState->oTransMatrix.fX = oCTM.fX + fX * oCTM.fA + fY * oCTM.fC;
pAttr->pGState->oTransMatrix.fY = oCTM.fY + fX * oCTM.fB + fY * oCTM.fD;
return nRet;
}
//--- Path construction operator ----------------------------------------------------------------------
// Operator : m
// Description: Начинаем новый subpath, передвигая текущий указатель в точку (x, y)(она же стартовая).
unsigned long PageMoveTo (Page pPage, float fX, float fY)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT | GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH );
if ( OK != nRet )
{
nRet = OK;
nRet = PageCheckState( pPage, GMODE_PATH_OBJECT );
if ( OK != nRet )
return nRet;
else
ErrorReset( pPage->oError );
}
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
UtilsStrCpy( pBufPointer, " m\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fX;
pAttr->oCurPos.fY = fY;
pAttr->oStrPos = pAttr->oCurPos;
pAttr->nGMode = GMODE_PATH_OBJECT;
return nRet;
}
// Operator : l
// Description: Добавляем линию от текущей точки до точки (x, y). Текущую точку выставляем (х, у).
unsigned long PageLineTo (Page pPage, float fX, float fY)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
UtilsStrCpy( pBufPointer, " l\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fX;
pAttr->oCurPos.fY = fY;
return nRet;
}
// Operator : c
// Description: Добавляем кривую Безье(кубическую). Начинается кривая в текущей позиции, заканчивается
// в точке (x3, y3). (x1, y1) и (x2, y2) - контрольные точки. Текущую точку устанавливаем
// в (х3, у3).
unsigned long PageCurveTo (Page pPage, float fX1, float fY1, float fX2, float fY2, float fX3, float fY3)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX3, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY3, pEndBufPointer);
UtilsStrCpy (pBufPointer, " c\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fX3;
pAttr->oCurPos.fY = fY3;
return nRet;
}
// Operator : v
// Description: Добавляем кривую Безье(кубическую). Начинается кривая в текущей позиции, заканчивается
// в точке (x3, y3). (x2, y2) - контрольная точка. Текущую точку устанавливаем в (х3, у3).
unsigned long PageCurveTo2 (Page pPage, float fX2, float fY2, float fX3, float fY3)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY2, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX3, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY3, pEndBufPointer);
UtilsStrCpy( pBufPointer, " v\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fX3;
pAttr->oCurPos.fY = fY3;
return nRet;
}
// Operator : y
// Description: Добавляем кривую Безье(кубическую). Начинается кривая в текущей позиции, заканчивается
// в точке (x3, y3). (x1, y1) - контрольная точка. Текущую точку устанавливаем в (х3, у3).
unsigned long PageCurveTo3 (Page pPage, float fX1, float fY1, float fX3, float fY3)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY1, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX3, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY3, pEndBufPointer);
UtilsStrCpy( pBufPointer, " y\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fX3;
pAttr->oCurPos.fY = fY3;
return nRet;
}
// Operator : h
// Description: Закрываем subpath, соединяя текущую точку с начальной прямой линией. Если subpath
// уже закрыт, тогда ничего не делаем
unsigned long PageClosePath (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "h\012" ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos = pAttr->oStrPos;
return nRet;
}
// Operator : re
// Description: Добавляем прямоугольник к текущему path, как уже законченый subpath.
unsigned long PageRectangle (Page pPage, float fX, float fY, float fWidth, float fHeight)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fWidth, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fHeight, pEndBufPointer);
UtilsStrCpy( pBufPointer, " re\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fX;
pAttr->oCurPos.fY = fY;
pAttr->oStrPos = pAttr->oCurPos;
pAttr->nGMode = GMODE_PATH_OBJECT;
return nRet;
}
//--- Path painting operator --------------------------------------------------------------------------
// Operator : S
// Description: Обводим path.
unsigned long PageStroke (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "S\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
// Operator : s
// Description: Закрываем и обводим path. (Результат должен быть аналогичен последовательному применению
// двух операторов "h S")
unsigned long PageClosePathStroke (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "s\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
// Operator : f
// Description: Заливка path по правилу Nonzero Winding Number Rule(см. спецификацию PDF Part1: PDF 1.7
// стр. 136, закладка 8.5.3.3.2).
unsigned long PageFill (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "f\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
// Operator : f*
// Description: Заливка path по правилу Even-Odd Rule(см. спецификацию PDF Part1: PDF 1.7 стр. 137,
// закладка 8.5.3.3.3).
unsigned long PageEoFill (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "f*\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
// Operator : B
// Description: Заливка и обоводка path, используя правило для заливки Nonzero Winding Number Rule(см.
// спецификацию PDF Part1: PDF 1.7 стр. 136, закладка 8.5.3.3.2). Этот оператор должен
// привести к тому же самому результату как строительство двух идентичных объектов path,
// применяя к первому оператор f и ко второму - S.
unsigned long PageFillStroke (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "B\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
// Operator : B*
// Description: Заливка и обоводка path, используя правило для заливки Even-Odd Rule(см.
// спецификацию PDF Part1: PDF 1.7 стр. 137, закладка 8.5.3.3.3). Этот оператор должен
// привести к тому же самому результату как строительство двух идентичных объектов path,
// применяя к первому оператор f* и ко второму - S.
unsigned long PageEoFillStroke (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "B*\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
// Operator : b
// Description: Закрывем, заливаем и обоводим path, используя правило для заливки Nonzero Winding
// Number Rule((см. спецификацию PDF Part1: PDF 1.7 стр. 136, закладка 8.5.3.3.2).
// Этот оператор должен привести к тому же самому результату как последовательное применение
// операторов h и B.
unsigned long PageClosePathFillStroke (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "b\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
// Operator : b
// Description: Закрывем, заливаем и обоводим path, используя правило для заливки Even-Odd Rule(см.
// спецификацию PDF Part1: PDF 1.7 стр. 137, закладка 8.5.3.3.3). Этот оператор должен
// привести к тому же самому результату как последовательное применение операторов h и B*.
unsigned long PageClosePathEoFillStroke(Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "b*\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
// Operator : n
// Description: Закрываем path, не заливая и не обводя его. Этот оператор используется прежде всего для
// изменения текущего path.
unsigned long PageEndPath (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT | GMODE_CLIPPING_PATH);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "n\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
pAttr->oCurPos = c_oInitPosition;
return nRet;
}
//--- Clipping paths operator -------------------------------------------------------------------------
// Operator : W
// Description: Изменяем текущий clipping path, пересакая его с текущим path, ипользуя правило Nonzero
// Winding Number Rule, для определения какие регионы лежат внутри clipping path.
unsigned long PageClip (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "W\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_CLIPPING_PATH;
return nRet;
}
// Operator : W*
// Description: Изменяем текущий clipping path, пересакая его с текущим path, ипользуя правило Even-Odd
// Rule, для определения какие регионы лежат внутри clipping path.
unsigned long PageEoclip (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "W*\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_CLIPPING_PATH;
return nRet;
}
//--- Text object operator ----------------------------------------------------------------------------
// Operator : BT
// Description: Начало текста
unsigned long PageBeginText (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
const TransMatrix c_oDefaultMatrix = {1, 0, 0, 1, 0, 0};
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "BT\012" ) ) )
return CheckError( pPage->oError );
pAttr->nGMode = GMODE_TEXT_OBJECT;
pAttr->oTextPos = c_oInitPosition;
pAttr->oTextMatrix = c_oDefaultMatrix;
return nRet;
}
// Operator : ET
// Description: Окончание текста
unsigned long PageEndText (Page pPage)
{
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "ET\012" ) ) )
return CheckError( pPage->oError );
pAttr->oTextPos = c_oInitPosition;
pAttr->nGMode = GMODE_PAGE_DESCRIPTION;
return nRet;
}
//--- Text state --------------------------------------------------------------------------------------
// Operator : Tc
// Description: Устанавливаем расстояние между буквами
unsigned long PageSetCharSpace (Page pPage, float fValue)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( fValue < MIN_CHARSPACE || fValue > MAX_CHARSPACE)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fValue ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " Tc\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fCharSpace = fValue;
return nRet;
}
// Operator : Tw
// Description: Устанавливаем расстояние между словами
unsigned long PageSetWordSpace (Page pPage, float fValue)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( fValue < MIN_WORDSPACE || fValue > MAX_WORDSPACE )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0 );
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fValue ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " Tw\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fWordSpace = fValue;
return nRet;
}
// Operator : Tz
// Description: Устанавливаем горизонтальное растяжение/сжатие
unsigned long PageSetHorizontalScalling(Page pPage, float fValue)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
// if ( fValue < MIN_HORIZONTALSCALING || fValue > MAX_HORIZONTALSCALING )
//return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0 );
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fValue ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " Tz\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fHScalling = fValue;
return nRet;
}
// Operator : TL
// Description: Устанавливаем расстояние между строками
unsigned long PageSetTextLeading (Page pPage, float fValue)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( ( nRet = StreamWriteReal( pAttr->pStream, fValue ) ) )
return CheckError( pPage->oError );
if ( ( nRet = StreamWriteStr( pAttr->pStream, " TL\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fTextLeading = fValue;
return nRet;
}
// Operator : Tf
// Description: Устанавливаем фонт и размер фонта
unsigned long PageSetFontAndSize (Page pPage, FontDict pFont, float fSize)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
if ( !FontValidate( pFont ) )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_FONT, 0 );
if ( fSize < 0 || fSize > MAX_FONTSIZE )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_FONT_SIZE, 0);
// проверяем принадлежность фонта документу
if ( pPage->oMMgr != pFont->oMMgr )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_FONT, 0);
PageAttr pAttr = (PageAttr)pPage->pAttr;
const char *sLocalName = PageGetLocalFontName( pPage, pFont);
if ( !sLocalName )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_FONT, 0 );
if ( OK != ( nRet = StreamWriteEscapeName( pAttr->pStream, sLocalName ) ) )
return CheckError( pPage->oError );
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
UtilsMemSet (sBuffer, 0, TEMP_BUFFER_SIZE);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fSize, pEndBufPointer);
UtilsStrCpy( pBufPointer, " Tf\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->pGState->pFont = pFont;
pAttr->pGState->fFontSize = fSize;
pAttr->pGState->eWritingMode = ((FontAttr)pFont->pAttr)->eWritingMode;
return nRet;
}
// Operator : Tr
// Description: Устанавливаем тип закрашивания символов (TextRenderingMode)
unsigned long PageSetTextRenderingMode (Page pPage, TextRenderingMode eMode)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
if ( eMode < 0 || eMode >= RenderingModeEOF )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, (unsigned long)eMode );
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteInt( pAttr->pStream, (int)eMode ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " Tr\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->eRenderingMode = eMode;
return nRet;
}
// Operator : Ts
// Description: Устанавливаем поднятие текста в строке
unsigned long PageSetTextRise (Page pPage, float fValue)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fValue ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " Ts\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fTextRise = fValue;
return nRet;
}
//--- Text positioning --------------------------------------------------------------------------------
// Operator : Td
// Description: Переходим к началу следующей линии, сдвигаясь от начала текущей на ( fX, fY ).
unsigned long PageMoveTextPos (Page pPage, float fX, float fY)
{
unsigned long nRet = PageCheckState ( pPage, GMODE_TEXT_OBJECT );
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
UtilsStrCpy( pBufPointer, " Td\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oTextMatrix.fX += fX * pAttr->oTextMatrix.fA + fY * pAttr->oTextMatrix.fC;
pAttr->oTextMatrix.fY += fX * pAttr->oTextMatrix.fB + fY * pAttr->oTextMatrix.fD;
pAttr->oTextPos.fX = pAttr->oTextMatrix.fX;
pAttr->oTextPos.fY = pAttr->oTextMatrix.fY;
return nRet;
}
// Operator : TD
// Description: Переходим к началу следующей линии, сдвигаясь от начала текущей на ( fX, fY ). При
// этом расстояние между строк (TextLeading) высталяется -fY. Этот оператор должен
// быть эквивалентен следующей паре операторов:
// -fY TL
// fX fY Td
unsigned long PageMoveTextPos2 (Page pPage, float fX, float fY)
{
unsigned long nRet = PageCheckState ( pPage, GMODE_TEXT_OBJECT );
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
UtilsStrCpy( pBufPointer, " TD\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oTextMatrix.fX += fX * pAttr->oTextMatrix.fA + fY * pAttr->oTextMatrix.fC;
pAttr->oTextMatrix.fY += fX * pAttr->oTextMatrix.fB + fY * pAttr->oTextMatrix.fD;
pAttr->oTextPos.fX = pAttr->oTextMatrix.fX;
pAttr->oTextPos.fY = pAttr->oTextMatrix.fY;
pAttr->pGState->fTextLeading = -fY;
return nRet;
}
// Operator : Tm
// Description: Устанавливаем матрицу преобразования для текста.
unsigned long PageSetTextMatrix (Page pPage, float fA, float fB, float fC, float fD, float fX, float fY)
{
unsigned long nRet = PageCheckState ( pPage, GMODE_TEXT_OBJECT );
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
// правильнее бы здесь сделать проверку на определить матрицы
if ( ( 0 == fA || 0 == fD ) && ( 0 == fB || 0 == fC ) )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_PARAMETER, 0 );
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE );
pBufPointer = UtilsFToA( pBufPointer, fA, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fB, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fC, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fD, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
UtilsStrCpy( pBufPointer, " Tm\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oTextMatrix.fA = fA;
pAttr->oTextMatrix.fB = fB;
pAttr->oTextMatrix.fC = fC;
pAttr->oTextMatrix.fD = fD;
pAttr->oTextMatrix.fX = fX;
pAttr->oTextMatrix.fY = fY;
pAttr->oTextPos.fX = pAttr->oTextMatrix.fX;
pAttr->oTextPos.fY = pAttr->oTextMatrix.fY;
return nRet;
}
// Operator : T*
// Description: Передвигаемся на начало следующей линии. Этот оператор должен быть эквивалентен строке:
// 0 -tL Td, где tL - параметр равный текущему расстоянию между строк(TextLeading)
unsigned long PageMoveToNextLine (Page pPage)
{
unsigned long nRet = PageCheckState ( pPage, GMODE_TEXT_OBJECT );
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, "T*\012" ) ) )
return CheckError( pPage->oError );
// вычисляем точку, в которую нужно перенести текущую позицию
pAttr->oTextMatrix.fX -= pAttr->pGState->fTextLeading * pAttr->oTextMatrix.fC;
pAttr->oTextMatrix.fY -= pAttr->pGState->fTextLeading * pAttr->oTextMatrix.fD;
pAttr->oTextPos.fX = pAttr->oTextMatrix.fX;
pAttr->oTextPos.fY = pAttr->oTextMatrix.fY;
return nRet;
}
//--- Text showing ------------------------------------------------------------------------------------
// Operator : Tj
// Description: Показать текстовую строку.
unsigned long PageShowText (Page pPage, const BYTE *sText, unsigned int nLen, unsigned int *pCIDs, unsigned int nLenCID)
{
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT );
if ( OK != nRet || NULL == sText || 0 == nLen )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( !pAttr->pGState->pFont )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_FONT_NOT_FOUND, 0);
float fTextWidth = PageTextWidth( pPage, sText, nLen, pCIDs, nLenCID);
if ( !fTextWidth )
return nRet;
if ( OK != ( nRet = InternalWriteText( pAttr, sText, nLen ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " Tj\012" ) ) )
return CheckError( pPage->oError );
// Вычисляем текущую точку текста
if ( WModeHorizontal == pAttr->pGState->eWritingMode )
{
pAttr->oTextPos.fX += fTextWidth * pAttr->oTextMatrix.fA;
pAttr->oTextPos.fY += fTextWidth * pAttr->oTextMatrix.fB;
}
else
{
pAttr->oTextPos.fX -= fTextWidth * pAttr->oTextMatrix.fB;
pAttr->oTextPos.fY -= fTextWidth * pAttr->oTextMatrix.fA;
}
return nRet;
}
// Operator : '
// Description: Переходим на следующую строку и показываем текст. Этот оператор должен быть эквивалентен
// паре операторов:
// T*
// sText Tj
unsigned long PageShowTextNextLine (Page pPage, const BYTE *sText, unsigned int nLen, unsigned int *pCIDs, unsigned int nLenCID)
{
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT );
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( !pAttr->pGState->pFont )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_FONT_NOT_FOUND, 0);
if ( NULL == sText || 0 == nLen )
return PageMoveToNextLine( pPage );
if ( OK != ( nRet = InternalWriteText( pAttr, sText, nLen ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " \'\012" ) ) )
return CheckError( pPage->oError );
float fTextWidth = PageTextWidth( pPage, sText, nLen, pCIDs, nLenCID );
pAttr->oTextMatrix.fX -= pAttr->pGState->fTextLeading * pAttr->oTextMatrix.fC;
pAttr->oTextMatrix.fY -= pAttr->pGState->fTextLeading * pAttr->oTextMatrix.fD;
pAttr->oTextPos.fX = pAttr->oTextMatrix.fX;
pAttr->oTextPos.fY = pAttr->oTextMatrix.fY;
if ( WModeHorizontal == pAttr->pGState->eWritingMode )
{
pAttr->oTextPos.fX += fTextWidth * pAttr->oTextMatrix.fA;
pAttr->oTextPos.fY += fTextWidth * pAttr->oTextMatrix.fB;
}
else
{
pAttr->oTextPos.fX -= fTextWidth * pAttr->oTextMatrix.fB;
pAttr->oTextPos.fY -= fTextWidth * pAttr->oTextMatrix.fA;
}
return nRet;
}
// Operator : "
// Description: Переходим на следующую строку и показываем текст, с расстоянием между словами fWordSpace и
// Расстоянием между символами fCharSpace (соответствующие параметры сохраняем в GState).
// Этот оператор должен быть эквивалентен последовательности операторов:
// fWordSpace Tw
// fCharSpace Tc
// sText '
unsigned long PageShowTextNextLineEx (Page pPage, float fWordSpace, float fCharSpace, const BYTE *sText, unsigned int nLen, unsigned int *pCIDs, unsigned int nLenCID)
{
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
if ( fWordSpace < MIN_WORDSPACE || fWordSpace > MAX_WORDSPACE)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
if ( fCharSpace < MIN_CHARSPACE || fCharSpace > MAX_CHARSPACE)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( !pAttr->pGState->pFont )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_FONT_NOT_FOUND, 0);
if ( NULL == sText || 0 == nLen )
return PageMoveToNextLine( pPage );
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fWordSpace, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fCharSpace, pEndBufPointer);
*pBufPointer = ' ';
if ( OK != ( nRet = InternalWriteText( pAttr, (BYTE *)sBuffer, UtilsStrLen( sBuffer, LIMIT_MAX_NAME_LEN ) ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = InternalWriteText( pAttr, sText, nLen ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " \"\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fWordSpace = fWordSpace;
pAttr->pGState->fCharSpace = fCharSpace;
float fTextWidth = PageTextWidth( pPage, sText, nLen, pCIDs, nLenCID );
pAttr->oTextMatrix.fX += pAttr->pGState->fTextLeading * pAttr->oTextMatrix.fB;
pAttr->oTextMatrix.fY -= pAttr->pGState->fTextLeading * pAttr->oTextMatrix.fA;
pAttr->oTextPos.fX = pAttr->oTextMatrix.fX;
pAttr->oTextPos.fY = pAttr->oTextMatrix.fY;
if ( WModeHorizontal == pAttr->pGState->eWritingMode )
{
pAttr->oTextPos.fX += fTextWidth * pAttr->oTextMatrix.fA;
pAttr->oTextPos.fY += fTextWidth * pAttr->oTextMatrix.fB;
}
else
{
pAttr->oTextPos.fX -= fTextWidth * pAttr->oTextMatrix.fB;
pAttr->oTextPos.fY -= fTextWidth * pAttr->oTextMatrix.fA;
}
return nRet;
}
//--- Color showing -----------------------------------------------------------------------------------
// TO DO:
// CS cs SC SCN sc scn
// Operator : G
// Description: Устанавливаем цветовое пространтсво для обводки в DeviceGray, а уровень серости(GrayLevel)
// выставляем равным fGray (для обводки).
unsigned long PageSetGrayStroke (Page pPage, float fGray)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( fGray < 0 || fGray > 1 )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0 );
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fGray ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " G\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fGrayStroke = fGray;
pAttr->pGState->eCSStroke = CSDeviceGray;
return nRet;
}
// Operator : g
// Description: Устанавливаем цветовое пространтсво для заливки в DeviceGray, а уровень серости(GrayLevel)
// выставляем равным fGray (для заливки).
unsigned long PageSetGrayFill (Page pPage, float fGray)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( fGray < 0 || fGray > 1 )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0 );
if ( OK != ( nRet = StreamWriteReal( pAttr->pStream, fGray ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " g\012" ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fGrayFill = fGray;
pAttr->pGState->eCSFill = CSDeviceGray;
return nRet;
}
// Operator : RG
// Description: Устанавливаем цветовое пространтсво для обводки в DeviceRGB и устанавливаем цвет для
// операций связанных с обведением фигур.
unsigned long PageSetRGBStroke (Page pPage, float fR, float fG, float fB)
{
if ( fR < 0 || fR > 1 || fG < 0 || fG > 1 || fB < 0 || fB > 1)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fR, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fG, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fB, pEndBufPointer);
UtilsStrCpy( pBufPointer, " RG\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->pGState->oRGBStroke.r = fR;
pAttr->pGState->oRGBStroke.g = fG;
pAttr->pGState->oRGBStroke.b = fB;
pAttr->pGState->eCSStroke = CSDeviceRGB;
return nRet;
}
// Operator : rg
// Description: Устанавливаем цветовое пространтсво для заливки в DeviceRGB и устанавливаем цвет для
// операций связанных с заливкой фигур.
unsigned long PageSetRGBFill (Page pPage, float fR, float fG, float fB)
{
if ( fR < 0 || fR > 1 || fG < 0 || fG > 1 || fB < 0 || fB > 1)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT | GMODE_PAGE_DESCRIPTION);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fR, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fG, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fB, pEndBufPointer);
UtilsStrCpy( pBufPointer, " rg\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->pGState->oRGBFill.r = fR;
pAttr->pGState->oRGBFill.g = fG;
pAttr->pGState->oRGBFill.b = fB;
pAttr->pGState->eCSFill = CSDeviceRGB;
return nRet;
}
// Operator : K
// Description: Устанавливаем цветовое пространтсво для обводки в DeviceCMYK и устанавливаем цвет для
// операций связанных с обведением фигур.
unsigned long PageSetCMYKStroke (Page pPage, float fC, float fM, float fY, float fK)
{
if ( fC < 0 || fC > 1 || fM < 0 || fM > 1 || fY < 0 || fY > 1 || fK < 0 || fK > 1)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT | GMODE_PAGE_DESCRIPTION);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fC, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fM, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fK, pEndBufPointer);
UtilsStrCpy( pBufPointer, " K\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->pGState->oCMYKStroke.c = fC;
pAttr->pGState->oCMYKStroke.m = fM;
pAttr->pGState->oCMYKStroke.y = fY;
pAttr->pGState->oCMYKStroke.k = fK;
pAttr->pGState->eCSStroke = CSDeviceCMYK;
return nRet;
}
// Operator : k
// Description: Устанавливаем цветовое пространтсво для заливки в DeviceCMYK и устанавливаем цвет для
// операций связанных с заливкой фигур.
unsigned long PageSetCMYKFill (Page pPage, float fC, float fM, float fY, float fK)
{
if ( fC < 0 || fC > 1 || fM < 0 || fM > 1 || fY < 0 || fY > 1 || fK < 0 || fK > 1)
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT | GMODE_PAGE_DESCRIPTION);
if ( OK != nRet )
return nRet;
char sBuffer[TEMP_BUFFER_SIZE];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
PageAttr pAttr = (PageAttr)pPage->pAttr;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fC, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fM, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fK, pEndBufPointer);
UtilsStrCpy( pBufPointer, " K\012", pEndBufPointer);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->pGState->oCMYKFill.c = fC;
pAttr->pGState->oCMYKFill.m = fM;
pAttr->pGState->oCMYKFill.y = fY;
pAttr->pGState->oCMYKFill.k = fK;
pAttr->pGState->eCSFill = CSDeviceCMYK;
return nRet;
}
//--- Shading patterns --------------------------------------------------------------------------------
// TO DO :
// sh
//--- In-line images ----------------------------------------------------------------------------------
// TO DO :
// BI ID EI
//--- XObjects ----------------------------------------------------------------------------------------
// Operator : Do
// Description: Рисуем объект XObject
unsigned long PageExecuteXObject (Page pPage, XObject pXobj)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION);
if ( OK != nRet )
return nRet;
if ( !pXobj || pXobj->pHeader.nObjClass != (OSUBCLASS_XOBJECT | OCLASS_DICT) )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_INVALID_OBJECT, 0);
if ( pPage->oMMgr != pXobj->oMMgr )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_XOBJECT, 0);
PageAttr pAttr = (PageAttr)pPage->pAttr;
const char *sLocalName = PageGetXObjectName( pPage, pXobj);
if ( !sLocalName )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_XOBJECT, 0);
if ( OK != ( nRet = StreamWriteEscapeName( pAttr->pStream, sLocalName ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, " Do\012" ) ) )
return CheckError( pPage->oError );
return nRet;
}
//--- Marked content ----------------------------------------------------------------------------------
// TO DO :
// MP DP BMC BDC EMC
//--- Compatibility -----------------------------------------------------------------------------------
// TO DO :
// BX EX
//--- Дополнительные функции(не по спецификации) ------------------------------------------------------
unsigned long PageCircle (Page pPage, float fX, float fY, float fRad)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
char sBuffer[TEMP_BUFFER_SIZE * 2];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX - fRad, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
pBufPointer = (char*)UtilsStrCpy( pBufPointer, " m\012", pEndBufPointer);
pBufPointer = QuarterCircleA( pBufPointer, pEndBufPointer, fX, fY, fRad);
pBufPointer = QuarterCircleB( pBufPointer, pEndBufPointer, fX, fY, fRad);
pBufPointer = QuarterCircleC( pBufPointer, pEndBufPointer, fX, fY, fRad);
QuarterCircleD( pBufPointer, pEndBufPointer, fX, fY, fRad);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fX - fRad;
pAttr->oCurPos.fY = fY;
pAttr->oStrPos = pAttr->oCurPos;
pAttr->nGMode = GMODE_PATH_OBJECT;
return nRet;
}
unsigned long PageEllipse (Page pPage, float fX, float fY, float fXRay, float fYRay)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
char sBuffer[TEMP_BUFFER_SIZE * 2];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
pBufPointer = UtilsFToA( pBufPointer, fX - fXRay, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fY, pEndBufPointer);
pBufPointer = (char*)UtilsStrCpy( pBufPointer, " m\012", pEndBufPointer);
pBufPointer = QuarterEllipseA( pBufPointer, pEndBufPointer, fX, fY, fXRay, fYRay);
pBufPointer = QuarterEllipseB( pBufPointer, pEndBufPointer, fX, fY, fXRay, fYRay);
pBufPointer = QuarterEllipseC( pBufPointer, pEndBufPointer, fX, fY, fXRay, fYRay);
QuarterEllipseD( pBufPointer, pEndBufPointer, fX, fY, fXRay, fYRay);
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fX - fXRay;
pAttr->oCurPos.fY = fY;
pAttr->oStrPos = pAttr->oCurPos;
pAttr->nGMode = GMODE_PATH_OBJECT;
return nRet;
}
unsigned long PageEllipseArc (Page pPage, float fX, float fY, float fXRad, float fYRad, float fAngle1, float fAngle2, bool bClockDirection)
{
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_PATH_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
char sBuffer[TEMP_BUFFER_SIZE * 2];
char *pBufPointer = sBuffer;
char *pEndBufPointer = sBuffer + TEMP_BUFFER_SIZE - 1;
UtilsMemSet( sBuffer, 0, TEMP_BUFFER_SIZE);
// переведем углы в радианы
double dAngle1 = fAngle1 * 3.141592f / 180;
double dAngle2 = fAngle2 * 3.141592f / 180;
// Выясним в каких четвертях находятся начальная и конечная точки
int nFirstPointQuard = int(fAngle1) / 90 + 1;
int nSecondPointQuard = int(fAngle2) / 90 + 1;
nSecondPointQuard = (std::min)( 4, (std::max)( 1, nSecondPointQuard ) );
nFirstPointQuard = (std::min)( 4, (std::max)( 1, nFirstPointQuard ) );
// Проведем линию в начальную точку дуги
float fStartX = 0.0f, fStartY = 0.0f, fEndX = 0.0f, fEndY = 0.0f;
fStartX = fX + fXRad * cos( AngToEllPrm( dAngle1, fXRad, fYRad ) );
fStartY = fY + fYRad * sin( AngToEllPrm( dAngle1, fXRad, fYRad ) );
pBufPointer = UtilsFToA( pBufPointer, fStartX, pEndBufPointer);
*pBufPointer++ = ' ';
pBufPointer = UtilsFToA( pBufPointer, fStartY, pEndBufPointer);
pBufPointer = (char*)UtilsStrCpy( pBufPointer, " l\012", pEndBufPointer);
// Дальше рисуем по четверям
float fCurX = fStartX, fCurY = fStartY;
double dStartAngle = dAngle1;
double dEndAngle = 0;
if ( !bClockDirection )
{
for( unsigned int nIndex = nFirstPointQuard; nIndex <= nSecondPointQuard; nIndex++ )
{
if ( nIndex == nSecondPointQuard )
dEndAngle = dAngle2;
else
dEndAngle = (90 * (nIndex ) ) * 3.141592f / 180;
if ( !( nIndex == nFirstPointQuard ) )
dStartAngle = (90 * (nIndex - 1 ) ) * 3.141592f / 180;
pBufPointer = EllipseArc( pBufPointer, pEndBufPointer, fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), &fEndX, &fEndY, false);
}
}
else
{
for( unsigned int nIndex = nFirstPointQuard; nIndex >= nSecondPointQuard; nIndex-- )
{
if ( nIndex == nFirstPointQuard )
dStartAngle = dAngle1;
else
dStartAngle = (90 * (nIndex ) ) * 3.141592f / 180;
if ( !( nIndex == nSecondPointQuard ) )
dEndAngle = (90 * (nIndex - 1 ) ) * 3.141592f / 180;
else
dEndAngle = dAngle2;
pBufPointer = EllipseArc( pBufPointer, pEndBufPointer, fX, fY, fXRad, fYRad, AngToEllPrm( dStartAngle, fXRad, fYRad ), AngToEllPrm( dEndAngle, fXRad, fYRad ), &fEndX, &fEndY, false);
}
}
if ( OK != ( nRet = StreamWriteStr( pAttr->pStream, sBuffer ) ) )
return CheckError( pPage->oError );
pAttr->oCurPos.fX = fEndX;
pAttr->oCurPos.fY = fEndY;
pAttr->oStrPos = pAttr->oCurPos;
pAttr->nGMode = GMODE_PATH_OBJECT;
return nRet;
}
unsigned long PageEllipseArc2 (Page pPage, float fX, float fY, float fXRad, float fYRad, float fAngle1, float fAngle2, bool bClockDirection/* = false*/)
{
unsigned long nRet = OK;
// Проверяем эллипс на невырожденность
if ( fXRad < 0.001 || fYRad < 0.001 )
{
double dAngle1 = fAngle1 * 3.141592f / 180;
double dAngle2 = fAngle2 * 3.141592f / 180;
if ( fXRad < 0.001 && fYRad < 0.001 )
nRet = PageLineTo( pPage, fX, fY );
else if ( fXRad < 0.001 )
{
nRet += PageLineTo( pPage, fX, fY + sin( dAngle1 ) * fYRad );
nRet += PageLineTo( pPage, fX, fY + sin( dAngle2 ) * fYRad );
}
else // if ( fYRad < 0.001 )
{
nRet += PageLineTo( pPage, fX + cos( dAngle1 ) * fXRad, fY );
nRet += PageLineTo( pPage, fX + cos( dAngle2 ) * fXRad, fY );
}
return nRet;
}
while ( fAngle1 < 0 )
fAngle1 += 360;
while ( fAngle1 > 360 )
fAngle1 -= 360;
while ( fAngle2 < 0 )
fAngle2 += 360;
while ( fAngle2 >= 360 )
fAngle2 -= 360;
if ( !bClockDirection )
{
if ( fAngle1 <= fAngle2 )
nRet = PageEllipseArc( pPage, fX, fY, fXRad, fYRad, fAngle1, fAngle2, false );
else
{
nRet += PageEllipseArc( pPage, fX, fY, fXRad, fYRad, fAngle1, 360, false );
nRet += PageEllipseArc( pPage, fX, fY, fXRad, fYRad, 0, fAngle2, false );
}
}
else
{
if ( fAngle1 >= fAngle2 )
nRet = PageEllipseArc( pPage, fX, fY, fXRad, fYRad, fAngle1, fAngle2, true );
else
{
nRet += PageEllipseArc( pPage, fX, fY, fXRad, fYRad, fAngle1, 0, true );
nRet += PageEllipseArc( pPage, fX, fY, fXRad, fYRad, 360, fAngle2, true );
}
}
return nRet;
}
// Математическое описание см. здесь
// http://www.tinaja.com/glib/bezarc1.pdf
// http://www.whizkidtech.redprince.net/bezier/circle/
unsigned long PageArc (Page pPage, float fX, float fY, float fRay, float fAng1, float fAng2)
{
bool bContFlag = false;
unsigned long nRet = PageCheckState( pPage, GMODE_PAGE_DESCRIPTION | GMODE_PATH_OBJECT);
if ( fAng1 >= fAng2 || ( fAng2 - fAng1 ) >= 360 )
RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_OUT_OF_RANGE, 0);
if ( OK != nRet )
return nRet;
while ( fAng1 < 0 || fAng2 < 0 )
{
fAng1 = fAng1 + 360;
fAng2 = fAng2 + 360;
}
for (;;)
{
if ( fAng2 - fAng1 <= 90 )
return InternalArc( pPage, fX, fY, fRay, fAng1, fAng2, bContFlag);
else
{
float fTempAngle = fAng1 + 90;
if ( OK != ( nRet = InternalArc( pPage, fX, fY, fRay, fAng1, fTempAngle, bContFlag ) ) )
return nRet;
fAng1 = fTempAngle;
}
if ( fAng1 >= fAng2 )
break;
bContFlag = true;
}
return OK;
}
unsigned long PageDrawImage (Page pPage, ImageDict pImage, float fX, float fY, float fWidth, float fHeight)
{
unsigned long nRet = OK;
if ( OK != ( nRet = PageGSave( pPage ) ) )
return nRet;
if ( OK != ( nRet = PageConcat( pPage, fWidth, 0, 0, fHeight, fX, fY ) ) )
return nRet;
if ( OK != ( nRet = PageExecuteXObject( pPage, pImage ) ) )
return nRet;
return PageGRestore( pPage );
}
unsigned long PageTextOut (Page pPage, float fXPos, float fYPos, const BYTE *sText, unsigned int nLen, unsigned int *pCIDs, unsigned int nLenCID)
{
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT );
if ( OK != nRet )
return nRet;
float fX = 0.0f;
float fY = 0.0f;
PageAttr pAttr = (PageAttr)pPage->pAttr;
if ( 0 == pAttr->oTextMatrix.fA )
{
fY = ( fXPos - pAttr->oTextMatrix.fX ) / pAttr->oTextMatrix.fC;
fX = ( fYPos - pAttr->oTextMatrix.fY - ( fXPos - pAttr->oTextMatrix.fX ) * pAttr->oTextMatrix.fD / pAttr->oTextMatrix.fC ) / pAttr->oTextMatrix.fB;
}
else
{
fY = ( fYPos - pAttr->oTextMatrix.fY - ( fXPos - pAttr->oTextMatrix.fX ) * pAttr->oTextMatrix.fB / pAttr->oTextMatrix.fA ) / ( pAttr->oTextMatrix.fD - pAttr->oTextMatrix.fC * pAttr->oTextMatrix.fB / pAttr->oTextMatrix.fA );
fX = ( fXPos - pAttr->oTextMatrix.fX - fY * pAttr->oTextMatrix.fC ) / pAttr->oTextMatrix.fA;
}
if ( OK != ( nRet = PageMoveTextPos( pPage, fX, fY ) ) )
return nRet;
return PageShowText( pPage, sText, nLen, pCIDs, nLenCID );
}
unsigned long PageTextRect (Page pPage, float fLeft, float fTop, float fRight, float fBottom, const char *sText, TextAlignment eAlign, unsigned int *pnLen, unsigned int *pCIDs, unsigned int nLenCID)
{
unsigned long nRet = PageCheckState( pPage, GMODE_TEXT_OBJECT);
if ( OK != nRet )
return nRet;
PageAttr pAttr = (PageAttr)pPage->pAttr;
const char *ptr = sText;
float fSaveCharSpace = 0.0f;
bool bIsInsufficientSpace = false;
bool bCharSpaceChanged = false;
if ( !pAttr->pGState->pFont )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_FONT_NOT_FOUND, 0 );
Box oBox = FontGetBBox( pAttr->pGState->pFont );
if ( pnLen )
*pnLen = 0;
unsigned int nNumRest = UtilsStrLen( sText, LIMIT_MAX_STRING_LEN + 1 );
if ( nNumRest > LIMIT_MAX_STRING_LEN )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_STRING_OUT_OF_RANGE, 0 );
else if ( !nNumRest )
return OK;
if ( 0 == pAttr->pGState->fTextLeading )
PageSetTextLeading( pPage, ( oBox.fTop - oBox.fBottom ) / 1000 * pAttr->pGState->fFontSize );
fTop = fTop - oBox.fTop / 1000 * pAttr->pGState->fFontSize + pAttr->pGState->fTextLeading;
fBottom = fBottom - oBox.fBottom / 1000 * pAttr->pGState->fFontSize;
float fX = 0.0f;
float fY = 0.0f;
if ( 0 == pAttr->oTextMatrix.fA )
{
fY = ( fLeft - pAttr->oTextMatrix.fX ) / pAttr->oTextMatrix.fC;
fX = ( fTop - pAttr->oTextMatrix.fY - ( fLeft - pAttr->oTextMatrix.fX ) * pAttr->oTextMatrix.fD / pAttr->oTextMatrix.fC ) / pAttr->oTextMatrix.fB;
}
else
{
fY = ( fTop - pAttr->oTextMatrix.fY - ( fLeft - pAttr->oTextMatrix.fX ) * pAttr->oTextMatrix.fB / pAttr->oTextMatrix.fA ) / ( pAttr->oTextMatrix.fD - pAttr->oTextMatrix.fC * pAttr->oTextMatrix.fB / pAttr->oTextMatrix.fA );
fX = ( fLeft - pAttr->oTextMatrix.fX - fY * pAttr->oTextMatrix.fC ) / pAttr->oTextMatrix.fA;
}
if ( OK != ( nRet = PageMoveTextPos( pPage, fX, fY ) ) )
return nRet;
if ( TAlignJustify == eAlign )
{
fSaveCharSpace = pAttr->pGState->fCharSpace;
pAttr->pGState->fCharSpace = 0;
}
for (;;)
{
float fRealWidth = 0.0f;
float fXAdjust = 0.0f;
const char *pTempPointer = NULL;
unsigned int nNumChar = 0;
ParseTextRec pState;
EncoderRecPtr pEncoder;
unsigned int nIndex = 0;
unsigned int nTempLen = PageMeasureText( pPage, ptr, pCIDs, nLenCID, fRight - fLeft, true, &fRealWidth );
if ( 0 == nTempLen )
{
bIsInsufficientSpace = true;
break;
}
if ( pnLen )
*pnLen += nTempLen;
switch ( eAlign )
{
case TAlignRight:
fXAdjust = fRight - fLeft - fRealWidth;
if ( OK != ( nRet = PageMoveTextPos( pPage, fXAdjust, 0 ) ) )
return nRet;
if ( OK != ( nRet = InternalShowTextNextLine( pPage, (BYTE *)ptr, nTempLen, pCIDs, nLenCID ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = PageMoveTextPos( pPage, -fXAdjust, 0 ) ) )
return nRet;
break;
case TAlignCenter:
fXAdjust = ( fRight - fLeft - fRealWidth ) / 2;
if ( OK != ( nRet = PageMoveTextPos( pPage, fXAdjust, 0 ) ) )
return nRet;
if ( OK != ( nRet = InternalShowTextNextLine( pPage, (BYTE *)ptr, nTempLen, pCIDs, nLenCID ) ) )
return CheckError( pPage->oError );
if ( OK != ( nRet = PageMoveTextPos( pPage, -fXAdjust, 0 ) ) )
return nRet;
break;
case TAlignJustify:
nNumChar = 0;
pEncoder = ((FontAttr)pAttr->pGState->pFont->pAttr)->pEncoder;
pTempPointer = ptr;
EncoderSetParseText( pEncoder, &pState, (BYTE*)pTempPointer, nTempLen );
while ( *pTempPointer )
{
ByteType eByteType = EncoderByteType( pEncoder, &pState);
if ( ByteTypeTrial != eByteType )
nNumChar++;
nIndex++;
if ( nIndex >= nTempLen )
break;
pTempPointer++;
}
if ( IS_WHITE_SPACE(*pTempPointer) )
nNumChar--;
if ( nNumChar > 1 )
fXAdjust = ( fRight - fLeft - fRealWidth ) / ( nNumChar - 1 );
else
fXAdjust = 0;
if ( nNumRest == nTempLen )
{
if ( OK != ( nRet = PageSetCharSpace( pPage, fSaveCharSpace ) ) )
return nRet;
bCharSpaceChanged = false;
}
else
{
if ( OK != ( nRet = PageSetCharSpace( pPage, fXAdjust ) ) )
return nRet;
bCharSpaceChanged = true;
}
if ( OK != ( nRet = InternalShowTextNextLine( pPage, (BYTE *)ptr, nTempLen, pCIDs, nLenCID ) ) )
return CheckError( pPage->oError );
pAttr->pGState->fCharSpace = 0;
break;
default:
if ( OK != ( nRet = InternalShowTextNextLine( pPage, (BYTE *)ptr, nTempLen, pCIDs, nLenCID ) ) )
return CheckError( pPage->oError );
break;
}
nNumRest -= nTempLen;
if ( nNumRest <= 0 )
break;
if ( pAttr->oTextPos.fY - pAttr->pGState->fTextLeading < fBottom )
{
bIsInsufficientSpace = true;
break;
}
ptr += nTempLen;
}
if ( bCharSpaceChanged )
if ( OK != ( nRet = PageSetCharSpace( pPage, fSaveCharSpace ) ) )
return nRet;
if ( bIsInsufficientSpace )
return AVS_OFFICEPDFWRITER_ERROR_PAGE_INSUFFICIENT_SPACE;
else
return OK;
}
unsigned long PageSetSlideShow(Page pPage, TransitionStyle eType, float fDispTime, float fTransTime)
{
unsigned long nRet = OK;
if ( !PageValidate( pPage ) )
return AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGE;
if ( fDispTime < 0 )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_DISPLAY_TIME, (unsigned long)fDispTime);
if ( fTransTime < 0 )
return RaiseError( pPage->oError, AVS_OFFICEPDFWRITER_ERROR_PAGE_INVALID_TRANSITION_TIME, (unsigned long)fTransTime);
Dict pDict = DictNew( pPage->oMMgr );
if ( !pDict )
return ErrorGetCode( pPage->oError );
if ( OK != ( nRet = DictAddName( pDict, "Type", "Trans" ) ) )
{
DictFree( pDict );
return ErrorGetCode( pPage->oError );
}
if ( OK != ( nRet = DictAddReal( pDict, "D", fTransTime ) ) )
{
DictFree( pDict );
return ErrorGetCode( pPage->oError );
}
switch ( eType )
{
case TSWipeRight:
nRet += DictAddName( pDict, "S", "Wipe");
nRet += DictAddNumber( pDict, "Di", 0);
break;
case TSWipeUp:
nRet += DictAddName( pDict, "S", "Wipe");
nRet += DictAddNumber( pDict, "Di", 90);
break;
case TSWipeLeft:
nRet += DictAddName( pDict, "S", "Wipe");
nRet += DictAddNumber( pDict, "Di", 180);
break;
case TSWipeDown:
nRet += DictAddName( pDict, "S", "Wipe");
nRet += DictAddNumber( pDict, "Di", 270);
break;
case TSBarnDoorsHorizontalOut:
nRet += DictAddName( pDict, "S", "Split");
nRet += DictAddName( pDict, "Dm", "H");
nRet += DictAddName( pDict, "M", "O");
break;
case TSBarnDoorsHorizontalIn:
nRet += DictAddName( pDict, "S", "Split");
nRet += DictAddName( pDict, "Dm", "H");
nRet += DictAddName( pDict, "M", "I");
break;
case TSBarnDoorsVerticalOut:
nRet += DictAddName( pDict, "S", "Split");
nRet += DictAddName( pDict, "Dm", "V");
nRet += DictAddName( pDict, "M", "O");
break;
case TSBarnDoorsVerticalIn:
nRet += DictAddName( pDict, "S", "Split");
nRet += DictAddName( pDict, "Dm", "V");
nRet += DictAddName( pDict, "M", "I");
break;
case TSBoxOut:
nRet += DictAddName( pDict, "S", "Box");
nRet += DictAddName( pDict, "M", "O");
break;
case TSBoxIn:
nRet += DictAddName( pDict, "S", "Box");
nRet += DictAddName( pDict, "M", "I");
break;
case TSBlindsHorizontal:
nRet += DictAddName( pDict, "S", "Blinds");
nRet += DictAddName( pDict, "Dm", "H");
break;
case TSBlindsVertical:
nRet += DictAddName( pDict, "S", "Blinds");
nRet += DictAddName( pDict, "Dm", "V");
break;
case TSDissolve:
nRet += DictAddName( pDict, "S", "Dissolve");
break;
case TSGlitterRight:
nRet += DictAddName( pDict, "S", "Glitter");
nRet += DictAddNumber( pDict, "Di", 0);
break;
case TSGlitterDown:
nRet += DictAddName( pDict, "S", "Glitter");
nRet += DictAddNumber( pDict, "Di", 270);
break;
case TSGlitterTopLeftToBottomRight:
nRet += DictAddName( pDict, "S", "Glitter");
nRet += DictAddNumber( pDict, "Di", 315);
break;
case TSReplace:
nRet += DictAddName( pDict, "S", "R");
break;
default:
nRet = AVS_OFFICEPDFWRITER_ERROR_INVALID_PAGE_SLIDESHOW_TYPE;
}
if ( OK != nRet )
{
DictFree( pDict );
return ErrorGetCode( pPage->oError );
}
if ( OK != ( nRet = DictAddReal( pPage, "Dur", fDispTime ) ) )
{
DictFree( pDict );
return ErrorGetCode( pPage->oError );
}
if ( OK != ( nRet = DictAdd( pPage, "Trans", pDict ) ) )
return nRet;
return OK;
}