From 0803b33067112e4bc54daca168a73757959272fa Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Thu, 18 Jan 2024 18:37:54 +0300 Subject: [PATCH] Write PushButton --- PdfFile/PdfWriter.cpp | 46 +++--- PdfFile/SrcWriter/Annotation.cpp | 70 +++++---- PdfFile/SrcWriter/Field.cpp | 256 +++++++++++++++++++++++++++++++ PdfFile/SrcWriter/Field.h | 9 ++ 4 files changed, 327 insertions(+), 54 deletions(-) diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index 02e57e9ebd..7904789b31 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -3556,7 +3556,12 @@ void CPdfWriter::DrawButtonWidget(NSFonts::IApplicationFonts* pAppFonts, PdfWrit wsValue = pButtonWidget->GetAC(); if (!pButtonWidget->HaveBorder()) - pButtonWidget->SetEmptyBorder(); + { + if (pButtonWidget->HaveBC()) + pButtonWidget->SetBorder(0, 1, {}); + else + pButtonWidget->SetEmptyBorder(); + } if (!wsValue.empty() && nTP != 1) { @@ -3576,7 +3581,8 @@ void CPdfWriter::DrawButtonWidget(NSFonts::IApplicationFonts* pAppFonts, PdfWrit dShiftBorder *= 2; if (dShiftBorder == 0) dShiftBorder = 1; - if (!pButtonWidget->GetRespectBorder()) + bool bRespectBorder = pButtonWidget->GetRespectBorder(); + if (!bRespectBorder) dShiftBorder = 0; bool bFont = GetFontData(pAppFonts, wsValue, pFont, isBold, isItalic, pUnicodes, unLen, pCodes, ppFonts); @@ -3598,34 +3604,32 @@ void CPdfWriter::DrawButtonWidget(NSFonts::IApplicationFonts* pAppFonts, PdfWrit if (pFontTT) { double dKoef = dFontSize / pFontTT->m_dUnitsPerEm; - dLineH = pFontTT->m_dHeight * dKoef; + // TODO что-то между m_dMaxY-m_dMinY и m_dHeight, но не просто среднее + dLineH = (pFontTT->m_dMaxY + std::abs(pFontTT->m_dMinY) + pFontTT->m_dHeight) / 2.0 * dKoef; + // dLineH = (pFontTT->m_dMaxY + std::abs(pFontTT->m_dMinY)) * dKoef; + // dLineH = pFontTT->m_dHeight * dKoef; + // double dLineHeight = pFontTT->m_dHeight * dKoef; + // double dDescent = std::abs(pFontTT->m_dDescent * dKoef); + // double dAscent1 = pFontTT->m_dAscent * dKoef; + // double dAscent = dLineHeight - dDescent; + // double dMidPoint = dAscent - pFontTT->m_dMinY * dKoef + dAscent - pFontTT->m_dMaxY * dKoef; + // double dDiff = dLineHeight - dMidPoint; if (nTP == 0 || nTP == 2 || nTP == 3 || nTP == 6) dShiftX = (dWidth - dLineW) / 2; else if (nTP == 4) - dShiftX = dWidth - dLineW - dShiftBorder * 2; + dShiftX = dWidth - dLineW - dShiftBorder * 1.5; else if (nTP == 5) - dShiftX = dShiftBorder * 2; + dShiftX = dShiftBorder * 2.5; - if (nTP == 0 || nTP == 4 || nTP == 5 || nTP == 6) - dShiftY = (dHeight - dLineH) / 2.0 + std::abs(pFontTT->m_dDescent * dKoef); + if (nTP == 0 || nTP == 6) + dShiftY = (dHeight - dLineH) / 2 + std::abs(pFontTT->m_dMinY * dKoef); else if (nTP == 3) - dShiftY = dHeight - dShiftBorder * 2 - dLineH + std::abs(pFontTT->m_dDescent * dKoef); + dShiftY = dHeight - dShiftBorder * 2.5 - dLineH + std::abs(pFontTT->m_dMinY * dKoef); else if (nTP == 2) - { - // double dLineHeight = pFontTT->m_dHeight * dKoef; - // double dDescent = std::abs(pFontTT->m_dDescent * dKoef); - // double dAscent1 = pFontTT->m_dAscent * dKoef; - // double dAscent = dLineHeight - dDescent; - // double dMin = pFontTT->m_dMinY * dKoef; - // double dMax = pFontTT->m_dMaxY * dKoef; - // double dMidPoint = dAscent - pFontTT->m_dMinY * dKoef + dAscent - pFontTT->m_dMaxY * dKoef; - // double dDiff = dLineHeight - dMidPoint; - // dShiftY = dLineHeight / 2.0; - // dShiftY = dShiftY + dDescent; - // Find! PERFECT!!! dShiftY = dShiftBorder * 2 + std::abs(pFontTT->m_dMinY * dKoef); - } + else if (nTP == 4 || nTP == 5) + dShiftY = (dHeight - dLineH) / 2 + std::abs(pFontTT->m_dMinY * dKoef); } } diff --git a/PdfFile/SrcWriter/Annotation.cpp b/PdfFile/SrcWriter/Annotation.cpp index 01128ced36..19dd6870f3 100644 --- a/PdfFile/SrcWriter/Annotation.cpp +++ b/PdfFile/SrcWriter/Annotation.cpp @@ -221,7 +221,6 @@ namespace PdfWriter } void CAnnotation::SetEmptyBorder() { - m_oBorder.bHave = true; m_oBorder.nType = 0; m_oBorder.dWidth = 1; } @@ -1251,14 +1250,15 @@ namespace PdfWriter return; Add("AP", m_pAppearance); + double dHeight = fabs(m_oRect.fTop - m_oRect.fBottom); + double dWidth = fabs(m_oRect.fRight - m_oRect.fLeft); + + pAppearance->StartDraw(dWidth, dHeight); + if (pForm) { - double dH = fabs(m_oRect.fTop - m_oRect.fBottom); - double dW = fabs(m_oRect.fRight - m_oRect.fLeft); - if (m_nTP == 2 || m_nTP == 3) - dH -= dLineH; - if (m_nTP == 4 || m_nTP == 5) - dW -= dLineW; + double dH = dHeight; + double dW = dWidth; double dOriginW = pForm->GetWidth(); double dOriginH = pForm->GetHeight(); @@ -1267,20 +1267,32 @@ namespace PdfWriter || (2 == m_nScaleType && (dOriginH > dH || dOriginW > dW)) || (3 == m_nScaleType && dOriginH < dH && dOriginW < dW)); + double dBorderSize = m_oBorder.dWidth; + if (m_oBorder.nType == 1 || m_oBorder.nType == 3) + dBorderSize *= 2; + double dDstW = dOriginW; double dDstH = dOriginH; double dDstX = 0; double dDstY = 0; - if (m_nTP == 2 || m_nTP == 3) - dDstY += dLineH; - if (m_nTP == 4 || m_nTP == 5) - dDstX += dLineW; - if (m_bRespectBorders && m_oBorder.bHave) + if (m_nTP == 2) + { + dH -= (dLineH + dBorderSize); + dDstY += (dLineH + dBorderSize); + } + if (m_nTP == 3) + dH -= (dLineH + dBorderSize); + if (m_nTP == 4) + dW -= (dLineW + dBorderSize); + if (m_nTP == 5) + { + dW -= (dLineW + dBorderSize); + dDstX += (dLineW + dBorderSize); + } + + if (m_bRespectBorders) { - double dBorderSize = m_oBorder.dWidth; - if (m_oBorder.nType == 1 || m_oBorder.nType == 3) - dBorderSize *= 2; dDstX += 2 * dBorderSize; dDstY += 2 * dBorderSize; dH -= 4 * dBorderSize; @@ -1305,29 +1317,21 @@ namespace PdfWriter dDstX += (dW - dDstW) * m_dShiftX; dDstY += (dH - dDstH) * m_dShiftY; - pAppearance->DrawPicture(pForm->GetName().c_str(), dDstX, dDstY, dDstW / dOriginW, dDstH / dOriginH, m_bRespectBorders); - } - else - pAppearance->StartDrawText(m_pFont, m_dFontSize, 0, 0, 0, NULL, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop)); + pAppearance->DrawPictureInline(pForm->GetName().c_str(), dDstX, dDstY, dDstW / dOriginW, dDstH / dOriginH, m_bRespectBorders); - if (pCodes) - { - CStream* pStream = pAppearance->GetStream(); - if (pForm) - pStream->WriteStr("\012q\012BT\012"); - pAppearance->DrawTextLine(dX, dY, pCodes, unCount, ppFonts, NULL); - if (pForm) - pStream->WriteStr("ET\012Q\012"); - else - pAppearance->EndDrawText(); - } - - if (pForm) - { CheckMK(); std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX"); m_pMK->Add(sAP, pForm); } + + if (pCodes) + { + pAppearance->StartText(m_pFont, m_dFontSize); + pAppearance->DrawTextLine(dX, dY, pCodes, unCount, ppFonts, NULL); + pAppearance->EndText(); + } + + pAppearance->EndDraw(); } //---------------------------------------------------------------------------------------- // CCheckBoxWidget diff --git a/PdfFile/SrcWriter/Field.cpp b/PdfFile/SrcWriter/Field.cpp index fa817b0b87..29276b2982 100644 --- a/PdfFile/SrcWriter/Field.cpp +++ b/PdfFile/SrcWriter/Field.cpp @@ -2170,6 +2170,262 @@ namespace PdfWriter m_bStart = true; m_pFont = pFont; } + void CAnnotAppearanceObject::StartDraw(const double& dWidth, const double& dHeight) + { + CWidgetAnnotation* pAnnot = dynamic_cast(m_pAnnot); + if (!m_pStream || !pAnnot) + return; + + DrawBackground(dWidth, dHeight); + DrawBorder(dWidth, dHeight); + + m_pStream->WriteStr("q\012"); + + double dBorderSize = pAnnot->GetBorderWidth(); + BYTE nType = pAnnot->GetBorderType(); + if (nType == 1 || nType == 3) + dBorderSize *= 2; + + if (pAnnot->GetWidgetType() == WidgetPushbutton && !((CPushButtonWidget*)pAnnot)->GetRespectBorder()) + dBorderSize = 0; + + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(std::max(dWidth - dBorderSize * 2, 0.0)); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(std::max(dHeight - dBorderSize * 2, 0.0)); + m_pStream->WriteStr(" re\012W\012n\012"); + + if (pAnnot && pAnnot->GetWidgetType() == WidgetListbox) + { + CChoiceWidget* pAnnot = dynamic_cast(m_pAnnot); + double dBaseLine = pAnnot->GetListBoxHeight(); + std::vector arrIndex = pAnnot->GetListBoxIndex(); + m_pStream->WriteStr("0.60 0.75 0.85 rg\012"); + for (int i = 0; i < arrIndex.size(); ++i) + { + double dH = dHeight - dBorderSize - dBaseLine * (double)(arrIndex[i] + 1); + if (dH < 0) + break; + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dH); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(std::max(dWidth - dBorderSize * 2.0, 0.0)); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dBaseLine); + m_pStream->WriteStr(" re\012f\012"); + } + } + } + void CAnnotAppearanceObject::StartText(CFontDict* pFont, const double& dFontSize) + { + CWidgetAnnotation* pAnnot = dynamic_cast(m_pAnnot); + if (!m_pStream || !pAnnot) + return; + + m_dFontSize = std::min(1000.0, std::max(0.0, dFontSize)); + m_pFont = pFont; + m_bStart = true; + + m_pStream->WriteStr("BT\012"); + m_pStream->WriteStr(pAnnot->GetDAforAP(pFont).c_str()); + } + void CAnnotAppearanceObject::DrawPictureInline(const char* sImageName, const double& dX, const double& dY, const double& dW, const double& dH, const bool& bRespectBorder) + { + CWidgetAnnotation* pAnnot = dynamic_cast(m_pAnnot); + if (!m_pStream || !pAnnot || !sImageName) + return; + + m_pStream->WriteStr("q\012"); + + if (bRespectBorder) + { + TRect oRect = pAnnot->GetRect(); + double dWidth = fabs(oRect.fRight - oRect.fLeft); + double dHeight = fabs(oRect.fBottom - oRect.fTop); + + double dBorderSize = pAnnot->GetBorderWidth(); + BYTE nType = pAnnot->GetBorderType(); + if (nType == 1 || nType == 3) + dBorderSize *= 2; + + m_pStream->WriteReal(2 * dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(2 * dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(fmax(dWidth - 4 * dBorderSize, 0.0)); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(fmax(dHeight - 4 * dBorderSize, 0.0)); + m_pStream->WriteStr(" re\012W\012n\012"); + } + + m_pStream->WriteReal(dW); + m_pStream->WriteStr(" 0 0 "); + m_pStream->WriteReal(dH); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dX); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dY); + m_pStream->WriteStr(" cm\012"); + + m_pStream->WriteEscapeName(sImageName); + m_pStream->WriteStr(" Do\012"); + + m_pStream->WriteStr("Q\012"); + } + void CAnnotAppearanceObject::EndText() + { + m_pStream->WriteStr("ET\012"); + } + void CAnnotAppearanceObject::EndDraw() + { + m_pStream->WriteStr("Q\012"); + } + void CAnnotAppearanceObject::DrawBackground(const double& dWidth, const double& dHeight) + { + CWidgetAnnotation* pAnnot = dynamic_cast(m_pAnnot); + if (!pAnnot || !pAnnot->HaveBG()) + return; + + m_pStream->WriteStr("q\012"); + m_pStream->WriteStr(pAnnot->GetBGforAP().c_str()); + m_pStream->WriteStr("1 0 0 1 0 0 cm\012"); + m_pStream->WriteStr("0 0 "); + m_pStream->WriteReal(fmax(dWidth, 0.0)); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(fmax(dHeight, 0.0)); + m_pStream->WriteStr(" re\012f\012"); + m_pStream->WriteStr("Q\012"); + } + void CAnnotAppearanceObject::DrawBorder(const double& dWidth, const double& dHeight) + { + CWidgetAnnotation* pAnnot = dynamic_cast(m_pAnnot); + if (!pAnnot || !pAnnot->HaveBorder()) + return; + + m_pStream->WriteStr("q\012"); + + double dBorderSize = pAnnot->GetBorderWidth(); + BYTE nType = pAnnot->GetBorderType(); + + switch (nType) + { + case 1: // Beveled + case 3: // Inset + { + m_pStream->WriteStr(nType == 1 ? "1 g\012" : "0.501953 g\012"); + + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteStr(" m\012"); + + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dHeight - dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteReal(dWidth - dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dHeight - dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteReal(dWidth - 2 * dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dHeight - 2 * dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteReal(2 * dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dHeight - 2 * dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteReal(2 * dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(2 * dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteStr("f\012"); + + if (nType == 1 && pAnnot->HaveBG()) + m_pStream->WriteStr(pAnnot->GetBGforAP(-0.25).c_str()); + else + m_pStream->WriteStr("0.75293 g\012"); + + m_pStream->WriteReal(dWidth - dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dHeight - dBorderSize); + m_pStream->WriteStr(" m\012"); + + m_pStream->WriteReal(dWidth - dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteReal(2 * dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(2 * dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteReal(dWidth - 2 * dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(2 * dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteReal(dWidth - 2 * dBorderSize); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dHeight - 2 * dBorderSize); + m_pStream->WriteStr(" l\012"); + + m_pStream->WriteStr("f\012"); + break; + } + case 2: // Dashed + { + m_pStream->WriteStr(pAnnot->GetBorderDash().c_str()); + break; + } + default: break; + } + + m_pStream->WriteStr(pAnnot->GetBCforAP().c_str()); + m_pStream->WriteReal(dBorderSize); + m_pStream->WriteStr(" w\0120 j\0120 J\012"); + + if (nType == 4) // Underline + { + m_pStream->WriteInt(0); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dBorderSize / 2); + m_pStream->WriteStr(" m\012"); + + m_pStream->WriteReal(dWidth); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dBorderSize / 2); + m_pStream->WriteStr(" l\012S\012"); + } + else + { + m_pStream->WriteReal(dBorderSize / 2); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(dBorderSize / 2); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(std::max(dWidth - dBorderSize, 0.0)); + m_pStream->WriteChar(' '); + m_pStream->WriteReal(std::max(dHeight - dBorderSize, 0.0)); + m_pStream->WriteStr(" re\012S\012"); + } + + m_pStream->WriteStr("Q\012"); + } void CAnnotAppearanceObject::DrawTextLine(const double& dX, const double& dY, const unsigned short* pCodes, const unsigned int& unCount, CFontCidTrueType** ppFonts, const double* pShifts) { CResourcesDict* pResources = dynamic_cast(Get("Resources")); diff --git a/PdfFile/SrcWriter/Field.h b/PdfFile/SrcWriter/Field.h index fcb33d8d75..0bd02c05c6 100644 --- a/PdfFile/SrcWriter/Field.h +++ b/PdfFile/SrcWriter/Field.h @@ -390,6 +390,12 @@ namespace PdfWriter void DrawTextLine(const double &dX, const double &dY, const std::wstring& wsText); void EndDrawText(); + void StartDraw(const double& dWidth, const double& dHeight); + void StartText(CFontDict* pFont, const double& dFontSize); + void DrawPictureInline(const char* sImageName, const double& dX, const double& dY, const double& dW, const double& dH, const bool& bRespectBorder); + void EndText(); + void EndDraw(); + void DrawTextComment(); CStream* GetStream() { return m_pStream; } @@ -398,6 +404,9 @@ namespace PdfWriter private: void Init(CXref* pXref, CResourcesDict* pResources, TRect* pRect); + void DrawBackground(const double& dWidth, const double& dHeight); + void DrawBorder(const double& dWidth, const double& dHeight); + CXref* m_pXref; CStream* m_pStream; CFieldBase* m_pField;