Create DrawCheckBoxCircle

This commit is contained in:
Svetlana Kulikova
2025-03-31 15:27:17 +03:00
parent d2b5299b99
commit 1d9230b731
5 changed files with 538 additions and 322 deletions

View File

@ -2387,7 +2387,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF
pButtonWidget->SetV(wsValue);
}
std::wstring wsStyleValue = pButtonWidget->SetStyle(pPrB->GetStyle());
pButtonWidget->SetStyle(pPrB->GetStyle());
// ВНЕШНИЙ ВИД
// Если изменился текущий внешний вид
@ -2398,6 +2398,8 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF
return S_OK;
}
pButtonWidget->SetAP();
/*
put_FontName(wsFontName);
put_FontStyle(nStyle);
put_FontSize(dFontSize);
@ -2415,6 +2417,7 @@ HRESULT CPdfWriter::AddAnnotField(NSFonts::IApplicationFonts* pAppFonts, CAnnotF
double dBaseLine = dY2 - dY1 - dFontSize - dMargin;
pButtonWidget->SetAP(wsStyleValue, NULL, 0, 0, dBaseLine, NULL, NULL);
}
*/
}
}
else if (oInfo.IsTextWidget())

View File

@ -71,6 +71,10 @@ namespace PdfWriter
{
"Check", "Checkmark", "Circle", "Comment", "Cross", "CrossHairs", "Help", "Insert", "Key", "NewParagraph", "Note", "Paragraph", "RightArrow", "RightPointer", "Star", "UpArrow", "UpLeftArrow"
};
const static char* c_sCheckBoxStyleNames[] =
{
"4", "8", "u", "l", "H", "n"
};
void AddToVectorD(CDictObject* pObj, const std::string& sName, const std::vector<double>& arrV)
{
@ -168,6 +172,7 @@ namespace PdfWriter
m_pAppearance = NULL;
m_pDocument = NULL;
m_pXref = pXref;
m_oBorder.bHave = false;
Add("Type", "Annot");
Add("Subtype", c_sAnnotTypeNames[(int)eType]);
@ -766,299 +771,12 @@ namespace PdfWriter
{
AddToVectorD(this, "IC", arrIC);
}
void AdjustLineEndpoint(ELineEndType nType, double x, double y, double dx, double dy, double w, double& tx, double& ty)
{
tx = x;
ty = y;
switch (nType)
{
case ELineEndType::ClosedArrow:
case ELineEndType::OpenArrow:
case ELineEndType::Diamond:
{
tx += w * dx;
if ((dx > 0.001 && dy > 0) || (dx < -0.001 && dy < 0))
ty += w * dy;
break;
}
case ELineEndType::Square:
case ELineEndType::Circle:
{
if ((dx > -0.02 && dy < 0.02) || (dx < 0.02 && dy > -0.02))
tx += w * dx;
break;
}
case ELineEndType::Slash:
case ELineEndType::Butt:
case ELineEndType::ROpenArrow:
case ELineEndType::RClosedArrow:
case ELineEndType::None:
default:
break;
}
}
void SreamWriteXYMove(CStream* pStream, double x, double y)
{
pStream->WriteReal(x);
pStream->WriteChar(' ');
pStream->WriteReal(y);
pStream->WriteStr(" m\012");
}
void SreamWriteXYLine(CStream* pStream, double x, double y)
{
pStream->WriteReal(x);
pStream->WriteChar(' ');
pStream->WriteReal(y);
pStream->WriteStr(" l\012");
}
void SreamWriteXYCurve(CStream* pStream, double x1, double y1, double x2, double y2, double x3, double y3)
{
pStream->WriteReal(x1);
pStream->WriteChar(' ');
pStream->WriteReal(y1);
pStream->WriteChar(' ');
pStream->WriteReal(x2);
pStream->WriteChar(' ');
pStream->WriteReal(y2);
pStream->WriteChar(' ');
pStream->WriteReal(x3);
pStream->WriteChar(' ');
pStream->WriteReal(y3);
pStream->WriteStr(" c\012");
}
void StreamWriteRect(CStream* pStream, double x1, double y1, double x2, double y2)
{
pStream->WriteReal(x1);
pStream->WriteChar(' ');
pStream->WriteReal(y1);
pStream->WriteChar(' ');
pStream->WriteReal(x2);
pStream->WriteChar(' ');
pStream->WriteReal(y2);
pStream->WriteStr(" re\012");
}
void SreamWriteCircle(CStream* pStream, double cx, double cy, double r)
{
double bezierCircle = 0.55228475 * r;
SreamWriteXYMove(pStream, cx + r, cy);
SreamWriteXYCurve(pStream, cx + r, cy + bezierCircle, cx + bezierCircle, cy + r, cx, cy + r);
SreamWriteXYCurve(pStream, cx - bezierCircle, cy + r, cx - r, cy + bezierCircle, cx - r, cy);
SreamWriteXYCurve(pStream, cx - r, cy - bezierCircle, cx - bezierCircle, cy - r, cx, cy - r);
SreamWriteXYCurve(pStream, cx + bezierCircle, cy - r, cx + r, cy - bezierCircle, cx + r, cy);
}
void DrawArrow(CStream* pStream, ELineEndType nType, double x, double y, double dx, double dy, double w)
{
double lineEndSize1 = 3, pi = 3.14159265358979323846;
switch (nType)
{
case ELineEndType::Butt:
{
w *= lineEndSize1;
SreamWriteXYMove(pStream, x + w * dy, y - w * dx);
SreamWriteXYLine(pStream, x - w * dy, y + w * dx);
pStream->WriteStr("S\012");
break;
}
case ELineEndType::Circle:
{
SreamWriteCircle(pStream, x, y, w * lineEndSize1);
pStream->WriteStr("h\012B\012");
break;
}
case ELineEndType::Diamond:
{
w *= lineEndSize1;
SreamWriteXYMove(pStream, x - w, y);
SreamWriteXYLine(pStream, x, y + w);
SreamWriteXYLine(pStream, x + w, y);
SreamWriteXYLine(pStream, x, y - w);
pStream->WriteStr("b\012");
break;
}
case ELineEndType::OpenArrow:
case ELineEndType::ClosedArrow:
{
w *= lineEndSize1 * lineEndSize1;
double d32 = pi * 32.0 / 180.0;
double d28 = pi * 28.0 / 180.0;
if ((dx > 0.001 && dy < 0) || (dx < -0.001 && dy > 0))
{
SreamWriteXYMove(pStream, x + w * cos(d32) * dx + w * sin(d32) * dy, y + w * cos(d32) * dy - w * sin(d32) * dx);
SreamWriteXYLine(pStream, x, y);
SreamWriteXYLine(pStream, x + w * cos(d28) * dx - w * sin(d28) * dy, y + w * cos(d28) * dy + w * sin(d28) * dx);
}
else
{
double dCos = w * cos(pi / 6.0);
double dSin = w * sin(pi / 6.0);
SreamWriteXYMove(pStream, x + dCos * dx + dSin * dy, y + dCos * dy - dSin * dx);
SreamWriteXYLine(pStream, x, y);
SreamWriteXYLine(pStream, x + dCos * dx - dSin * dy, y + dCos * dy + dSin * dx);
}
pStream->WriteStr(nType == ELineEndType::OpenArrow ? "S\012" : "b\012");
break;
}
case ELineEndType::ROpenArrow:
case ELineEndType::RClosedArrow:
{
x -= cos(pi / 18.0) * dx * w;
y -= cos(pi / 18.0) * dy * w;
w *= lineEndSize1 * lineEndSize1;
double dCos = w * cos(pi / 6.0);
double dSin = w * sin(pi / 6.0);
SreamWriteXYMove(pStream, x - dCos * dx + dSin * dy, y - dCos * dy - dSin * dx);
SreamWriteXYLine(pStream, x, y);
SreamWriteXYLine(pStream, x - dCos * dx - dSin * dy, y - dCos * dy + dSin * dx);
pStream->WriteStr(nType == ELineEndType::ROpenArrow ? "S\012" : "b\012");
break;
}
case ELineEndType::Slash:
{
w *= lineEndSize1 * lineEndSize1;
double dCos = w * cos(pi / 6.0);
double dSin = w * sin(pi / 6.0);
SreamWriteXYMove(pStream, x + dCos * dy - dSin * dx, y - dCos * dx - dSin * dy);
SreamWriteXYLine(pStream, x - dCos * dy + dSin * dx, y + dCos * dx + dSin * dy);
pStream->WriteStr("S\012");
break;
}
case ELineEndType::Square:
{
w *= lineEndSize1;
pStream->WriteReal(x - w);
pStream->WriteChar(' ');
pStream->WriteReal(y - w);
pStream->WriteChar(' ');
pStream->WriteReal(w * 2);
pStream->WriteChar(' ');
pStream->WriteReal(w * 2);
pStream->WriteStr(" re\012");
pStream->WriteStr("B\012");
break;
}
case ELineEndType::None:
default:
{
break;
}
}
}
void DrawLineArrow(CStream* pStream, double dBorderSize, double x1, double y1, double x2, double y2, ELineEndType nLE1, ELineEndType nLE2, double dLL = 0, double dLLO = 0, double dLLE = 0)
{
double dDX = x2 - x1;
double dDY = y2 - y1;
double dLen = sqrt(dDX * dDX + dDY * dDY);
if (dLen > 0)
{
dDX /= dLen;
dDY /= dLen;
}
double lx1, ly1, lx2, ly2;
double ax1, ay1, ax2, ay2;
double bx1, by1, bx2, by2;
if (dLL != 0)
{
ax1 = x1 + dLLO * dDY;
ay1 = y1 - dLLO * dDX;
lx1 = ax1 + dLL * dDY;
ly1 = ay1 - dLL * dDX;
bx1 = lx1 + dLLE * dDY;
by1 = ly1 - dLLE * dDX;
ax2 = x2 + dLLO * dDY;
ay2 = y2 - dLLO * dDX;
lx2 = ax2 + dLL * dDY;
ly2 = ay2 - dLL * dDX;
bx2 = lx2 + dLLE * dDY;
by2 = ly2 - dLLE * dDX;
}
else
{
lx1 = x1;
ly1 = y1;
lx2 = x2;
ly2 = y2;
ax1 = ay1 = ax2 = ay2 = 0;
bx1 = by1 = bx2 = by2 = 0;
}
double tx1, ty1, tx2, ty2;
AdjustLineEndpoint(nLE1, lx1, ly1, dDX, dDY, dBorderSize, tx1, ty1);
AdjustLineEndpoint(nLE2, lx2, ly2, -dDX, -dDY, dBorderSize, tx2, ty2);
if (dLL)
{
SreamWriteXYMove(pStream, ax1, ay1);
SreamWriteXYLine(pStream, bx1, by1);
SreamWriteXYMove(pStream, ax2, ay2);
SreamWriteXYLine(pStream, bx2, by2);
}
SreamWriteXYMove(pStream, tx1, ty1);
SreamWriteXYLine(pStream, tx2, ty2);
pStream->WriteStr("S\012");
DrawArrow(pStream, nLE1, tx1, ty1, dDX, dDY, dBorderSize);
DrawArrow(pStream, nLE2, tx2, ty2, -dDX, -dDY, dBorderSize);
}
void CLineAnnotation::SetAP()
{
CAnnotAppearance* pAppearance = new CAnnotAppearance(m_pXref, this);
Add("AP", pAppearance);
CAnnotAppearanceObject* pNormal = pAppearance->GetNormal();
CStream* pStream = pNormal->GetStream();
pNormal->AddBBox(GetRect().fLeft, GetRect().fBottom, GetRect().fRight, GetRect().fTop);
pNormal->AddMatrix(1, 0, 0, 1, -GetRect().fLeft, -GetRect().fBottom);
if (GetBorderType() == EBorderType::Dashed)
pStream->WriteStr(GetBorderDash().c_str());
double dBorderSize = GetBorderWidth();
pStream->WriteReal(dBorderSize);
pStream->WriteStr(" w\012");
CObjectBase* pObj = Get("IC");
if (pObj && pObj->GetType() == object_type_ARRAY)
{
pStream->WriteStr(GetColor(dynamic_cast<CArrayObject*>(pObj), false).c_str());
pStream->WriteStr("\012");
}
pStream->WriteStr(GetColor(dynamic_cast<CArrayObject*>(Get("C")), true).c_str());
pStream->WriteStr("\012");
pObj = Get("CA");
if (pObj && pObj->GetType() == object_type_REAL)
{
float dAlpha = ((CRealObject*)pObj)->Get();
if (dAlpha != 1)
{
CExtGrState* pExtGrState = m_pDocument->GetExtGState(dAlpha, dAlpha);
const char* sExtGrStateName = m_pDocument->GetFieldsResources()->GetExtGrStateName(pExtGrState);
if (sExtGrStateName)
{
pStream->WriteEscapeName(sExtGrStateName);
pStream->WriteStr(" gs\012");
}
}
}
double dLL = 0, dLLE = 0, dLLO = 0;
pObj = Get("LL");
if (pObj && pObj->GetType() == object_type_REAL)
dLL = ((CRealObject*)pObj)->Get();
pObj = Get("LLE");
if (pObj && pObj->GetType() == object_type_REAL)
dLLE = ((CRealObject*)pObj)->Get();
pObj = Get("LLO");
if (pObj && pObj->GetType() == object_type_REAL)
dLLO = ((CRealObject*)pObj)->Get();
DrawLineArrow(pStream, dBorderSize, dL[0], dL[1], dL[2], dL[3], m_nLE1, m_nLE2, dLL, dLLE, dLLO);
pNormal->DrawLine();
}
//----------------------------------------------------------------------------------------
// CPopupAnnotation
@ -2091,6 +1809,7 @@ namespace PdfWriter
CCheckBoxWidget::CCheckBoxWidget(CXref* pXref) : CWidgetAnnotation(pXref, AnnotWidget)
{
m_nSubtype = WidgetRadiobutton;
m_nStyle = ECheckBoxStyle::Circle;
}
void CCheckBoxWidget::SetV(const std::wstring& wsV)
{
@ -2104,37 +1823,34 @@ namespace PdfWriter
else
pOwner->Add("V", new CStringObject(sV.c_str(), true));
}
std::wstring CCheckBoxWidget::SetStyle(BYTE nStyle)
void CCheckBoxWidget::SetStyle(BYTE nStyle)
{
m_nStyle = ECheckBoxStyle(nStyle);
CheckMK();
std::string sValue;
switch (nStyle)
{
case 1:
{ sValue = "8"; break; }
case 2:
{ sValue = "u"; break; }
case 3:
{ sValue = "l"; break; }
case 4:
{ sValue = "H"; break; }
case 5:
{ sValue = "n"; break; }
default:
case 0:
{ sValue = "4"; break; }
}
m_pMK->Add("CA", new CStringObject(sValue.c_str()));
return UTF8_TO_U(sValue);
m_pMK->Add("CA", new CStringObject(c_sCheckBoxStyleNames[(int)nStyle]));
}
void CCheckBoxWidget::SetAP_N_Yes(const std::wstring& wsAP_N_Yes)
{
std::string sValue = U_TO_UTF8(wsAP_N_Yes);
m_sAP_N_Yes = sValue;
}
void CCheckBoxWidget::SetAP()
{
if (Get("AP"))
return;
CCheckBoxAnnotAppearance* pAP = new CCheckBoxAnnotAppearance(m_pXref, this, m_sAP_N_Yes.empty() ? NULL : m_sAP_N_Yes.c_str());
Add("AP", pAP);
if (m_nStyle == ECheckBoxStyle::Circle)
{
pAP->GetYesN()->DrawCheckBoxCircle(true);
pAP->GetOffN()->DrawCheckBoxCircle(false);
pAP->GetYesD()->DrawCheckBoxCircle(true);
pAP->GetOffD()->DrawCheckBoxCircle(false);
}
}
void CCheckBoxWidget::SwitchAP(const std::string& sV)
{
CObjectBase* pAP, *pAPN;

View File

@ -41,12 +41,12 @@
namespace PdfWriter
{
class CDestination;
enum ELineIntentType
enum class ELineIntentType
{
LineDimension = 0,
LineArrow
};
enum ELineEndType
enum class ELineEndType
{
Square = 0,
Circle,
@ -59,12 +59,12 @@ namespace PdfWriter
RClosedArrow,
Slash
};
enum ECaptionPositioning
enum class ECaptionPositioning
{
Inline = 0,
Top
};
enum EBorderType
enum class EBorderType
{
Solid = 0,
Beveled,
@ -72,6 +72,15 @@ namespace PdfWriter
Inset,
Underline
};
enum class ECheckBoxStyle
{
Check = 0,
Cross,
Diamond,
Circle,
Star,
Square
};
class CAction : public CDictObject
{
@ -284,10 +293,10 @@ namespace PdfWriter
};
class CLineAnnotation : public CMarkupAnnotation
{
private:
public:
ELineEndType m_nLE1, m_nLE2;
double dL[4];
public:
CLineAnnotation(CXref* pXref);
EAnnotType GetAnnotationType() const override
{
@ -519,15 +528,16 @@ namespace PdfWriter
{
private:
std::string m_sAP_N_Yes;
ECheckBoxStyle m_nStyle;
public:
CCheckBoxWidget(CXref* pXref);
void SetV(const std::wstring& wsV);
std::wstring SetStyle(BYTE nStyle);
void SetStyle(BYTE nStyle);
void SetAP_N_Yes(const std::wstring& wsAP_N_Yes);
virtual void SetFlag (const int& nFlag);
void SetAP();
void SwitchAP(const std::string& sV);
};
class CTextWidget : public CWidgetAnnotation

View File

@ -53,6 +53,286 @@
namespace PdfWriter
{
void AdjustLineEndpoint(ELineEndType nType, double x, double y, double dx, double dy, double w, double& tx, double& ty)
{
tx = x;
ty = y;
switch (nType)
{
case ELineEndType::ClosedArrow:
case ELineEndType::OpenArrow:
case ELineEndType::Diamond:
{
tx += w * dx;
if ((dx > 0.001 && dy > 0) || (dx < -0.001 && dy < 0))
ty += w * dy;
break;
}
case ELineEndType::Square:
case ELineEndType::Circle:
{
if ((dx > -0.02 && dy < 0.02) || (dx < 0.02 && dy > -0.02))
tx += w * dx;
break;
}
case ELineEndType::Slash:
case ELineEndType::Butt:
case ELineEndType::ROpenArrow:
case ELineEndType::RClosedArrow:
case ELineEndType::None:
default:
break;
}
}
void StreamWriteCM(CStream* pStream, double m11, double m12, double m21, double m22, double tx, double ty)
{
pStream->WriteReal(m11);
pStream->WriteChar(' ');
pStream->WriteReal(m12);
pStream->WriteChar(' ');
pStream->WriteReal(m21);
pStream->WriteChar(' ');
pStream->WriteReal(m22);
pStream->WriteChar(' ');
pStream->WriteReal(tx);
pStream->WriteChar(' ');
pStream->WriteReal(ty);
pStream->WriteStr(" cm\012");
}
void StreamWriteXYMove(CStream* pStream, double x, double y)
{
pStream->WriteReal(x);
pStream->WriteChar(' ');
pStream->WriteReal(y);
pStream->WriteStr(" m\012");
}
void StreamWriteXYLine(CStream* pStream, double x, double y)
{
pStream->WriteReal(x);
pStream->WriteChar(' ');
pStream->WriteReal(y);
pStream->WriteStr(" l\012");
}
void StreamWriteXYCurve(CStream* pStream, double x1, double y1, double x2, double y2, double x3, double y3)
{
pStream->WriteReal(x1);
pStream->WriteChar(' ');
pStream->WriteReal(y1);
pStream->WriteChar(' ');
pStream->WriteReal(x2);
pStream->WriteChar(' ');
pStream->WriteReal(y2);
pStream->WriteChar(' ');
pStream->WriteReal(x3);
pStream->WriteChar(' ');
pStream->WriteReal(y3);
pStream->WriteStr(" c\012");
}
void StreamWriteRect(CStream* pStream, double x1, double y1, double x2, double y2)
{
pStream->WriteReal(x1);
pStream->WriteChar(' ');
pStream->WriteReal(y1);
pStream->WriteChar(' ');
pStream->WriteReal(x2);
pStream->WriteChar(' ');
pStream->WriteReal(y2);
pStream->WriteStr(" re\012");
}
void StreamWriteCircle(CStream* pStream, double cx, double cy, double r)
{
double bezierCircle = 0.55228475 * r;
StreamWriteXYMove(pStream, cx + r, cy);
StreamWriteXYCurve(pStream, cx + r, cy + bezierCircle, cx + bezierCircle, cy + r, cx, cy + r);
StreamWriteXYCurve(pStream, cx - bezierCircle, cy + r, cx - r, cy + bezierCircle, cx - r, cy);
StreamWriteXYCurve(pStream, cx - r, cy - bezierCircle, cx - bezierCircle, cy - r, cx, cy - r);
StreamWriteXYCurve(pStream, cx + bezierCircle, cy - r, cx + r, cy - bezierCircle, cx + r, cy);
}
void DrawArrow(CStream* pStream, ELineEndType nType, double x, double y, double dx, double dy, double w)
{
double lineEndSize1 = 3, pi = 3.14159265358979323846;
switch (nType)
{
case ELineEndType::Butt:
{
w *= lineEndSize1;
StreamWriteXYMove(pStream, x + w * dy, y - w * dx);
StreamWriteXYLine(pStream, x - w * dy, y + w * dx);
pStream->WriteStr("S\012");
break;
}
case ELineEndType::Circle:
{
StreamWriteCircle(pStream, x, y, w * lineEndSize1);
pStream->WriteStr("h\012B\012");
break;
}
case ELineEndType::Diamond:
{
w *= lineEndSize1;
StreamWriteXYMove(pStream, x - w, y);
StreamWriteXYLine(pStream, x, y + w);
StreamWriteXYLine(pStream, x + w, y);
StreamWriteXYLine(pStream, x, y - w);
pStream->WriteStr("b\012");
break;
}
case ELineEndType::OpenArrow:
case ELineEndType::ClosedArrow:
{
w *= lineEndSize1 * lineEndSize1;
double d32 = pi * 32.0 / 180.0;
double d28 = pi * 28.0 / 180.0;
if ((dx > 0.001 && dy < 0) || (dx < -0.001 && dy > 0))
{
StreamWriteXYMove(pStream, x + w * cos(d32) * dx + w * sin(d32) * dy, y + w * cos(d32) * dy - w * sin(d32) * dx);
StreamWriteXYLine(pStream, x, y);
StreamWriteXYLine(pStream, x + w * cos(d28) * dx - w * sin(d28) * dy, y + w * cos(d28) * dy + w * sin(d28) * dx);
}
else
{
double dCos = w * cos(pi / 6.0);
double dSin = w * sin(pi / 6.0);
StreamWriteXYMove(pStream, x + dCos * dx + dSin * dy, y + dCos * dy - dSin * dx);
StreamWriteXYLine(pStream, x, y);
StreamWriteXYLine(pStream, x + dCos * dx - dSin * dy, y + dCos * dy + dSin * dx);
}
pStream->WriteStr(nType == ELineEndType::OpenArrow ? "S\012" : "b\012");
break;
}
case ELineEndType::ROpenArrow:
case ELineEndType::RClosedArrow:
{
x -= cos(pi / 18.0) * dx * w;
y -= cos(pi / 18.0) * dy * w;
w *= lineEndSize1 * lineEndSize1;
double dCos = w * cos(pi / 6.0);
double dSin = w * sin(pi / 6.0);
StreamWriteXYMove(pStream, x - dCos * dx + dSin * dy, y - dCos * dy - dSin * dx);
StreamWriteXYLine(pStream, x, y);
StreamWriteXYLine(pStream, x - dCos * dx - dSin * dy, y - dCos * dy + dSin * dx);
pStream->WriteStr(nType == ELineEndType::ROpenArrow ? "S\012" : "b\012");
break;
}
case ELineEndType::Slash:
{
w *= lineEndSize1 * lineEndSize1;
double dCos = w * cos(pi / 6.0);
double dSin = w * sin(pi / 6.0);
StreamWriteXYMove(pStream, x + dCos * dy - dSin * dx, y - dCos * dx - dSin * dy);
StreamWriteXYLine(pStream, x - dCos * dy + dSin * dx, y + dCos * dx + dSin * dy);
pStream->WriteStr("S\012");
break;
}
case ELineEndType::Square:
{
w *= lineEndSize1;
pStream->WriteReal(x - w);
pStream->WriteChar(' ');
pStream->WriteReal(y - w);
pStream->WriteChar(' ');
pStream->WriteReal(w * 2);
pStream->WriteChar(' ');
pStream->WriteReal(w * 2);
pStream->WriteStr(" re\012");
pStream->WriteStr("B\012");
break;
}
case ELineEndType::None:
default:
{
break;
}
}
}
void DrawLineArrow(CStream* pStream, double dBorderSize, double x1, double y1, double x2, double y2, ELineEndType nLE1, ELineEndType nLE2, double dLL = 0, double dLLO = 0, double dLLE = 0)
{
double dDX = x2 - x1;
double dDY = y2 - y1;
double dLen = sqrt(dDX * dDX + dDY * dDY);
if (dLen > 0)
{
dDX /= dLen;
dDY /= dLen;
}
double lx1, ly1, lx2, ly2;
double ax1, ay1, ax2, ay2;
double bx1, by1, bx2, by2;
if (dLL != 0)
{
ax1 = x1 + dLLO * dDY;
ay1 = y1 - dLLO * dDX;
lx1 = ax1 + dLL * dDY;
ly1 = ay1 - dLL * dDX;
bx1 = lx1 + dLLE * dDY;
by1 = ly1 - dLLE * dDX;
ax2 = x2 + dLLO * dDY;
ay2 = y2 - dLLO * dDX;
lx2 = ax2 + dLL * dDY;
ly2 = ay2 - dLL * dDX;
bx2 = lx2 + dLLE * dDY;
by2 = ly2 - dLLE * dDX;
}
else
{
lx1 = x1;
ly1 = y1;
lx2 = x2;
ly2 = y2;
ax1 = ay1 = ax2 = ay2 = 0;
bx1 = by1 = bx2 = by2 = 0;
}
double tx1, ty1, tx2, ty2;
AdjustLineEndpoint(nLE1, lx1, ly1, dDX, dDY, dBorderSize, tx1, ty1);
AdjustLineEndpoint(nLE2, lx2, ly2, -dDX, -dDY, dBorderSize, tx2, ty2);
if (dLL)
{
StreamWriteXYMove(pStream, ax1, ay1);
StreamWriteXYLine(pStream, bx1, by1);
StreamWriteXYMove(pStream, ax2, ay2);
StreamWriteXYLine(pStream, bx2, by2);
}
StreamWriteXYMove(pStream, tx1, ty1);
StreamWriteXYLine(pStream, tx2, ty2);
pStream->WriteStr("S\012");
DrawArrow(pStream, nLE1, tx1, ty1, dDX, dDY, dBorderSize);
DrawArrow(pStream, nLE2, tx2, ty2, -dDX, -dDY, dBorderSize);
}
std::string GetColor(CArrayObject* pArr, bool bCAPS, float dDiff = 0)
{
std::string sDA;
if (!pArr)
return sDA;
int nSize = pArr->GetCount();
for (int i = 0; i < nSize; ++i)
{
CObjectBase* pColor = pArr->Get(i);
float fColor = pColor->GetType() == object_type_REAL ? ((CRealObject*)pColor)->Get() : ((CNumberObject*)pColor)->Get();
sDA.append(std::to_string(fColor + dDiff));
sDA.append(" ");
}
if (nSize == 3)
sDA.append(bCAPS ? "RG" : "rg");
else if (nSize == 4)
sDA.append(bCAPS ? "K" : "k");
else if (nSize == 1)
sDA.append(bCAPS ? "G" : "g");
return sDA;
}
//----------------------------------------------------------------------------------------
// CFieldBase
//----------------------------------------------------------------------------------------
@ -1591,7 +1871,6 @@ namespace PdfWriter
CCheckBoxAnnotAppearance::CCheckBoxAnnotAppearance(CXref* pXref, CFieldBase* pField, const char* sYesName)
{
m_pXref = pXref;
m_pField = pField;
m_pYesN = new CAnnotAppearanceObject(pXref, pField);
m_pOffN = new CAnnotAppearanceObject(pXref, pField);
@ -1608,6 +1887,25 @@ namespace PdfWriter
pDictD->Add(sYesName ? sYesName : "Yes", m_pYesD);
pDictD->Add("Off", m_pOffD);
}
CCheckBoxAnnotAppearance::CCheckBoxAnnotAppearance(CXref* pXref, CAnnotation* pAnnot, const char* sYesName)
{
m_pXref = pXref;
m_pYesN = new CAnnotAppearanceObject(pXref, pAnnot);
m_pOffN = new CAnnotAppearanceObject(pXref, pAnnot);
m_pYesD = new CAnnotAppearanceObject(pXref, pAnnot);
m_pOffD = new CAnnotAppearanceObject(pXref, pAnnot);
CDictObject* pDictN = new CDictObject();
Add("N", pDictN);
pDictN->Add(sYesName ? sYesName : "Yes", m_pYesN);
pDictN->Add("Off", m_pOffN);
CDictObject* pDictD = new CDictObject();
Add("D", pDictD);
pDictD->Add(sYesName ? sYesName : "Yes", m_pYesD);
pDictD->Add("Off", m_pOffD);
}
CAnnotAppearanceObject* CCheckBoxAnnotAppearance::GetYesN()
{
return m_pYesN;
@ -2844,4 +3142,186 @@ namespace PdfWriter
m_pStream->WriteStr(sColor.c_str());
m_pStream->WriteStr(" 0 G 0 i 0.59 w 4 M 1 j 0 J [] 0 d 1 0 0 1 2.8335 1.7627 cm 0 0 m -2.74 15.16 l 12.345 12.389 l 9.458 9.493 l 14.027 4.91 l 7.532 -1.607 l 2.964 2.975 l b");
}
void CAnnotAppearanceObject::DrawLine()
{
AddBBox(m_pAnnot->GetRect().fLeft, m_pAnnot->GetRect().fBottom, m_pAnnot->GetRect().fRight, m_pAnnot->GetRect().fTop);
AddMatrix(1, 0, 0, 1, -m_pAnnot->GetRect().fLeft, -m_pAnnot->GetRect().fBottom);
if (m_pAnnot->GetBorderType() == EBorderType::Dashed)
m_pStream->WriteStr(m_pAnnot->GetBorderDash().c_str());
double dBorderSize = m_pAnnot->GetBorderWidth();
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" w\012");
CObjectBase* pObj = m_pAnnot->Get("IC");
if (pObj && pObj->GetType() == object_type_ARRAY)
{
m_pStream->WriteStr(GetColor(dynamic_cast<CArrayObject*>(pObj), false).c_str());
m_pStream->WriteStr("\012");
}
m_pStream->WriteStr(GetColor(dynamic_cast<CArrayObject*>(Get("C")), true).c_str());
m_pStream->WriteStr("\012");
pObj = m_pAnnot->Get("CA");
if (pObj && pObj->GetType() == object_type_REAL)
{
float dAlpha = ((CRealObject*)pObj)->Get();
if (dAlpha != 1)
{
CExtGrState* pExtGrState = m_pAnnot->GetDocument()->GetExtGState(dAlpha, dAlpha);
const char* sExtGrStateName = m_pAnnot->GetDocument()->GetFieldsResources()->GetExtGrStateName(pExtGrState);
if (sExtGrStateName)
{
m_pStream->WriteEscapeName(sExtGrStateName);
m_pStream->WriteStr(" gs\012");
}
}
}
double dLL = 0, dLLE = 0, dLLO = 0;
pObj = m_pAnnot->Get("LL");
if (pObj && pObj->GetType() == object_type_REAL)
dLL = ((CRealObject*)pObj)->Get();
pObj = m_pAnnot->Get("LLE");
if (pObj && pObj->GetType() == object_type_REAL)
dLLE = ((CRealObject*)pObj)->Get();
pObj = m_pAnnot->Get("LLO");
if (pObj && pObj->GetType() == object_type_REAL)
dLLO = ((CRealObject*)pObj)->Get();
CLineAnnotation* pAnnot = (CLineAnnotation*)m_pAnnot;
DrawLineArrow(m_pStream, dBorderSize, pAnnot->dL[0], pAnnot->dL[1], pAnnot->dL[2], pAnnot->dL[3], pAnnot->m_nLE1, pAnnot->m_nLE2, dLL, dLLE, dLLO);
}
void CAnnotAppearanceObject::DrawCheckBoxCheck(bool bSet, bool bN)
{
}
void CAnnotAppearanceObject::DrawCheckBoxCross(bool bSet, bool bN)
{
}
void CAnnotAppearanceObject::DrawCheckBoxDiamond(bool bSet, bool bN)
{
}
void CAnnotAppearanceObject::DrawCheckBoxCircle(bool bSet, bool bN)
{
CCheckBoxWidget* pAnnot = dynamic_cast<CCheckBoxWidget*>(m_pAnnot);
if (!pAnnot)
return;
std::string sBC = pAnnot->GetBCforAP();
std::string sBG = pAnnot->GetBGforAP(bN ? 0 : -0.250977);
double dW = m_pAnnot->GetRect().fRight - m_pAnnot->GetRect().fLeft;
double dH = m_pAnnot->GetRect().fBottom - m_pAnnot->GetRect().fTop;
double dCX = dW / 2.0, dCY = dH / 2.0;
double dR = std::min(dW, dH) / 2.0;
// Задний фон
m_pStream->WriteStr(sBG.c_str());
m_pStream->WriteStr("q\012");
m_pStream->WriteStr("1 0 0 1 ");
m_pStream->WriteReal(dCX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dCY);
m_pStream->WriteStr(" cm\012");
StreamWriteCircle(m_pStream, 0, 0, dR);
m_pStream->WriteStr("f\012Q\012");
// Граница
double dBorder = 1;
EBorderType nBorderType = EBorderType::Inset;
if (m_pAnnot->HaveBorder())
{
dBorder = m_pAnnot->GetBorderWidth();
nBorderType = m_pAnnot->GetBorderType();
}
if (dBorder != 1)
{
m_pStream->WriteReal(dBorder);
m_pStream->WriteStr(" w\012");
}
if (nBorderType == EBorderType::Dashed)
m_pStream->WriteStr(m_pAnnot->GetBorderDash().c_str());
m_pStream->WriteStr(sBC.c_str());
m_pStream->WriteStr("q\012");
m_pStream->WriteStr("1 0 0 1 ");
m_pStream->WriteReal(dCX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dCY);
m_pStream->WriteStr(" cm\012");
switch (nBorderType) {
case EBorderType::Solid:
case EBorderType::Dashed:
{
StreamWriteCircle(m_pStream, 0, 0, dR - dBorder / 2.0);
m_pStream->WriteStr("s\012Q\012");
break;
}
case EBorderType::Beveled:
{
break;
}
case EBorderType::Inset:
{
StreamWriteCircle(m_pStream, 0, 0, dR - dBorder / 2.0);
m_pStream->WriteStr("s\012Q\012");
double ca = cos(45.0 / 180.0 * M_PI);
double cx = 0, cy = 0, r = dR - dBorder * 1.5;
double bezierCircle = 0.55228475 * r;
if (bN)
m_pStream->WriteStr("0 G\012");
else
m_pStream->WriteStr("0.501953 G\012");
m_pStream->WriteStr("q\012");
StreamWriteCM(m_pStream, ca, ca, -ca, ca, dCX, dCY);
StreamWriteXYMove(m_pStream, cx + r, cy);
StreamWriteXYCurve(m_pStream, cx + r, cy + bezierCircle, cx + bezierCircle, cy + r, cx, cy + r);
StreamWriteXYCurve(m_pStream, cx - bezierCircle, cy + r, cx - r, cy + bezierCircle, cx - r, cy);
m_pStream->WriteStr("S\012Q\012");
if (bN)
m_pStream->WriteStr("1 G\012");
else
m_pStream->WriteStr("0.75293 G\012");
m_pStream->WriteStr("q\012");
StreamWriteCM(m_pStream, ca, ca, -ca, ca, dCX, dCY);
StreamWriteXYMove(m_pStream, cx - r, cy);
StreamWriteXYCurve(m_pStream, cx - r, cy - bezierCircle, cx - bezierCircle, cy - r, cx, cy - r);
StreamWriteXYCurve(m_pStream, cx + bezierCircle, cy - r, cx + r, cy - bezierCircle, cx + r, cy);
m_pStream->WriteStr("S\012Q\012");
break;
}
case EBorderType::Underline:
{
break;
}
}
// Установлен
if (!bSet)
return;
m_pStream->WriteStr("0 g\012q\012");
m_pStream->WriteStr("1 0 0 1 ");
m_pStream->WriteReal(dCX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dCY);
m_pStream->WriteStr(" cm\012");
StreamWriteCircle(m_pStream, 0, 0, dR / 2.0 - dBorder);
m_pStream->WriteStr("f\012Q\012");
}
void CAnnotAppearanceObject::DrawCheckBoxStar(bool bSet, bool bN)
{
}
void CAnnotAppearanceObject::DrawCheckBoxSquare(bool bSet, bool bN)
{
}
}

View File

@ -363,6 +363,7 @@ namespace PdfWriter
{
public:
CCheckBoxAnnotAppearance(CXref* pXref, CFieldBase* pField, const char* sYesName = NULL);
CCheckBoxAnnotAppearance(CXref* pXref, CAnnotation* pAnnot, const char* sYesName = NULL);
CAnnotAppearanceObject* GetYesN();
CAnnotAppearanceObject* GetOffN();
@ -372,7 +373,6 @@ namespace PdfWriter
private:
CXref* m_pXref;
CFieldBase* m_pField;
CAnnotAppearanceObject* m_pYesN;
CAnnotAppearanceObject* m_pOffN;
CAnnotAppearanceObject* m_pYesD;
@ -418,7 +418,14 @@ namespace PdfWriter
void DrawTextUpArrow(const std::string& sColor);
void DrawTextUpLeftArrow(const std::string& sColor);
void DrawRadiobuttonCircle();
void DrawLine();
void DrawCheckBoxCheck(bool bSet, bool bN);
void DrawCheckBoxCross(bool bSet, bool bN);
void DrawCheckBoxDiamond(bool bSet, bool bN);
void DrawCheckBoxCircle(bool bSet, bool bN);
void DrawCheckBoxStar(bool bSet, bool bN);
void DrawCheckBoxSquare(bool bSet, bool bN);
CStream* GetStream() const { return m_pStream; }
CFontDict* GetFont() { return m_pFont; }