From 1d9230b731b8de697491eee8edec33b76d16a995 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Mon, 31 Mar 2025 15:27:17 +0300 Subject: [PATCH] Create DrawCheckBoxCircle --- PdfFile/PdfWriter.cpp | 5 +- PdfFile/SrcWriter/Annotation.cpp | 336 ++------------------- PdfFile/SrcWriter/Annotation.h | 26 +- PdfFile/SrcWriter/Field.cpp | 482 ++++++++++++++++++++++++++++++- PdfFile/SrcWriter/Field.h | 11 +- 5 files changed, 538 insertions(+), 322 deletions(-) diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index 21f307f793..a226e9c773 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -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()) diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index acdeef640c..d2761319f7 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -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& 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(pObj), false).c_str()); - pStream->WriteStr("\012"); - } - - pStream->WriteStr(GetColor(dynamic_cast(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; diff --git a/PdfFile/SrcWriter/Annotation.h b/PdfFile/SrcWriter/Annotation.h index 15725c5dc1..88bc1e5fd0 100644 --- a/PdfFile/SrcWriter/Annotation.h +++ b/PdfFile/SrcWriter/Annotation.h @@ -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 diff --git a/PdfFile/SrcWriter/Field.cpp b/PdfFile/SrcWriter/Field.cpp index ba50565fb4..e0f25963f4 100644 --- a/PdfFile/SrcWriter/Field.cpp +++ b/PdfFile/SrcWriter/Field.cpp @@ -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(pObj), false).c_str()); + m_pStream->WriteStr("\012"); + } + + m_pStream->WriteStr(GetColor(dynamic_cast(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(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) + { + + } } diff --git a/PdfFile/SrcWriter/Field.h b/PdfFile/SrcWriter/Field.h index ca2750a156..9498a76e9b 100644 --- a/PdfFile/SrcWriter/Field.h +++ b/PdfFile/SrcWriter/Field.h @@ -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; }