mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
1796 lines
44 KiB
C++
1796 lines
44 KiB
C++
#include "stdafx.h"
|
||
|
||
#include <stdlib.h>
|
||
#include <math.h>
|
||
#include "MemoryUtils.h"
|
||
#include "List.h"
|
||
#include "Object.h"
|
||
#include "Catalog.h"
|
||
#include "Graphics.h"
|
||
#include "GFont.h"
|
||
#include "Lexer.h"
|
||
#include "Annot.h"
|
||
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
#define annotFlagHidden 0x0002
|
||
#define annotFlagPrint 0x0004
|
||
#define annotFlagNoView 0x0020
|
||
|
||
#define fieldFlagReadOnly 0x00000001
|
||
#define fieldFlagRequired 0x00000002
|
||
#define fieldFlagNoExport 0x00000004
|
||
#define fieldFlagMultiline 0x00001000
|
||
#define fieldFlagPassword 0x00002000
|
||
#define fieldFlagNoToggleToOff 0x00004000
|
||
#define fieldFlagRadio 0x00008000
|
||
#define fieldFlagPushbutton 0x00010000
|
||
#define fieldFlagCombo 0x00020000
|
||
#define fieldFlagEdit 0x00040000
|
||
#define fieldFlagSort 0x00080000
|
||
#define fieldFlagFileSelect 0x00100000
|
||
#define fieldFlagMultiSelect 0x00200000
|
||
#define fieldFlagDoNotSpellCheck 0x00400000
|
||
#define fieldFlagDoNotScroll 0x00800000
|
||
#define fieldFlagComb 0x01000000
|
||
#define fieldFlagRichText 0x02000000
|
||
#define fieldFlagRadiosInUnison 0x02000000
|
||
#define fieldFlagCommitOnSelChange 0x04000000
|
||
|
||
#define fieldQuadLeft 0
|
||
#define fieldQuadCenter 1
|
||
#define fieldQuadRight 2
|
||
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
// AnnotBorderStyle
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
AnnotBorderStyle::AnnotBorderStyle(AnnotBorderType eType, double dWidth, double *pDash, int nDashLength, double dR, double dG, double dB)
|
||
{
|
||
m_eType = eType;
|
||
m_dWidth = dWidth;
|
||
m_pDash = pDash;
|
||
m_nDashLength = nDashLength;
|
||
m_dR = dR;
|
||
m_dG = dG;
|
||
m_dB = dB;
|
||
}
|
||
|
||
AnnotBorderStyle::~AnnotBorderStyle()
|
||
{
|
||
MemUtilsFree( m_pDash );
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
// Annot
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
Annot::Annot(GlobalParams *pGlobalParams, XRef *pXref, Dict *pAcroForm, Dict *pDict, Ref *pRef)
|
||
{
|
||
m_pGlobalParams = pGlobalParams;
|
||
|
||
m_bValid = TRUE;
|
||
m_pXref = pXref;
|
||
m_oRef = *pRef;
|
||
m_seType = NULL;
|
||
m_seAppBuffer = NULL;
|
||
m_pBorderStyle = NULL;
|
||
|
||
// SubType
|
||
Object oDictItem;
|
||
if ( pDict->Search("Subtype", &oDictItem)->IsName() )
|
||
{
|
||
m_seType = new StringExt( oDictItem.GetName() );
|
||
}
|
||
oDictItem.Free();
|
||
|
||
// Rect
|
||
if ( pDict->Search("Rect", &oDictItem)->IsArray() && oDictItem.ArrayGetLength() == 4 )
|
||
{
|
||
Object oTemp;
|
||
m_dMinX = m_dMinY = m_dMaxX = m_dMaxY = 0;
|
||
if ( oDictItem.ArrayGet( 0, &oTemp)->IsNum() )
|
||
{
|
||
m_dMinX = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
|
||
if ( oDictItem.ArrayGet( 1, &oTemp)->IsNum() )
|
||
{
|
||
m_dMinY = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
|
||
if ( oDictItem.ArrayGet( 2, &oTemp)->IsNum() )
|
||
{
|
||
m_dMaxX = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
|
||
if ( oDictItem.ArrayGet( 3, &oTemp)->IsNum() )
|
||
{
|
||
m_dMaxY = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
|
||
if ( m_dMinX > m_dMaxX )
|
||
{
|
||
double dTemp = m_dMinX;
|
||
m_dMinX = m_dMaxX;
|
||
m_dMaxX = dTemp;
|
||
}
|
||
|
||
if ( m_dMinY > m_dMaxY )
|
||
{
|
||
double dTemp = m_dMinY;
|
||
m_dMinY = m_dMaxY;
|
||
m_dMaxY = dTemp;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// TO DO: Error "Bad bounding box for annotation"
|
||
m_bValid = FALSE;
|
||
}
|
||
oDictItem.Free();
|
||
|
||
// F (flags)
|
||
if ( pDict->Search("F", &oDictItem)->IsInt() )
|
||
{
|
||
m_nFlags = oDictItem.GetInt();
|
||
}
|
||
else
|
||
{
|
||
m_nFlags = 0;
|
||
}
|
||
oDictItem.Free();
|
||
|
||
//Border style
|
||
|
||
AnnotBorderType eBorderType = annotBorderSolid;
|
||
double dBorderWidth = 1;
|
||
double *pBorderDash = NULL;
|
||
int nBorderDashLength = 0;
|
||
double dBorderR = 0;
|
||
double dBorderG = 0;
|
||
double dBorderB = 1;
|
||
if ( pDict->Search("BS", &oDictItem)->IsDict() )
|
||
{
|
||
Object oTemp;
|
||
if ( oDictItem.DictLookup("S", &oTemp)->IsName() )
|
||
{
|
||
if ( oTemp.IsName("S") )
|
||
{
|
||
eBorderType = annotBorderSolid;
|
||
}
|
||
else if ( oTemp.IsName("D") )
|
||
{
|
||
eBorderType = annotBorderDashed;
|
||
}
|
||
else if ( oTemp.IsName("B") )
|
||
{
|
||
eBorderType = annotBorderBeveled;
|
||
}
|
||
else if ( oTemp.IsName("I") )
|
||
{
|
||
eBorderType = annotBorderInset;
|
||
}
|
||
else if ( oTemp.IsName("U") )
|
||
{
|
||
eBorderType = annotBorderUnderlined;
|
||
}
|
||
}
|
||
oTemp.Free();
|
||
|
||
if ( oDictItem.DictLookup("W", &oTemp)->IsNum() )
|
||
{
|
||
dBorderWidth = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
|
||
if ( oDictItem.DictLookup("D", &oTemp)->IsArray() )
|
||
{
|
||
nBorderDashLength = oTemp.ArrayGetLength();
|
||
pBorderDash = (double *)MemUtilsMallocArray( nBorderDashLength, sizeof(double) );
|
||
|
||
for ( int nIndex = 0; nIndex < nBorderDashLength; ++nIndex )
|
||
{
|
||
Object oArrayItem;
|
||
if ( oTemp.ArrayGet( nIndex, &oArrayItem)->IsNum() )
|
||
{
|
||
pBorderDash[nIndex] = oArrayItem.GetNum();
|
||
}
|
||
else
|
||
{
|
||
pBorderDash[nIndex] = 1;
|
||
}
|
||
oArrayItem.Free();
|
||
}
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
else
|
||
{
|
||
oDictItem.Free();
|
||
if ( pDict->Search("Border", &oDictItem)->IsArray() )
|
||
{
|
||
Object oTemp;
|
||
if ( oDictItem.ArrayGetLength() >= 3 )
|
||
{
|
||
if ( oDictItem.ArrayGet( 2, &oTemp)->IsNum() )
|
||
{
|
||
dBorderWidth = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
if ( oDictItem.ArrayGetLength() >= 4 )
|
||
{
|
||
if ( oDictItem.ArrayGet( 3, &oTemp)->IsArray() )
|
||
{
|
||
eBorderType = annotBorderDashed;
|
||
nBorderDashLength = oTemp.ArrayGetLength();
|
||
pBorderDash = (double *)MemUtilsMallocArray( nBorderDashLength, sizeof(double) );
|
||
|
||
for ( int nIndex = 0; nIndex < nBorderDashLength; ++nIndex )
|
||
{
|
||
Object oArrayItem;
|
||
if ( oTemp.ArrayGet( nIndex, &oArrayItem)->IsNum() )
|
||
{
|
||
pBorderDash[nIndex] = oArrayItem.GetNum();
|
||
}
|
||
else
|
||
{
|
||
pBorderDash[nIndex] = 1;
|
||
}
|
||
oArrayItem.Free();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
dBorderWidth = 0;
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
oDictItem.Free();
|
||
|
||
// C (border color)
|
||
// TO DO: <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> 0, 1, 3, 4
|
||
if ( pDict->Search("C", &oDictItem)->IsArray() && oDictItem.ArrayGetLength() == 3 )
|
||
{
|
||
Object oTemp;
|
||
if ( oDictItem.ArrayGet(0, &oTemp)->IsNum() )
|
||
{
|
||
dBorderR = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
|
||
if ( oDictItem.ArrayGet(1, &oTemp)->IsNum() )
|
||
{
|
||
dBorderG = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
|
||
if ( oDictItem.ArrayGet(2, &oTemp)->IsNum() )
|
||
{
|
||
dBorderB = oTemp.GetNum();
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
oDictItem.Free();
|
||
|
||
m_pBorderStyle = new AnnotBorderStyle( eBorderType, dBorderWidth, pBorderDash, nBorderDashLength, dBorderR, dBorderG, dBorderB);
|
||
|
||
// AP (appereance)
|
||
Object oAP;
|
||
if ( pDict->Search("AP", &oAP)->IsDict() )
|
||
{
|
||
Object oAS;
|
||
if ( pDict->Search("AS", &oAS)->IsName() )
|
||
{
|
||
Object oItem;
|
||
if ( oAP.DictLookup("N", &oItem)->IsDict() )
|
||
{
|
||
Object oTemp;
|
||
if ( oItem.DictLookupAndCopy( oAS.GetName(), &oTemp)->IsRef() )
|
||
{
|
||
oTemp.Copy(&m_oAppearance);
|
||
m_bValid = TRUE;
|
||
}
|
||
else
|
||
{
|
||
oTemp.Free();
|
||
if ( oItem.DictLookupAndCopy("Off", &oTemp)->IsRef() )
|
||
{
|
||
oTemp.Copy(&m_oAppearance);
|
||
}
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
oItem.Free();
|
||
}
|
||
else
|
||
{
|
||
Object oItem;
|
||
if ( oAP.DictLookupAndCopy("N", &oItem)->IsRef() )
|
||
{
|
||
oItem.Copy(&m_oAppearance);
|
||
}
|
||
oItem.Free();
|
||
}
|
||
oAS.Free();
|
||
}
|
||
oAP.Free();
|
||
}
|
||
|
||
Annot::~Annot()
|
||
{
|
||
if ( m_seType )
|
||
{
|
||
delete m_seType;
|
||
}
|
||
m_oAppearance.Free();
|
||
|
||
if ( m_seAppBuffer )
|
||
{
|
||
delete m_seAppBuffer;
|
||
}
|
||
if ( m_pBorderStyle )
|
||
{
|
||
delete m_pBorderStyle;
|
||
}
|
||
}
|
||
|
||
void Annot::GenerateFieldAppearance(Dict *pField, Dict *pAnnot, Dict *pAcroForm)
|
||
{
|
||
// <20><><EFBFBD> Annotation <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Widget
|
||
if ( m_seType->Compare("Widget") )
|
||
{
|
||
return;
|
||
}
|
||
|
||
m_seAppBuffer = new StringExt();
|
||
|
||
// Appearance characteristics (MK) dictionary
|
||
Object oMKObject;
|
||
Dict *pMKDict;
|
||
if ( pAnnot->Search("MK", &oMKObject)->IsDict() )
|
||
{
|
||
pMKDict = oMKObject.GetDict();
|
||
}
|
||
else
|
||
{
|
||
pMKDict = NULL;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> (BackGround)
|
||
Object oDictItem;
|
||
if ( pMKDict )
|
||
{
|
||
if ( pMKDict->Search("BG", &oDictItem)->IsArray() && oDictItem.ArrayGetLength() > 0 )
|
||
{
|
||
SetColor( oDictItem.GetArray(), TRUE, 0 );
|
||
m_seAppBuffer->AppendFormat("0 0 {0:.2f} {1:.2f} re f\n", m_dMaxX - m_dMinX, m_dMaxY - m_dMinY);
|
||
}
|
||
oDictItem.Free();
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
// FT (File Type)
|
||
Object oFTobject;
|
||
FieldLookup( pField, "FT", &oFTobject);
|
||
|
||
// Ff (Filed flags)
|
||
int nFiledFlags = 0;
|
||
if ( FieldLookup( pField, "Ff", &oDictItem)->IsInt() )
|
||
{
|
||
nFiledFlags = oDictItem.GetInt();
|
||
}
|
||
else
|
||
{
|
||
nFiledFlags = 0;
|
||
}
|
||
oDictItem.Free();
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
if ( pMKDict )
|
||
{
|
||
double dWidth = m_pBorderStyle->GetWidth();
|
||
if ( dWidth > 0 )
|
||
{
|
||
// BC (Border Color), <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> BG
|
||
pMKDict->Search("BC", &oDictItem);
|
||
if ( !(oDictItem.IsArray() && oDictItem.ArrayGetLength() > 0) )
|
||
{
|
||
pMKDict->Search("BG", &oDictItem);
|
||
}
|
||
if ( oDictItem.IsArray() && oDictItem.ArrayGetLength() > 0 )
|
||
{
|
||
double dDx = m_dMaxX - m_dMinX;
|
||
double dDy = m_dMaxY - m_dMinY;
|
||
double *pDash;
|
||
int nDashLength = 0;
|
||
|
||
Object oTemp;
|
||
BOOL bHasCaption = pMKDict->Search("CA", &oTemp)->IsString();
|
||
oTemp.Free();
|
||
|
||
if ( oFTobject.IsName("Btn") && ( nFiledFlags & fieldFlagRadio ) && !bHasCaption )
|
||
{
|
||
double dRad = 0.5 * (dDx < dDy ? dDx : dDy);
|
||
switch ( m_pBorderStyle->GetType() )
|
||
{
|
||
case annotBorderDashed:
|
||
m_seAppBuffer->Append("[");
|
||
m_pBorderStyle->GetDash( &pDash, &nDashLength );
|
||
for ( int nIndex = 0; nIndex < nDashLength; ++nIndex )
|
||
{
|
||
m_seAppBuffer->AppendFormat(" {0:.2f}", pDash[nIndex]);
|
||
}
|
||
m_seAppBuffer->Append("] 0 d\n");
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
case annotBorderSolid:
|
||
case annotBorderUnderlined:
|
||
m_seAppBuffer->AppendFormat("{0:.2f} w\n", dWidth);
|
||
SetColor( oDictItem.GetArray(), FALSE, 0);
|
||
DrawCircle( 0.5 * dDx, 0.5 * dDy, dRad - 0.5 * dWidth, FALSE);
|
||
break;
|
||
case annotBorderBeveled:
|
||
case annotBorderInset:
|
||
m_seAppBuffer->AppendFormat("{0:.2f} w\n", 0.5 * dWidth);
|
||
|
||
SetColor( oDictItem.GetArray(), FALSE, 0);
|
||
DrawCircle( 0.5 * dDx, 0.5 * dDy, dRad - 0.25 * dWidth, FALSE);
|
||
|
||
SetColor( oDictItem.GetArray(), FALSE, m_pBorderStyle->GetType() == annotBorderBeveled ? 1 : -1);
|
||
DrawCircleTopLeft( 0.5 * dDx, 0.5 * dDy, dRad - 0.75 * dWidth);
|
||
|
||
SetColor( oDictItem.GetArray(), FALSE, m_pBorderStyle->GetType() == annotBorderBeveled ? -1 : 1);
|
||
DrawCircleBottomRight(0.5 * dDx, 0.5 * dDy, dRad - 0.75 * dWidth);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
switch ( m_pBorderStyle->GetType() )
|
||
{
|
||
case annotBorderDashed:
|
||
m_seAppBuffer->Append("[");
|
||
m_pBorderStyle->GetDash( &pDash, &nDashLength );
|
||
for ( int nIndex = 0; nIndex < nDashLength; ++nIndex )
|
||
{
|
||
m_seAppBuffer->AppendFormat(" {0:.2f}", pDash[nIndex]);
|
||
}
|
||
m_seAppBuffer->Append("] 0 d\n");
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
case annotBorderSolid:
|
||
m_seAppBuffer->AppendFormat("{0:.2f} w\n", dWidth);
|
||
SetColor( oDictItem.GetArray(), FALSE, 0);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re s\n", 0.5 * dWidth, dDx - dWidth, dDy - dWidth);
|
||
break;
|
||
case annotBorderBeveled:
|
||
case annotBorderInset:
|
||
|
||
SetColor( oDictItem.GetArray(), TRUE, m_pBorderStyle->GetType() == annotBorderBeveled ? 1 : -1);
|
||
m_seAppBuffer->Append("0 0 m\n");
|
||
m_seAppBuffer->AppendFormat("0 {0:.2f} l\n", dDy);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} l\n", dDx, dDy);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} l\n", dDx - dWidth, dDy - dWidth);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} l\n", dWidth, dDy - dWidth);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {0:.2f} l\n", dWidth);
|
||
m_seAppBuffer->Append("f\n");
|
||
|
||
SetColor( oDictItem.GetArray(), TRUE, m_pBorderStyle->GetType() == annotBorderBeveled ? -1 : 1);
|
||
m_seAppBuffer->Append("0 0 m\n");
|
||
m_seAppBuffer->AppendFormat("{0:.2f} 0 l\n", dDx);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} l\n", dDx, dDy);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} l\n", dDx - dWidth, dDy - dWidth);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} l\n", dDx - dWidth, dWidth);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {0:.2f} l\n", dWidth);
|
||
m_seAppBuffer->Append("f\n");
|
||
break;
|
||
case annotBorderUnderlined:
|
||
m_seAppBuffer->AppendFormat("{0:.2f} w\n", dWidth);
|
||
SetColor( oDictItem.GetArray(), FALSE, 0);
|
||
m_seAppBuffer->AppendFormat("0 0 m {0:.2f} 0 l s\n", dDx);
|
||
break;
|
||
}
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re W n\n", dWidth, dDx - 2 * dWidth, dDy - 2 * dWidth);
|
||
}
|
||
}
|
||
oDictItem.Free();
|
||
}
|
||
}
|
||
|
||
// DR
|
||
Object oDRobject;
|
||
pAcroForm->Search("DR", &oDRobject);
|
||
|
||
// Font dictionary
|
||
GrFontDict *pFontDict;
|
||
if ( oDRobject.IsDict() && oDRobject.DictLookup("Font", &oDictItem)->IsDict() )
|
||
{
|
||
pFontDict = new GrFontDict( m_pXref, NULL, oDictItem.GetDict(), m_pGlobalParams );
|
||
}
|
||
else
|
||
{
|
||
pFontDict = NULL;
|
||
}
|
||
oDictItem.Free();
|
||
|
||
// DA (Default appereance string)
|
||
StringExt *seDA;
|
||
if ( FieldLookup( pField, "DA", &oDictItem )->IsNull() )
|
||
{
|
||
oDictItem.Free();
|
||
pAcroForm->Search("DA", &oDictItem);
|
||
}
|
||
if ( oDictItem.IsString() )
|
||
{
|
||
seDA = oDictItem.GetString()->Copy();
|
||
}
|
||
else
|
||
{
|
||
seDA = NULL;
|
||
}
|
||
oDictItem.Free();
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Filed
|
||
if ( oFTobject.IsName("Btn") )
|
||
{
|
||
StringExt *seCaption = NULL;
|
||
if ( pMKDict )
|
||
{
|
||
if ( pMKDict->Search("CA", &oDictItem)->IsString() )
|
||
{
|
||
seCaption = oDictItem.GetString()->Copy();
|
||
}
|
||
oDictItem.Free();
|
||
}
|
||
|
||
// Radio button
|
||
if ( nFiledFlags & fieldFlagRadio )
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Caption, <20><><EFBFBD><EFBFBD> <20><><EFBFBD> AP
|
||
if ( FieldLookup( pField, "V", &oDictItem )->IsName() )
|
||
{
|
||
Object oAppStream;
|
||
if ( pAnnot->Search("AS", &oAppStream)->IsName( oDictItem.GetName() ) )
|
||
{
|
||
if ( seCaption )
|
||
{
|
||
DrawText( seCaption, seDA, pFontDict, FALSE, 0, fieldQuadCenter, FALSE, TRUE);
|
||
}
|
||
else
|
||
{
|
||
if ( pMKDict )
|
||
{
|
||
Object oTemp;
|
||
if ( pMKDict->Search("BC", &oTemp)->IsArray() && oTemp.ArrayGetLength() > 0 )
|
||
{
|
||
double dDx = m_dMaxX - m_dMinX;
|
||
double dDy = m_dMaxY - m_dMinY;
|
||
SetColor( oTemp.GetArray(), TRUE, 0 );
|
||
DrawCircle( 0.5 * dDx, 0.5 * dDy, 0.2 * (dDx < dDy ? dDx : dDy), TRUE);
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
}
|
||
}
|
||
oAppStream.Free();
|
||
}
|
||
oDictItem.Free();
|
||
}
|
||
else if ( nFiledFlags & fieldFlagPushbutton ) // PushButton
|
||
{
|
||
if ( seCaption )
|
||
{
|
||
DrawText( seCaption, seDA, pFontDict, FALSE, 0, fieldQuadCenter, FALSE, FALSE);
|
||
}
|
||
}
|
||
else // CheckBox
|
||
{
|
||
// "Yes" - <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, "off" - <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
if ( FieldLookup( pField, "V", &oDictItem )->IsName("Yes") )
|
||
{
|
||
if ( !seCaption )
|
||
{
|
||
seCaption = new StringExt("3"); // ZapfDingbats checkmark
|
||
}
|
||
DrawText( seCaption, seDA, pFontDict, FALSE, 0, fieldQuadCenter, FALSE, TRUE);
|
||
}
|
||
oDictItem.Free();
|
||
}
|
||
if ( seCaption )
|
||
{
|
||
delete seCaption;
|
||
}
|
||
}
|
||
else if ( oFTobject.IsName("Tx") )
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
Object oValue;
|
||
if ( FieldLookup( pField, "V", &oValue )->IsString() )
|
||
{
|
||
Object oTemp;
|
||
int nQuadding = 0;
|
||
if ( FieldLookup( pField, "Q", &oTemp )->IsInt() )
|
||
{
|
||
nQuadding = oTemp.GetInt();
|
||
}
|
||
else
|
||
{
|
||
nQuadding = fieldQuadLeft;
|
||
}
|
||
oTemp.Free();
|
||
int nComb = 0;
|
||
if ( nFiledFlags & fieldFlagComb )
|
||
{
|
||
if ( FieldLookup( pField, "MaxLen", &oTemp )->IsInt())
|
||
{
|
||
nComb = oTemp.GetInt();
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
DrawText( oValue.GetString(), seDA, pFontDict, nFiledFlags & fieldFlagMultiline, nComb, nQuadding, TRUE, FALSE);
|
||
}
|
||
oValue.Free();
|
||
}
|
||
else if ( oFTobject.IsName("Ch") )
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
int nQuadding = 0;
|
||
Object oTemp;
|
||
if ( FieldLookup( pField, "Q", &oTemp )->IsInt() )
|
||
{
|
||
nQuadding = oTemp.GetInt();
|
||
}
|
||
else
|
||
{
|
||
nQuadding = fieldQuadLeft;
|
||
}
|
||
oTemp.Free();
|
||
|
||
// ComboBox
|
||
if ( nFiledFlags & fieldFlagCombo )
|
||
{
|
||
Object oValue;
|
||
if ( FieldLookup( pField, "V", &oValue)->IsString() )
|
||
{
|
||
DrawText( oValue.GetString(), seDA, pFontDict, FALSE, 0, nQuadding, TRUE, FALSE);
|
||
//~ Acrobat draws a popup icon on the right side
|
||
}
|
||
oValue.Free();
|
||
}
|
||
else // ListBox
|
||
{
|
||
Object oOptions;
|
||
if ( pField->Search("Opt", &oOptions)->IsArray() )
|
||
{
|
||
int nOptionsCount = oOptions.ArrayGetLength();
|
||
// Option text
|
||
StringExt **ppText = (StringExt **)MemUtilsMallocArray(nOptionsCount, sizeof(StringExt *));
|
||
for ( int nIndex = 0; nIndex < nOptionsCount; ++nIndex )
|
||
{
|
||
ppText[nIndex] = NULL;
|
||
Object oTemp;
|
||
oOptions.ArrayGet( nIndex, &oTemp );
|
||
if ( oTemp.IsString() )
|
||
{
|
||
ppText[nIndex] = oTemp.GetString()->Copy();
|
||
}
|
||
else if ( oTemp.IsArray() && oTemp.ArrayGetLength() == 2 )
|
||
{
|
||
Object oArrayItem;
|
||
if ( oTemp.ArrayGet( 1, &oArrayItem)->IsString() )
|
||
{
|
||
ppText[nIndex] = oArrayItem.GetString()->Copy();
|
||
}
|
||
oArrayItem.Free();
|
||
}
|
||
oTemp.Free();
|
||
if ( !ppText[nIndex] )
|
||
{
|
||
ppText[nIndex] = new StringExt();
|
||
}
|
||
}
|
||
// Selected option(s)
|
||
BOOL *pSelection = (BOOL *)MemUtilsMallocArray( nOptionsCount, sizeof(BOOL));
|
||
//~ need to use the I field in addition to the V field
|
||
Object oValue;
|
||
FieldLookup( pField, "V", &oValue);
|
||
for ( int nIndex = 0; nIndex < nOptionsCount; ++nIndex )
|
||
{
|
||
pSelection[nIndex] = FALSE;
|
||
if ( oValue.IsString() )
|
||
{
|
||
if ( !oValue.GetString()->Compare( ppText[nIndex] ) )
|
||
{
|
||
pSelection[nIndex] = TRUE;
|
||
}
|
||
}
|
||
else if ( oValue.IsArray() )
|
||
{
|
||
for ( int nJ = 0; nJ < oValue.ArrayGetLength(); ++nJ )
|
||
{
|
||
Object oTemp;
|
||
if ( oValue.ArrayGet( nJ, &oTemp)->IsString() && !oTemp.GetString()->Compare( ppText[nIndex] ) )
|
||
{
|
||
pSelection[nIndex] = TRUE;
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
}
|
||
}
|
||
oValue.Free();
|
||
|
||
// TI (Top Index)
|
||
int nTopIndex = 0;
|
||
if ( pField->Search("TI", &oValue)->IsInt() )
|
||
{
|
||
nTopIndex = oValue.GetInt();
|
||
}
|
||
else
|
||
{
|
||
nTopIndex = 0;
|
||
}
|
||
oValue.Free();
|
||
|
||
DrawListBox( ppText, pSelection, nOptionsCount, nTopIndex, seDA, pFontDict, nQuadding);
|
||
for ( int nIndex = 0; nIndex < nOptionsCount; ++nIndex )
|
||
{
|
||
delete ppText[nIndex];
|
||
}
|
||
MemUtilsFree( ppText );
|
||
MemUtilsFree( pSelection );
|
||
}
|
||
oOptions.Free();
|
||
}
|
||
}
|
||
else if ( oFTobject.IsName("Sig") )
|
||
{
|
||
//~unimp
|
||
}
|
||
else
|
||
{
|
||
// TO DO: Error "Unknown field type"
|
||
}
|
||
|
||
if ( seDA )
|
||
{
|
||
delete seDA;
|
||
}
|
||
|
||
// Appearance stream dictionary
|
||
Object oAppearanceDict;
|
||
|
||
oAppearanceDict.InitDict( m_pXref );
|
||
oAppearanceDict.DictAdd(CopyString("Length"), oDictItem.InitInt(m_seAppBuffer->GetLength()));
|
||
oAppearanceDict.DictAdd(CopyString("Subtype"), oDictItem.InitName("Form"));
|
||
oDictItem.InitArray( m_pXref );
|
||
Object oTemp;
|
||
oDictItem.ArrayAdd( oTemp.InitReal(0) );
|
||
oDictItem.ArrayAdd( oTemp.InitReal(0) );
|
||
oDictItem.ArrayAdd( oTemp.InitReal(m_dMaxX - m_dMinX) );
|
||
oDictItem.ArrayAdd( oTemp.InitReal(m_dMaxY - m_dMinY) );
|
||
oAppearanceDict.DictAdd(CopyString("BBox"), &oDictItem);
|
||
|
||
// Resource dictionary
|
||
if ( oDRobject.IsDict() )
|
||
{
|
||
oAppearanceDict.DictAdd(CopyString("Resources"), oDRobject.Copy(&oDictItem));
|
||
}
|
||
oDRobject.Free();
|
||
|
||
// Appearance stream
|
||
MemoryStream *pAppearStream = new MemoryStream( m_seAppBuffer->GetBuffer(), 0, m_seAppBuffer->GetLength(), &oAppearanceDict);
|
||
m_oAppearance.Free();
|
||
m_oAppearance.InitStream( pAppearStream );
|
||
|
||
if ( pFontDict )
|
||
{
|
||
delete pFontDict;
|
||
}
|
||
oFTobject.Free();
|
||
oMKObject.Free();
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>; <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <pArray> (<28> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
// 1, 3, <20><><EFBFBD> 4 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>). <20><><EFBFBD><EFBFBD> <nAdjust> <20><><EFBFBD><EFBFBD><EFBFBD> +1, <20><><EFBFBD><EFBFBD> color is <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <nAdjust> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
// -1, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
void Annot::SetColor(Array *pArray, BOOL bFill, int nAdjust)
|
||
{
|
||
double arrColor[4];
|
||
|
||
int nComponentsCount = pArray->GetCount();
|
||
if ( nComponentsCount > 4 )
|
||
{
|
||
nComponentsCount = 4;
|
||
}
|
||
for ( int nIndex = 0; nIndex < nComponentsCount && nIndex < 4; ++nIndex )
|
||
{
|
||
Object oTemp;
|
||
if ( pArray->Get( nIndex, &oTemp)->IsNum() )
|
||
{
|
||
arrColor[nIndex] = oTemp.GetNum();
|
||
}
|
||
else
|
||
{
|
||
arrColor[nIndex] = 0;
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
if ( 4 == nComponentsCount )
|
||
{
|
||
nAdjust = -nAdjust;
|
||
}
|
||
if ( nAdjust > 0 )
|
||
{
|
||
for ( int nIndex = 0; nIndex < nComponentsCount; ++nIndex )
|
||
{
|
||
arrColor[nIndex] = 0.5 * arrColor[nIndex] + 0.5;
|
||
}
|
||
}
|
||
else if ( nAdjust < 0 )
|
||
{
|
||
for ( int nIndex = 0; nIndex < nComponentsCount; ++nIndex )
|
||
{
|
||
arrColor[nIndex] = 0.5 * arrColor[nIndex];
|
||
}
|
||
}
|
||
if ( 4 == nComponentsCount )
|
||
{
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:c}\n", arrColor[0], arrColor[1], arrColor[2], arrColor[3], bFill ? 'k' : 'K');
|
||
}
|
||
else if ( 3 == nComponentsCount )
|
||
{
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:s}\n", arrColor[0], arrColor[1], arrColor[2], bFill ? "rg" : "RG");
|
||
}
|
||
else
|
||
{
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:c}\n", arrColor[0], bFill ? 'g' : 'G');
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> Field.
|
||
void Annot::DrawText(StringExt *seText, StringExt *seDA, GrFontDict *pFontDict, BOOL bMultiline, int nComb, int nQuadding, BOOL bTextField, BOOL bForceZapfDingbats)
|
||
{
|
||
CList *pListDA;
|
||
StringExt *seToken;
|
||
double dX, dY, dWidth;
|
||
int i, j, k, nChar;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Default Appearance string
|
||
|
||
int nTfPos = -1, nTmPos = -1;
|
||
if ( seDA )
|
||
{
|
||
pListDA = new CList();
|
||
i = 0;
|
||
while ( i < seDA->GetLength() )
|
||
{
|
||
while ( i < seDA->GetLength() && Lexer::IsSpace( seDA->GetAt(i) ) )
|
||
{
|
||
++i;
|
||
}
|
||
if ( i < seDA->GetLength() )
|
||
{
|
||
for ( j = i + 1; j < seDA->GetLength() && !Lexer::IsSpace(seDA->GetAt(j) ); ++j) ;
|
||
pListDA->Append(new StringExt(seDA, i, j - i));
|
||
i = j;
|
||
}
|
||
}
|
||
for ( i = 2; i < pListDA->GetLength(); ++i )
|
||
{
|
||
if ( i >= 2 && !((StringExt *)pListDA->GetByIndex(i))->Compare("Tf") )
|
||
{
|
||
nTfPos = i - 2;
|
||
}
|
||
else if ( i >= 6 && !((StringExt *)pListDA->GetByIndex(i))->Compare("Tm") )
|
||
{
|
||
nTmPos = i - 6;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pListDA = NULL;
|
||
}
|
||
|
||
// ZapfDingbats
|
||
if ( bForceZapfDingbats )
|
||
{
|
||
if ( nTfPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTfPos );
|
||
if ( seToken->Compare("/ZaDb") )
|
||
{
|
||
seToken->Clear();
|
||
seToken->Append("/ZaDb");
|
||
}
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
GrFont *pFont = NULL;
|
||
double dFontSize = 0;
|
||
if ( nTfPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTfPos );
|
||
if ( seToken->GetLength() >= 1 && seToken->GetAt(0) == '/' )
|
||
{
|
||
if ( !pFontDict || !(pFont = pFontDict->Search(seToken->GetBuffer() + 1) ) )
|
||
{
|
||
// TO DO: Error "Unknown font in field's DA string"
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// TO DO: Error "Invalid font name in 'Tf' operator in field's DA string"
|
||
}
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTfPos + 1 );
|
||
dFontSize = atof( seToken->GetBuffer());
|
||
}
|
||
else
|
||
{
|
||
// TO DO: Error "Missing 'Tf' operator in field's DA string"
|
||
}
|
||
|
||
// Border Width
|
||
double dBorderWidth = m_pBorderStyle->GetWidth();
|
||
|
||
if ( bTextField )
|
||
{
|
||
m_seAppBuffer->Append("/Tx BMC\n");
|
||
}
|
||
m_seAppBuffer->Append("q\n");
|
||
m_seAppBuffer->Append("BT\n");
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
if ( bMultiline )
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> nComb <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
double dWMax = m_dMaxX - m_dMinX - 2 * dBorderWidth - 4;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||
if ( 0 == dFontSize )
|
||
{
|
||
for ( dFontSize = 20; dFontSize > 1; --dFontSize )
|
||
{
|
||
dY = m_dMaxY - m_dMinY;
|
||
double dMaxLineWidth = 0;
|
||
i = 0;
|
||
while ( i < seText->GetLength() )
|
||
{
|
||
GetNextLine( seText, i, pFont, dFontSize, dWMax, &j, &dWidth, &k);
|
||
if ( dWidth > dMaxLineWidth )
|
||
{
|
||
dMaxLineWidth = dWidth;
|
||
}
|
||
i = k;
|
||
dY -= dFontSize;
|
||
}
|
||
|
||
if ( dY >= 0.33 * dFontSize )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if ( nTfPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTfPos + 1 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dFontSize);
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Y
|
||
// (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Td)
|
||
dY = m_dMaxY - m_dMinY;
|
||
|
||
// Font Matrix
|
||
if ( nTmPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTmPos + 4);
|
||
seToken->Clear();
|
||
seToken->Append('0');
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTmPos + 5);
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dY);
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> DA-string
|
||
if ( pListDA )
|
||
{
|
||
for (i = 0; i < pListDA->GetLength(); ++i)
|
||
{
|
||
m_seAppBuffer->Append((StringExt *)pListDA->GetByIndex(i))->Append(' ');
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> Font Matrix (<28><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20> DA-string)
|
||
if ( nTmPos < 0 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("1 0 0 1 0 {0:.2f} Tm\n", dY);
|
||
}
|
||
|
||
i = 0;
|
||
double dPrevX = 0;
|
||
while ( i < seText->GetLength() )
|
||
{
|
||
GetNextLine( seText, i, pFont, dFontSize, dWMax, &j, &dWidth, &k);
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
switch ( nQuadding )
|
||
{
|
||
case fieldQuadLeft:
|
||
default:
|
||
dX = dBorderWidth + 2;
|
||
break;
|
||
case fieldQuadCenter:
|
||
dX = (m_dMaxX - m_dMinX - dWidth) / 2;
|
||
break;
|
||
case fieldQuadRight:
|
||
dX = m_dMaxX - m_dMinX - dBorderWidth - 2 - dWidth;
|
||
break;
|
||
}
|
||
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} Td\n", dX - dPrevX, -dFontSize);
|
||
m_seAppBuffer->Append('(');
|
||
for (; i < j; ++i)
|
||
{
|
||
nChar = seText->GetAt(i) & 0xff;
|
||
if ( nChar == '(' || nChar == ')' || nChar == '\\' )
|
||
{
|
||
m_seAppBuffer->Append('\\');
|
||
m_seAppBuffer->Append(nChar);
|
||
}
|
||
else if ( nChar < 0x20 || nChar >= 0x80 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("\\{0:03o}", nChar);
|
||
}
|
||
else
|
||
{
|
||
m_seAppBuffer->Append(nChar);
|
||
}
|
||
}
|
||
m_seAppBuffer->Append(") Tj\n");
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
i = k;
|
||
dPrevX = dX;
|
||
}
|
||
|
||
}
|
||
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
{
|
||
if ( nComb > 0 )
|
||
{
|
||
dWidth = (m_dMaxX - m_dMinX - 2 * dBorderWidth) / nComb;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||
if ( 0 == dFontSize )
|
||
{
|
||
dFontSize = m_dMaxY - m_dMinY - 2 * dBorderWidth;
|
||
if ( dWidth < dFontSize )
|
||
{
|
||
dFontSize = dWidth;
|
||
}
|
||
dFontSize = floor(dFontSize);
|
||
if ( nTfPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTfPos + 1 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dFontSize);
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
switch ( nQuadding )
|
||
{
|
||
case fieldQuadLeft:
|
||
default:
|
||
dX = dBorderWidth + 2;
|
||
break;
|
||
case fieldQuadCenter:
|
||
dX = dBorderWidth + 2 + 0.5 * (nComb - seText->GetLength()) * dWidth;
|
||
break;
|
||
case fieldQuadRight:
|
||
dX = dBorderWidth + 2 + (nComb - seText->GetLength()) * dWidth;
|
||
break;
|
||
}
|
||
dY = 0.5 * (m_dMaxY - m_dMinY) - 0.4 * dFontSize;
|
||
|
||
// Font Matrix
|
||
if ( nTmPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTmPos + 4 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dX);
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTmPos + 5 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dY);
|
||
}
|
||
|
||
// DA-string
|
||
if ( pListDA )
|
||
{
|
||
for (i = 0; i < pListDA->GetLength(); ++i)
|
||
{
|
||
m_seAppBuffer->Append((StringExt *)pListDA->GetByIndex(i))->Append(' ');
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> Font Matrix (<28><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20> DA-string)
|
||
if ( nTmPos < 0 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("1 0 0 1 {0:.2f} {1:.2f} Tm\n", dX, dY);
|
||
}
|
||
|
||
// write the text string
|
||
//~ this should center (instead of left-justify) each character within
|
||
//~ its comb cell
|
||
for ( i = 0; i < seText->GetLength(); ++i )
|
||
{
|
||
if ( i > 0 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("{0:.2f} 0 Td\n", dWidth);
|
||
}
|
||
m_seAppBuffer->Append('(');
|
||
nChar = seText->GetAt(i) & 0xff;
|
||
if ( nChar == '(' || nChar == ')' || nChar == '\\' )
|
||
{
|
||
m_seAppBuffer->Append('\\');
|
||
m_seAppBuffer->Append(nChar);
|
||
}
|
||
else if ( nChar < 0x20 || nChar >= 0x80 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("{0:.2f} 0 Td\n", dWidth);
|
||
}
|
||
else
|
||
{
|
||
m_seAppBuffer->Append(nChar);
|
||
}
|
||
m_seAppBuffer->Append(") Tj\n");
|
||
}
|
||
}
|
||
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (non-comb)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if ( pFont && !pFont->IsCIDFont() )
|
||
{
|
||
dWidth = 0;
|
||
for ( i = 0; i < seText->GetLength(); ++i )
|
||
{
|
||
dWidth += ( (Gr8BitFont *)pFont )->GetWidth( seText->GetAt(i) );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
dWidth = seText->GetLength() * 0.5;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||
if ( 0 == dFontSize )
|
||
{
|
||
dFontSize = m_dMaxY - m_dMinY - 2 * dBorderWidth;
|
||
double dTempFontSize = (m_dMaxX - m_dMinX - 4 - 2 * dBorderWidth) / dWidth;
|
||
if ( dTempFontSize < dFontSize )
|
||
{
|
||
dFontSize = dTempFontSize;
|
||
}
|
||
dFontSize = floor(dFontSize);
|
||
if ( nTfPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTfPos + 1 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dFontSize);
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
dWidth *= dFontSize;
|
||
switch ( nQuadding )
|
||
{
|
||
case fieldQuadLeft:
|
||
default:
|
||
dX = dBorderWidth + 2;
|
||
break;
|
||
case fieldQuadCenter:
|
||
dX = (m_dMaxX - m_dMinX - dWidth) / 2;
|
||
break;
|
||
case fieldQuadRight:
|
||
dX = m_dMaxX - m_dMinX - dBorderWidth - 2 - dWidth;
|
||
break;
|
||
}
|
||
dY = 0.5 * (m_dMaxY - m_dMinY) - 0.4 * dFontSize;
|
||
|
||
// Font Matrix
|
||
if ( nTmPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTmPos + 4 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dX);
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTmPos + 5 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dY);
|
||
}
|
||
|
||
// DA-string
|
||
if ( pListDA )
|
||
{
|
||
for ( i = 0; i < pListDA->GetLength(); ++i)
|
||
{
|
||
m_seAppBuffer->Append((StringExt *)pListDA->GetByIndex(i))->Append(' ');
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> Font Matrix (<28><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20> DA-string)
|
||
if ( nTmPos < 0 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("1 0 0 1 {0:.2f} {1:.2f} Tm\n", dX, dY);
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
m_seAppBuffer->Append('(');
|
||
for ( i = 0; i < seText->GetLength(); ++i )
|
||
{
|
||
nChar = seText->GetAt(i) & 0xff;
|
||
if ( nChar == '(' || nChar == ')' || nChar == '\\' )
|
||
{
|
||
m_seAppBuffer->Append('\\');
|
||
m_seAppBuffer->Append(nChar);
|
||
}
|
||
else if ( nChar < 0x20 || nChar >= 0x80 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("\\{0:03o}", nChar);
|
||
}
|
||
else
|
||
{
|
||
m_seAppBuffer->Append(nChar);
|
||
}
|
||
}
|
||
m_seAppBuffer->Append(") Tj\n");
|
||
}
|
||
}
|
||
|
||
m_seAppBuffer->Append("ET\n");
|
||
m_seAppBuffer->Append("Q\n");
|
||
|
||
if ( bTextField )
|
||
{
|
||
m_seAppBuffer->Append("EMC\n");
|
||
}
|
||
|
||
if ( pListDA )
|
||
{
|
||
DeleteCList( pListDA, StringExt);
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> Field.
|
||
void Annot::DrawListBox(StringExt **ppText, BOOL *pSelection, int nOptionsCount, int nTopIndex, StringExt *seDA, GrFontDict *pFontDict, BOOL bQuadding)
|
||
{
|
||
CList *pListDA;
|
||
StringExt *seToken;
|
||
int i, j;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Default appearance string
|
||
int nTfPos = -1, nTmPos = -1;
|
||
if ( seDA )
|
||
{
|
||
pListDA = new CList();
|
||
i = 0;
|
||
while ( i < seDA->GetLength() )
|
||
{
|
||
while ( i < seDA->GetLength() && Lexer::IsSpace(seDA->GetAt(i)) )
|
||
{
|
||
++i;
|
||
}
|
||
if ( i < seDA->GetLength() )
|
||
{
|
||
for (j = i + 1; j < seDA->GetLength() && !Lexer::IsSpace(seDA->GetAt(j)); ++j) ;
|
||
pListDA->Append(new StringExt(seDA, i, j - i));
|
||
i = j;
|
||
}
|
||
}
|
||
for ( i = 2; i < pListDA->GetLength(); ++i )
|
||
{
|
||
if ( i >= 2 && !((StringExt *)pListDA->GetByIndex(i))->Compare("Tf") )
|
||
{
|
||
nTfPos = i - 2;
|
||
}
|
||
else if ( i >= 6 && !((StringExt *)pListDA->GetByIndex(i))->Compare("Tm") )
|
||
{
|
||
nTmPos = i - 6;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pListDA = NULL;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
GrFont *pFont = NULL;
|
||
double dFontSize = 0;
|
||
if ( nTfPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex(nTfPos);
|
||
if ( seToken->GetLength() >= 1 && seToken->GetAt(0) == '/' )
|
||
{
|
||
if ( !pFontDict || !(pFont = pFontDict->Search(seToken->GetBuffer() + 1)) )
|
||
{
|
||
// TO DO: Error "Unknown font in field's DA string"
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// TO DO: Error "Invalid font name in 'Tf' operator in field's DA string"
|
||
}
|
||
seToken = (StringExt *)pListDA->GetByIndex(nTfPos + 1);
|
||
dFontSize = atof(seToken->GetBuffer());
|
||
}
|
||
else
|
||
{
|
||
// TO DO: Error "Missing 'Tf' operator in field's DA string"
|
||
}
|
||
|
||
// Border width
|
||
double dBorder = m_pBorderStyle->GetWidth();
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
double dWidth = 0;
|
||
if ( 0 == dFontSize )
|
||
{
|
||
double dMaxW = 0;
|
||
for ( i = 0; i < nOptionsCount; ++i )
|
||
{
|
||
if ( pFont && !pFont->IsCIDFont() )
|
||
{
|
||
dWidth = 0;
|
||
for ( j = 0; j < ppText[i]->GetLength(); ++j )
|
||
{
|
||
dWidth += ((Gr8BitFont *)pFont)->GetWidth(ppText[i]->GetAt(j));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
dWidth = ppText[i]->GetLength() * 0.5;
|
||
}
|
||
if ( dWidth > dMaxW )
|
||
{
|
||
dMaxW = dWidth;
|
||
}
|
||
}
|
||
dFontSize = m_dMaxY - m_dMinY - 2 * dBorder;
|
||
double dFontSize2 = (m_dMaxX - m_dMinX - 4 - 2 * dBorder) / dMaxW;
|
||
|
||
if ( dFontSize2 < dFontSize )
|
||
{
|
||
dFontSize = dFontSize2;
|
||
}
|
||
dFontSize = floor(dFontSize);
|
||
|
||
if ( nTfPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex(nTfPos + 1);
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dFontSize);
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
double dY = m_dMaxY - m_dMinY - 1.1 * dFontSize;
|
||
|
||
for ( i = nTopIndex; i < nOptionsCount; ++i )
|
||
{
|
||
m_seAppBuffer->Append("q\n");
|
||
|
||
// Background
|
||
if ( pSelection[i] )
|
||
{
|
||
m_seAppBuffer->Append("0 g f\n");
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} re f\n", dBorder, dY - 0.2 * dFontSize, m_dMaxX - m_dMinX - 2 * dBorder, 1.1 * dFontSize);
|
||
}
|
||
|
||
m_seAppBuffer->Append("BT\n");
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if ( pFont && !pFont->IsCIDFont() )
|
||
{
|
||
dWidth = 0;
|
||
for ( j = 0; j < ppText[i]->GetLength(); ++j )
|
||
{
|
||
dWidth += ((Gr8BitFont *)pFont)->GetWidth(ppText[i]->GetAt(j));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
dWidth = ppText[i]->GetLength() * 0.5;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
double dX = 0;
|
||
dWidth *= dFontSize;
|
||
switch ( bQuadding )
|
||
{
|
||
case fieldQuadLeft:
|
||
default:
|
||
dX = dBorder + 2;
|
||
break;
|
||
case fieldQuadCenter:
|
||
dX = (m_dMaxX - m_dMinX - dWidth) / 2;
|
||
break;
|
||
case fieldQuadRight:
|
||
dX = m_dMaxX - m_dMinX - dBorder - 2 - dWidth;
|
||
break;
|
||
}
|
||
|
||
// Font Matrix
|
||
if ( nTmPos >= 0 )
|
||
{
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTmPos + 4 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dX);
|
||
seToken = (StringExt *)pListDA->GetByIndex( nTmPos + 5 );
|
||
seToken->Clear();
|
||
seToken->AppendFormat("{0:.2f}", dY);
|
||
}
|
||
|
||
// DA string
|
||
if ( pListDA )
|
||
{
|
||
for (j = 0; j < pListDA->GetLength(); ++j)
|
||
{
|
||
m_seAppBuffer->Append((StringExt *)pListDA->GetByIndex(j))->Append(' ');
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> Font Matrix (<28><><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DA-string)
|
||
if ( nTmPos < 0 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("1 0 0 1 {0:.2f} {1:.2f} Tm\n", dX, dY);
|
||
}
|
||
|
||
if ( pSelection[i] )
|
||
{
|
||
m_seAppBuffer->Append("1 g\n");
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
m_seAppBuffer->Append('(');
|
||
for ( j = 0; j < ppText[i]->GetLength(); ++j )
|
||
{
|
||
int nChar = ppText[i]->GetAt(j) & 0xff;
|
||
if ( nChar == '(' || nChar == ')' || nChar == '\\' )
|
||
{
|
||
m_seAppBuffer->Append('\\');
|
||
m_seAppBuffer->Append(nChar);
|
||
}
|
||
else if ( nChar < 0x20 || nChar >= 0x80 )
|
||
{
|
||
m_seAppBuffer->AppendFormat("\\{0:03o}", nChar);
|
||
}
|
||
else
|
||
{
|
||
m_seAppBuffer->Append(nChar);
|
||
}
|
||
}
|
||
m_seAppBuffer->Append(") Tj\n");
|
||
|
||
m_seAppBuffer->Append("ET\n");
|
||
m_seAppBuffer->Append("Q\n");
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
dY -= 1.1 * dFontSize;
|
||
}
|
||
|
||
if ( pListDA )
|
||
{
|
||
DeleteCList( pListDA, StringExt );
|
||
}
|
||
}
|
||
|
||
void Annot::GetNextLine(StringExt *seText, int nStart, GrFont *pFont, double dFontSize, double dMaxW, int *pEnd, double *pWidth, int *pNext)
|
||
{
|
||
double dWidth = 0, dTempWidth;
|
||
int j, k;
|
||
|
||
|
||
for ( j = nStart; j < seText->GetLength() && dWidth <= dMaxW; ++j )
|
||
{
|
||
int nChar = seText->GetAt(j) & 0xff;
|
||
if ( nChar == 0x0a || nChar == 0x0d )
|
||
{
|
||
break;
|
||
}
|
||
if ( pFont && !pFont->IsCIDFont() )
|
||
{
|
||
dTempWidth = ((Gr8BitFont *)pFont)->GetWidth(nChar) * dFontSize;
|
||
}
|
||
else
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
dTempWidth = 0.5 * dFontSize;
|
||
}
|
||
dWidth += dTempWidth;
|
||
}
|
||
if ( dWidth > dMaxW )
|
||
{
|
||
for ( k = j; k > nStart && seText->GetAt(k - 1) != ' '; --k );
|
||
for ( ; k > nStart && seText->GetAt(k - 1) == ' '; --k );
|
||
if ( k > nStart )
|
||
{
|
||
j = k;
|
||
}
|
||
|
||
if ( j == nStart )
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
j = nStart + 1;
|
||
}
|
||
}
|
||
*pEnd = j;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
dWidth = 0;
|
||
for ( k = nStart; k < j; ++k )
|
||
{
|
||
if ( pFont && !pFont->IsCIDFont() )
|
||
{
|
||
dTempWidth = ((Gr8BitFont *)pFont)->GetWidth(seText->GetAt(k)) * dFontSize;
|
||
}
|
||
else
|
||
{
|
||
dTempWidth = 0.5 * dFontSize;
|
||
}
|
||
dWidth += dTempWidth;
|
||
}
|
||
*pWidth = dWidth;
|
||
|
||
while (j < seText->GetLength() && seText->GetAt(j) == ' ')
|
||
{
|
||
++j;
|
||
}
|
||
if ( j < seText->GetLength() && seText->GetAt(j) == 0x0d )
|
||
{
|
||
++j;
|
||
}
|
||
if ( j < seText->GetLength() && seText->GetAt(j) == 0x0a )
|
||
{
|
||
++j;
|
||
}
|
||
*pNext = j;
|
||
}
|
||
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
// = (4 * (sqrt(2) - 1) / 3) * r
|
||
#define Kappa 0.55228475
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>. (dX, dY) - <20><><EFBFBD><EFBFBD><EFBFBD>, dRad - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
// bFill - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
|
||
void Annot::DrawCircle(double dX, double dY, double dRad, BOOL bFill)
|
||
{
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} m\n", dX + dRad, dY);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", dX + dRad, dY + Kappa * dRad, dX + Kappa * dRad, dY + dRad, dX, dY + dRad);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", dX - Kappa * dRad, dY + dRad, dX - dRad, dY + Kappa * dRad, dX - dRad, dY );
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", dX - dRad, dY - Kappa * dRad, dX - Kappa * dRad, dY - dRad, dX, dY - dRad);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", dX + Kappa * dRad, dY - dRad, dX + dRad, dY - Kappa * dRad, dX + dRad, dY );
|
||
m_seAppBuffer->Append( bFill ? "f\n" : "s\n" );
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>. (dX, dY) - <20><><EFBFBD><EFBFBD><EFBFBD>, dRad - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
void Annot::DrawCircleTopLeft(double dX, double dY, double dRad)
|
||
{
|
||
double dRad2 = dRad / sqrt(2.0);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} m\n", dX + dRad2, dY + dRad2);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", dX + (1 - Kappa) * dRad2, dY + (1 + Kappa) * dRad2, dX - (1 - Kappa) * dRad2, dY + (1 + Kappa) * dRad2, dX - dRad2, dY + dRad2);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", dX - (1 + Kappa) * dRad2, dY + (1 - Kappa) * dRad2, dX - (1 + Kappa) * dRad2, dY - (1 - Kappa) * dRad2, dX - dRad2, dY - dRad2);
|
||
m_seAppBuffer->Append("S\n");
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>. (dX, dY) - <20><><EFBFBD><EFBFBD><EFBFBD>, dRad - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||
void Annot::DrawCircleBottomRight(double dX, double dY, double dRad)
|
||
{
|
||
double dRad2 = dRad / sqrt(2.0);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} m\n", dX - dRad2, dY - dRad2);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", dX - (1 - Kappa) * dRad2, dY - (1 + Kappa) * dRad2, dX + (1 - Kappa) * dRad2, dY - (1 + Kappa) * dRad2, dX + dRad2, dY - dRad2);
|
||
m_seAppBuffer->AppendFormat("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", dX + (1 + Kappa) * dRad2, dY - (1 - Kappa) * dRad2, dX + (1 + Kappa) * dRad2, dY + (1 - Kappa) * dRad2, dX + dRad2, dY + dRad2);
|
||
m_seAppBuffer->Append("S\n");
|
||
}
|
||
|
||
Object *Annot::FieldLookup(Dict *pField, char *sKey, Object *pObject)
|
||
{
|
||
Dict *pDict = pField;
|
||
if ( !pDict->Search(sKey, pObject)->IsNull() )
|
||
{
|
||
return pObject;
|
||
}
|
||
pObject->Free();
|
||
|
||
Object oParent;
|
||
if ( pDict->Search("Parent", &oParent)->IsDict() )
|
||
{
|
||
FieldLookup( oParent.GetDict(), sKey, pObject);
|
||
}
|
||
else
|
||
{
|
||
pObject->InitNull();
|
||
}
|
||
oParent.Free();
|
||
return pObject;
|
||
}
|
||
|
||
void Annot::Draw(Graphics *pGraphics, BOOL bPrinting)
|
||
{
|
||
// Flags
|
||
if ( (m_nFlags & annotFlagHidden) || (bPrinting && !(m_nFlags & annotFlagPrint)) || (!bPrinting && (m_nFlags & annotFlagNoView)) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
// Appearance stream
|
||
BOOL bIsLink = m_seType && !m_seType->Compare("Link");
|
||
|
||
Object oTemp;
|
||
m_oAppearance.Fetch( m_pXref, &oTemp);
|
||
pGraphics->DrawAnnotation( &oTemp, (bIsLink ? m_pBorderStyle : (AnnotBorderStyle *)NULL), m_dMinX, m_dMinY, m_dMaxX, m_dMaxY);
|
||
oTemp.Free();
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
// Annots
|
||
//-------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
Annots::Annots(GlobalParams *pGlobalParams, XRef *pXref, Catalog *pCatalog, Object *pAnnotsObject)
|
||
{
|
||
m_pGlobalParams = pGlobalParams;
|
||
|
||
Annot *pAnnot = NULL;
|
||
Ref oRef;
|
||
|
||
m_ppAnnots = NULL;
|
||
int nSize = 0;
|
||
m_nAnnotsCount = 0;
|
||
|
||
Dict *pAcroForm = (pCatalog->GetAcroForm()->IsDict() ? pCatalog->GetAcroForm()->GetDict() : NULL);
|
||
if ( pAnnotsObject->IsArray() )
|
||
{
|
||
for ( int nIndex = 0; nIndex < pAnnotsObject->ArrayGetLength(); ++nIndex )
|
||
{
|
||
Object oTemp;
|
||
if ( pAnnotsObject->ArrayGetCopy(nIndex, &oTemp)->IsRef() )
|
||
{
|
||
oRef = oTemp.GetRef();
|
||
oTemp.Free();
|
||
pAnnotsObject->ArrayGet(nIndex, &oTemp);
|
||
}
|
||
else
|
||
{
|
||
oRef.nNum = oRef.nGen = -1;
|
||
}
|
||
if ( oTemp.IsDict() )
|
||
{
|
||
pAnnot = new Annot( m_pGlobalParams, pXref, pAcroForm, oTemp.GetDict(), &oRef );
|
||
if ( pAnnot->CheckValidation() )
|
||
{
|
||
if ( m_nAnnotsCount >= nSize )
|
||
{
|
||
nSize += 16;
|
||
m_ppAnnots = (Annot **)MemUtilsReallocArray(m_ppAnnots, nSize, sizeof(Annot *));
|
||
}
|
||
m_ppAnnots[m_nAnnotsCount++] = pAnnot;
|
||
}
|
||
else
|
||
{
|
||
delete pAnnot;
|
||
}
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
}
|
||
}
|
||
|
||
Annots::~Annots()
|
||
{
|
||
for ( int nIndex = 0; nIndex < m_nAnnotsCount; ++nIndex )
|
||
{
|
||
delete m_ppAnnots[nIndex];
|
||
}
|
||
MemUtilsFree( m_ppAnnots );
|
||
}
|
||
|
||
void Annots::GenerateAppearances(Dict *pAcroForm)
|
||
{
|
||
Ref oRef;
|
||
|
||
Object oField;
|
||
if ( pAcroForm->Search("Fields", &oField)->IsArray() )
|
||
{
|
||
for ( int nIndex = 0; nIndex < oField.ArrayGetLength(); ++nIndex )
|
||
{
|
||
Object oItem;
|
||
if ( oField.ArrayGetCopy(nIndex, &oItem)->IsRef() )
|
||
{
|
||
oRef = oItem.GetRef();
|
||
oItem.Free();
|
||
oField.ArrayGet(nIndex, &oItem);
|
||
}
|
||
else
|
||
{
|
||
oRef.nNum = oRef.nGen = -1;
|
||
}
|
||
if ( oItem.IsDict() )
|
||
{
|
||
ScanFieldAppearances( oItem.GetDict(), &oRef, NULL, pAcroForm);
|
||
}
|
||
oItem.Free();
|
||
}
|
||
}
|
||
oField.Free();
|
||
}
|
||
|
||
void Annots::ScanFieldAppearances(Dict *pNode, Ref *pRef, Dict *pParent, Dict *pAcroForm)
|
||
{
|
||
Annot *pAnnot = NULL;
|
||
Ref oRef2;
|
||
|
||
Object oNodeItem;
|
||
if ( pNode->Search("Kids", &oNodeItem)->IsArray() )
|
||
{
|
||
for ( int nIndex = 0; nIndex < oNodeItem.ArrayGetLength(); ++nIndex )
|
||
{
|
||
Object oTemp;
|
||
if ( oNodeItem.ArrayGetCopy(nIndex, &oTemp)->IsRef() )
|
||
{
|
||
oRef2 = oTemp.GetRef();
|
||
oTemp.Free();
|
||
oNodeItem.ArrayGet(nIndex, &oTemp);
|
||
}
|
||
else
|
||
{
|
||
oRef2.nNum = oRef2.nGen = -1;
|
||
}
|
||
if ( oTemp.IsDict() )
|
||
{
|
||
ScanFieldAppearances( oTemp.GetDict(), &oRef2, pNode, pAcroForm);
|
||
}
|
||
oTemp.Free();
|
||
}
|
||
oNodeItem.Free();
|
||
return;
|
||
}
|
||
oNodeItem.Free();
|
||
|
||
if ( (pAnnot = FindAnnot(pRef)) )
|
||
{
|
||
pNode->SearchAndCopy("Parent", &oNodeItem);
|
||
if ( !pParent || !oNodeItem.IsNull() )
|
||
{
|
||
pAnnot->GenerateFieldAppearance( pNode, pNode, pAcroForm );
|
||
}
|
||
else
|
||
{
|
||
pAnnot->GenerateFieldAppearance( pParent, pNode, pAcroForm );
|
||
}
|
||
oNodeItem.Free();
|
||
}
|
||
}
|
||
|
||
Annot *Annots::FindAnnot(Ref *pRef)
|
||
{
|
||
for ( int nIndex = 0; nIndex < m_nAnnotsCount; ++nIndex)
|
||
{
|
||
if ( m_ppAnnots[nIndex]->Match(pRef) )
|
||
{
|
||
return m_ppAnnots[nIndex];
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|