From cb2ea42cc56eb6aaab3e498abf13e63742e64181 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Wed, 19 Jul 2017 15:24:49 -0400 Subject: Create CPWL_AppStream. This CL creates a CPWL_AppStream and consolidates app stream generation code from CPDFSDK_Widget, CPDFSDK_BAAnnot and CPWL_Utils. The remaining app stream code from CPWL_Utils will be cleaned up in a future CL. Change-Id: I20cfdec09a351bd509241d2c667a182fba84b0c1 Reviewed-on: https://pdfium-review.googlesource.com/8310 Commit-Queue: dsinclair Reviewed-by: Tom Sepez Reviewed-by: Henrique Nakashima --- fpdfsdk/cpdfsdk_baannot.cpp | 51 +- fpdfsdk/cpdfsdk_baannot.h | 8 +- fpdfsdk/cpdfsdk_widget.cpp | 858 +------------------ fpdfsdk/cpdfsdk_widget.h | 18 +- fpdfsdk/pdfwindow/cpwl_appstream.cpp | 1558 ++++++++++++++++++++++++++++++++++ fpdfsdk/pdfwindow/cpwl_appstream.h | 43 + fpdfsdk/pdfwindow/cpwl_utils.cpp | 656 -------------- fpdfsdk/pdfwindow/cpwl_utils.h | 47 - 8 files changed, 1621 insertions(+), 1618 deletions(-) create mode 100644 fpdfsdk/pdfwindow/cpwl_appstream.cpp create mode 100644 fpdfsdk/pdfwindow/cpwl_appstream.h (limited to 'fpdfsdk') diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp index 1f4f279b5e..a426749fff 100644 --- a/fpdfsdk/cpdfsdk_baannot.cpp +++ b/fpdfsdk/cpdfsdk_baannot.cpp @@ -38,6 +38,13 @@ CPDF_Dictionary* CPDFSDK_BAAnnot::GetAnnotDict() const { return m_pAnnot->GetAnnotDict(); } +CPDF_Dictionary* CPDFSDK_BAAnnot::GetAPDict() const { + CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"); + if (!pAPDict) + pAPDict = m_pAnnot->GetAnnotDict()->SetNewFor("AP"); + return pAPDict; +} + void CPDFSDK_BAAnnot::SetRect(const CFX_FloatRect& rect) { ASSERT(rect.right - rect.left >= GetMinWidth()); ASSERT(rect.top - rect.bottom >= GetMinHeight()); @@ -293,50 +300,6 @@ bool CPDFSDK_BAAnnot::GetColor(FX_COLORREF& color) const { return false; } -void CPDFSDK_BAAnnot::WriteAppearance(const CFX_ByteString& sAPType, - const CFX_FloatRect& rcBBox, - const CFX_Matrix& matrix, - const CFX_ByteString& sContents, - const CFX_ByteString& sAPState) { - CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"); - if (!pAPDict) - pAPDict = m_pAnnot->GetAnnotDict()->SetNewFor("AP"); - - CPDF_Stream* pStream = nullptr; - CPDF_Dictionary* pParentDict = nullptr; - if (sAPState.IsEmpty()) { - pParentDict = pAPDict; - pStream = pAPDict->GetStreamFor(sAPType); - } else { - CPDF_Dictionary* pAPTypeDict = pAPDict->GetDictFor(sAPType); - if (!pAPTypeDict) - pAPTypeDict = pAPDict->SetNewFor(sAPType); - - pParentDict = pAPTypeDict; - pStream = pAPTypeDict->GetStreamFor(sAPState); - } - - if (!pStream) { - CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); - pStream = pDoc->NewIndirect(); - pParentDict->SetNewFor(sAPType, pDoc, pStream->GetObjNum()); - } - - CPDF_Dictionary* pStreamDict = pStream->GetDict(); - if (!pStreamDict) { - auto pNewDict = pdfium::MakeUnique( - m_pAnnot->GetDocument()->GetByteStringPool()); - pStreamDict = pNewDict.get(); - pStreamDict->SetNewFor("Type", "XObject"); - pStreamDict->SetNewFor("Subtype", "Form"); - pStreamDict->SetNewFor("FormType", 1); - pStream->InitStream(nullptr, 0, std::move(pNewDict)); - } - pStreamDict->SetMatrixFor("Matrix", matrix); - pStreamDict->SetRectFor("BBox", rcBBox); - pStream->SetData((uint8_t*)sContents.c_str(), sContents.GetLength()); -} - bool CPDFSDK_BAAnnot::IsVisible() const { uint32_t nFlags = GetFlags(); return !((nFlags & ANNOTFLAG_INVISIBLE) || (nFlags & ANNOTFLAG_HIDDEN) || diff --git a/fpdfsdk/cpdfsdk_baannot.h b/fpdfsdk/cpdfsdk_baannot.h index 6c9ae06ed4..18d25a1e02 100644 --- a/fpdfsdk/cpdfsdk_baannot.h +++ b/fpdfsdk/cpdfsdk_baannot.h @@ -36,6 +36,8 @@ class CPDFSDK_BAAnnot : public CPDFSDK_Annot { CPDF_Dictionary* GetAnnotDict() const; CPDF_Annot* GetPDFPopupAnnot() const; + CPDF_Dictionary* GetAPDict() const; + void SetContents(const CFX_WideString& sContents); CFX_WideString GetContents() const; @@ -88,12 +90,6 @@ class CPDFSDK_BAAnnot : public CPDFSDK_Annot { void ClearCachedAP(); - void WriteAppearance(const CFX_ByteString& sAPType, - const CFX_FloatRect& rcBBox, - const CFX_Matrix& matrix, - const CFX_ByteString& sContents, - const CFX_ByteString& sAPState = ""); - void SetOpenState(bool bState); protected: diff --git a/fpdfsdk/cpdfsdk_widget.cpp b/fpdfsdk/cpdfsdk_widget.cpp index 80e7c8adb1..fed6b953da 100644 --- a/fpdfsdk/cpdfsdk_widget.cpp +++ b/fpdfsdk/cpdfsdk_widget.cpp @@ -30,6 +30,7 @@ #include "fpdfsdk/fsdk_actionhandler.h" #include "fpdfsdk/fsdk_define.h" #include "fpdfsdk/fxedit/fxet_edit.h" +#include "fpdfsdk/pdfwindow/cpwl_appstream.h" #include "fpdfsdk/pdfwindow/cpwl_edit.h" #include "fpdfsdk/pdfwindow/cpwl_utils.h" @@ -764,26 +765,25 @@ void CPDFSDK_Widget::ResetAppearance(const CFX_WideString* sValue, if (bValueChanged) m_nValueAge++; - int nFieldType = GetFieldType(); - - switch (nFieldType) { + CPWL_AppStream appStream(this, GetAPDict()); + switch (GetFieldType()) { case FIELDTYPE_PUSHBUTTON: - ResetAppearance_PushButton(); + appStream.SetAsPushButton(); break; case FIELDTYPE_CHECKBOX: - ResetAppearance_CheckBox(); + appStream.SetAsCheckBox(); break; case FIELDTYPE_RADIOBUTTON: - ResetAppearance_RadioButton(); + appStream.SetAsRadioButton(); break; case FIELDTYPE_COMBOBOX: - ResetAppearance_ComboBox(sValue); + appStream.SetAsComboBox(sValue); break; case FIELDTYPE_LISTBOX: - ResetAppearance_ListBox(); + appStream.SetAsListBox(); break; case FIELDTYPE_TEXTFIELD: - ResetAppearance_TextField(sValue); + appStream.SetAsTextField(sValue); break; } @@ -861,777 +861,6 @@ void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice, m_pInterForm->GetHighlightColor(nFieldType))); } -void CPDFSDK_Widget::ResetAppearance_PushButton() { - CPDF_FormControl* pControl = GetFormControl(); - CFX_FloatRect rcWindow = GetRotatedRect(); - int32_t nLayout = 0; - switch (pControl->GetTextPosition()) { - case TEXTPOS_ICON: - nLayout = PPBL_ICON; - break; - case TEXTPOS_BELOW: - nLayout = PPBL_ICONTOPLABELBOTTOM; - break; - case TEXTPOS_ABOVE: - nLayout = PPBL_LABELTOPICONBOTTOM; - break; - case TEXTPOS_RIGHT: - nLayout = PPBL_ICONLEFTLABELRIGHT; - break; - case TEXTPOS_LEFT: - nLayout = PPBL_LABELLEFTICONRIGHT; - break; - case TEXTPOS_OVERLAID: - nLayout = PPBL_LABELOVERICON; - break; - default: - nLayout = PPBL_LABEL; - break; - } - - CFX_Color crBackground; - CFX_Color crBorder; - int iColorType; - float fc[4]; - pControl->GetOriginalBackgroundColor(iColorType, fc); - if (iColorType > 0) - crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - pControl->GetOriginalBorderColor(iColorType, fc); - if (iColorType > 0) - crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - float fBorderWidth = (float)GetBorderWidth(); - CPWL_Dash dsBorder(3, 0, 0); - CFX_Color crLeftTop; - CFX_Color crRightBottom; - - BorderStyle nBorderStyle = GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); - CFX_Color crText(COLORTYPE_GRAY, 0); - - CFX_ByteString csNameTag; - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - float fFontSize = 12.0f; - if (da.HasFont()) - csNameTag = da.GetFont(&fFontSize); - - CFX_WideString csWCaption; - CFX_WideString csNormalCaption; - CFX_WideString csRolloverCaption; - CFX_WideString csDownCaption; - if (pControl->HasMKEntry("CA")) - csNormalCaption = pControl->GetNormalCaption(); - - if (pControl->HasMKEntry("RC")) - csRolloverCaption = pControl->GetRolloverCaption(); - - if (pControl->HasMKEntry("AC")) - csDownCaption = pControl->GetDownCaption(); - - CPDF_Stream* pNormalIcon = nullptr; - CPDF_Stream* pRolloverIcon = nullptr; - CPDF_Stream* pDownIcon = nullptr; - if (pControl->HasMKEntry("I")) - pNormalIcon = pControl->GetNormalIcon(); - - if (pControl->HasMKEntry("RI")) - pRolloverIcon = pControl->GetRolloverIcon(); - - if (pControl->HasMKEntry("IX")) - pDownIcon = pControl->GetDownIcon(); - - if (pNormalIcon) { - if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgA", false); - } - } - - if (pRolloverIcon) { - if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgB", false); - } - } - - if (pDownIcon) { - if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgC", false); - } - } - - CPDF_IconFit iconFit = pControl->GetIconFit(); - - CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler()); - font_map.SetAPType("N"); - - CFX_ByteString csAP = - CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder) + - CPWL_Utils::GetPushButtonAppStream( - iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map, - pNormalIcon, iconFit, csNormalCaption, crText, fFontSize, nLayout); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP); - if (pNormalIcon) - AddImageToAppearance("N", pNormalIcon); - - CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode(); - if (eHLM == CPDF_FormControl::Push || eHLM == CPDF_FormControl::Toggle) { - if (csRolloverCaption.IsEmpty() && !pRolloverIcon) { - csRolloverCaption = csNormalCaption; - pRolloverIcon = pNormalIcon; - } - - font_map.SetAPType("R"); - - csAP = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, - nBorderStyle, dsBorder) + - CPWL_Utils::GetPushButtonAppStream( - iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map, - pRolloverIcon, iconFit, csRolloverCaption, crText, fFontSize, - nLayout); - - WriteAppearance("R", GetRotatedRect(), GetMatrix(), csAP); - if (pRolloverIcon) - AddImageToAppearance("R", pRolloverIcon); - - if (csDownCaption.IsEmpty() && !pDownIcon) { - csDownCaption = csNormalCaption; - pDownIcon = pNormalIcon; - } - - switch (nBorderStyle) { - case BorderStyle::BEVELED: { - CFX_Color crTemp = crLeftTop; - crLeftTop = crRightBottom; - crRightBottom = crTemp; - break; - } - case BorderStyle::INSET: { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - break; - } - default: - break; - } - - font_map.SetAPType("D"); - - csAP = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, - nBorderStyle, dsBorder) + - CPWL_Utils::GetPushButtonAppStream( - iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map, - pDownIcon, iconFit, csDownCaption, crText, fFontSize, nLayout); - - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP); - if (pDownIcon) - AddImageToAppearance("D", pDownIcon); - } else { - RemoveAppearance("D"); - RemoveAppearance("R"); - } -} - -void CPDFSDK_Widget::ResetAppearance_CheckBox() { - CPDF_FormControl* pControl = GetFormControl(); - CFX_Color crBackground, crBorder, crText; - int iColorType; - float fc[4]; - - pControl->GetOriginalBackgroundColor(iColorType, fc); - if (iColorType > 0) - crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - pControl->GetOriginalBorderColor(iColorType, fc); - if (iColorType > 0) - crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - float fBorderWidth = (float)GetBorderWidth(); - CPWL_Dash dsBorder(3, 0, 0); - CFX_Color crLeftTop, crRightBottom; - - BorderStyle nBorderStyle = GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcWindow = GetRotatedRect(); - CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - - int32_t nStyle = 0; - CFX_WideString csWCaption = pControl->GetNormalCaption(); - if (csWCaption.GetLength() > 0) { - switch (csWCaption[0]) { - case L'l': - nStyle = PCS_CIRCLE; - break; - case L'8': - nStyle = PCS_CROSS; - break; - case L'u': - nStyle = PCS_DIAMOND; - break; - case L'n': - nStyle = PCS_SQUARE; - break; - case L'H': - nStyle = PCS_STAR; - break; - default: // L'4' - nStyle = PCS_CHECK; - break; - } - } else { - nStyle = PCS_CHECK; - } - - CFX_ByteString csAP_N_ON = - CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder); - - CFX_ByteString csAP_N_OFF = csAP_N_ON; - - switch (nBorderStyle) { - case BorderStyle::BEVELED: { - CFX_Color crTemp = crLeftTop; - crLeftTop = crRightBottom; - crRightBottom = crTemp; - break; - } - case BorderStyle::INSET: { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - break; - } - default: - break; - } - - CFX_ByteString csAP_D_ON = - CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder); - - CFX_ByteString csAP_D_OFF = csAP_D_ON; - - csAP_N_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText); - csAP_D_ON += CPWL_Utils::GetCheckBoxAppStream(rcClient, nStyle, crText); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON, - pControl->GetCheckedAPState()); - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off"); - - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON, - pControl->GetCheckedAPState()); - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off"); - - CFX_ByteString csAS = GetAppState(); - if (csAS.IsEmpty()) - SetAppState("Off"); -} - -void CPDFSDK_Widget::ResetAppearance_RadioButton() { - CPDF_FormControl* pControl = GetFormControl(); - CFX_Color crBackground, crBorder, crText; - int iColorType; - float fc[4]; - - pControl->GetOriginalBackgroundColor(iColorType, fc); - if (iColorType > 0) - crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - pControl->GetOriginalBorderColor(iColorType, fc); - if (iColorType > 0) - crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - float fBorderWidth = (float)GetBorderWidth(); - CPWL_Dash dsBorder(3, 0, 0); - CFX_Color crLeftTop; - CFX_Color crRightBottom; - BorderStyle nBorderStyle = GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcWindow = GetRotatedRect(); - CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - - int32_t nStyle = 0; - CFX_WideString csWCaption = pControl->GetNormalCaption(); - if (csWCaption.GetLength() > 0) { - switch (csWCaption[0]) { - default: // L'l': - nStyle = PCS_CIRCLE; - break; - case L'8': - nStyle = PCS_CROSS; - break; - case L'u': - nStyle = PCS_DIAMOND; - break; - case L'n': - nStyle = PCS_SQUARE; - break; - case L'H': - nStyle = PCS_STAR; - break; - case L'4': - nStyle = PCS_CHECK; - break; - } - } else { - nStyle = PCS_CIRCLE; - } - - CFX_ByteString csAP_N_ON; - CFX_FloatRect rcCenter = rcWindow.GetCenterSquare().GetDeflated(1.0f, 1.0f); - if (nStyle == PCS_CIRCLE) { - if (nBorderStyle == BorderStyle::BEVELED) { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground - 0.25f; - } else if (nBorderStyle == BorderStyle::INSET) { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5f); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75f); - } - - csAP_N_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBackground) + - CPWL_Utils::GetCircleBorderAppStream( - rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom, - nBorderStyle, dsBorder); - } else { - csAP_N_ON = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, - nBorderStyle, dsBorder); - } - - CFX_ByteString csAP_N_OFF = csAP_N_ON; - - switch (nBorderStyle) { - case BorderStyle::BEVELED: { - CFX_Color crTemp = crLeftTop; - crLeftTop = crRightBottom; - crRightBottom = crTemp; - break; - } - case BorderStyle::INSET: { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - break; - } - default: - break; - } - - CFX_ByteString csAP_D_ON; - - if (nStyle == PCS_CIRCLE) { - CFX_Color crBK = crBackground - 0.25f; - if (nBorderStyle == BorderStyle::BEVELED) { - crLeftTop = crBackground - 0.25f; - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - crBK = crBackground; - } else if (nBorderStyle == BorderStyle::INSET) { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - } - - csAP_D_ON = CPWL_Utils::GetCircleFillAppStream(rcCenter, crBK) + - CPWL_Utils::GetCircleBorderAppStream( - rcCenter, fBorderWidth, crBorder, crLeftTop, crRightBottom, - nBorderStyle, dsBorder); - } else { - csAP_D_ON = - CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + - CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder); - } - - CFX_ByteString csAP_D_OFF = csAP_D_ON; - - csAP_N_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText); - csAP_D_ON += CPWL_Utils::GetRadioButtonAppStream(rcClient, nStyle, crText); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_ON, - pControl->GetCheckedAPState()); - WriteAppearance("N", GetRotatedRect(), GetMatrix(), csAP_N_OFF, "Off"); - - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_ON, - pControl->GetCheckedAPState()); - WriteAppearance("D", GetRotatedRect(), GetMatrix(), csAP_D_OFF, "Off"); - - CFX_ByteString csAS = GetAppState(); - if (csAS.IsEmpty()) - SetAppState("Off"); -} - -void CPDFSDK_Widget::ResetAppearance_ComboBox(const CFX_WideString* sValue) { - CPDF_FormControl* pControl = GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - std::ostringstream sBody; - - CFX_FloatRect rcClient = GetClientRect(); - CFX_FloatRect rcButton = rcClient; - rcButton.left = rcButton.right - 13; - rcButton.Normalize(); - - auto pEdit = pdfium::MakeUnique(); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - - CFX_FloatRect rcEdit = rcClient; - rcEdit.right = rcButton.left; - rcEdit.Normalize(); - - pEdit->SetPlateRect(rcEdit); - pEdit->SetAlignmentV(1, true); - - float fFontSize = GetFontSize(); - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - - if (sValue) { - pEdit->SetText(*sValue); - } else { - int32_t nCurSel = pField->GetSelectedIndex(0); - if (nCurSel < 0) - pEdit->SetText(pField->GetValue()); - else - pEdit->SetText(pField->GetOptionLabel(nCurSel)); - } - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - - CFX_ByteString sEdit = - CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF()); - if (sEdit.GetLength() > 0) { - sBody << "/Tx BMC\n" - << "q\n"; - if (rcContent.Width() > rcEdit.Width() || - rcContent.Height() > rcEdit.Height()) { - sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width() - << " " << rcEdit.Height() << " re\nW\nn\n"; - } - - CFX_Color crText = GetTextPWLColor(); - sBody << "BT\n" - << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n" - << "Q\nEMC\n"; - } - - sBody << CPWL_Utils::GetDropButtonAppStream(rcButton); - - CFX_ByteString sAP = - GetBackgroundAppStream() + GetBorderAppStream() + CFX_ByteString(sBody); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP); -} - -void CPDFSDK_Widget::ResetAppearance_ListBox() { - CPDF_FormControl* pControl = GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - CFX_FloatRect rcClient = GetClientRect(); - std::ostringstream sBody; - - auto pEdit = pdfium::MakeUnique(); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - - pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f)); - - float fFontSize = GetFontSize(); - - pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); - - pEdit->Initialize(); - - std::ostringstream sList; - float fy = rcClient.top; - - int32_t nTop = pField->GetTopVisibleIndex(); - int32_t nCount = pField->CountOptions(); - int32_t nSelCount = pField->CountSelectedItems(); - - for (int32_t i = nTop; i < nCount; ++i) { - bool bSelected = false; - for (int32_t j = 0; j < nSelCount; ++j) { - if (pField->GetSelectedIndex(j) == i) { - bSelected = true; - break; - } - } - - pEdit->SetText(pField->GetOptionLabel(i)); - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - float fItemHeight = rcContent.Height(); - - if (bSelected) { - CFX_FloatRect rcItem = - CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy); - sList << "q\n" - << CPWL_Utils::GetColorAppStream( - CFX_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f, 113.0f / 255.0f), - true) - << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width() - << " " << rcItem.Height() << " re f\n" - << "Q\n"; - - sList << "BT\n" - << CPWL_Utils::GetColorAppStream(CFX_Color(COLORTYPE_GRAY, 1), true) - << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy)) - << "ET\n"; - } else { - CFX_Color crText = GetTextPWLColor(); - sList << "BT\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy)) - << "ET\n"; - } - - fy -= fItemHeight; - } - - if (sList.tellp() > 0) { - sBody << "/Tx BMC\n" - << "q\n" - << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width() - << " " << rcClient.Height() << " re\nW\nn\n"; - sBody << sList.str() << "Q\nEMC\n"; - } - - CFX_ByteString sAP = - GetBackgroundAppStream() + GetBorderAppStream() + CFX_ByteString(sBody); - - WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP); -} - -void CPDFSDK_Widget::ResetAppearance_TextField(const CFX_WideString* sValue) { - CPDF_FormControl* pControl = GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - std::ostringstream sBody; - std::ostringstream sLines; - - auto pEdit = pdfium::MakeUnique(); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map(this, m_pInterForm->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - - CFX_FloatRect rcClient = GetClientRect(); - pEdit->SetPlateRect(rcClient); - pEdit->SetAlignmentH(pControl->GetControlAlignment(), true); - - uint32_t dwFieldFlags = pField->GetFieldFlags(); - bool bMultiLine = (dwFieldFlags >> 12) & 1; - - if (bMultiLine) { - pEdit->SetMultiLine(true, true); - pEdit->SetAutoReturn(true, true); - } else { - pEdit->SetAlignmentV(1, true); - } - - uint16_t subWord = 0; - if ((dwFieldFlags >> 13) & 1) { - subWord = '*'; - pEdit->SetPasswordChar(subWord, true); - } - - int nMaxLen = pField->GetMaxLen(); - bool bCharArray = (dwFieldFlags >> 24) & 1; - float fFontSize = GetFontSize(); - -#ifdef PDF_ENABLE_XFA - CFX_WideString sValueTmp; - if (!sValue && GetMixXFAWidget()) { - sValueTmp = GetValue(true); - sValue = &sValueTmp; - } -#endif // PDF_ENABLE_XFA - - if (nMaxLen > 0) { - if (bCharArray) { - pEdit->SetCharArray(nMaxLen); - - if (IsFloatZero(fFontSize)) { - fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0), - rcClient, nMaxLen); - } - } else { - if (sValue) - nMaxLen = sValue->GetLength(); - pEdit->SetLimitChar(nMaxLen); - } - } - - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - pEdit->SetText(sValue ? *sValue : pField->GetValue()); - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream( - pEdit.get(), CFX_PointF(), nullptr, !bCharArray, subWord); - - if (sEdit.GetLength() > 0) { - sBody << "/Tx BMC\n" - << "q\n"; - if (rcContent.Width() > rcClient.Width() || - rcContent.Height() > rcClient.Height()) { - sBody << rcClient.left << " " << rcClient.bottom << " " - << rcClient.Width() << " " << rcClient.Height() << " re\nW\nn\n"; - } - CFX_Color crText = GetTextPWLColor(); - sBody << "BT\n" - << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n" - << "Q\nEMC\n"; - } - - if (bCharArray) { - switch (GetBorderStyle()) { - case BorderStyle::SOLID: { - CFX_ByteString sColor = - CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false); - if (sColor.GetLength() > 0) { - sLines << "q\n" - << GetBorderWidth() << " w\n" - << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false) - << " 2 J 0 j\n"; - - for (int32_t i = 1; i < nMaxLen; ++i) { - sLines << rcClient.left + - ((rcClient.right - rcClient.left) / nMaxLen) * i - << " " << rcClient.bottom << " m\n" - << rcClient.left + - ((rcClient.right - rcClient.left) / nMaxLen) * i - << " " << rcClient.top << " l S\n"; - } - - sLines << "Q\n"; - } - break; - } - case BorderStyle::DASH: { - CFX_ByteString sColor = - CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false); - if (sColor.GetLength() > 0) { - CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0); - - sLines << "q\n" - << GetBorderWidth() << " w\n" - << CPWL_Utils::GetColorAppStream(GetBorderPWLColor(), false) - << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] " - << dsBorder.nPhase << " d\n"; - - for (int32_t i = 1; i < nMaxLen; ++i) { - sLines << rcClient.left + - ((rcClient.right - rcClient.left) / nMaxLen) * i - << " " << rcClient.bottom << " m\n" - << rcClient.left + - ((rcClient.right - rcClient.left) / nMaxLen) * i - << " " << rcClient.top << " l S\n"; - } - - sLines << "Q\n"; - } - break; - } - default: - break; - } - } - - CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() + - CFX_ByteString(sLines) + CFX_ByteString(sBody); - WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP); -} - CFX_FloatRect CPDFSDK_Widget::GetClientRect() const { CFX_FloatRect rcWindow = GetRotatedRect(); float fBorderWidth = (float)GetBorderWidth(); @@ -1668,47 +897,6 @@ CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const { return rcPDFWindow; } -CFX_ByteString CPDFSDK_Widget::GetBackgroundAppStream() const { - CFX_Color crBackground = GetFillPWLColor(); - if (crBackground.nColorType != COLORTYPE_TRANSPARENT) - return CPWL_Utils::GetRectFillAppStream(GetRotatedRect(), crBackground); - - return ""; -} - -CFX_ByteString CPDFSDK_Widget::GetBorderAppStream() const { - CFX_FloatRect rcWindow = GetRotatedRect(); - CFX_Color crBorder = GetBorderPWLColor(); - CFX_Color crBackground = GetFillPWLColor(); - CFX_Color crLeftTop, crRightBottom; - - float fBorderWidth = (float)GetBorderWidth(); - CPWL_Dash dsBorder(3, 0, 0); - - BorderStyle nBorderStyle = GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - return CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, - crLeftTop, crRightBottom, nBorderStyle, - dsBorder); -} - CFX_Matrix CPDFSDK_Widget::GetMatrix() const { CFX_Matrix mt; CPDF_FormControl* pControl = GetFormControl(); @@ -1775,34 +963,6 @@ CFX_Color CPDFSDK_Widget::GetFillPWLColor() const { return crFill; } -void CPDFSDK_Widget::AddImageToAppearance(const CFX_ByteString& sAPType, - CPDF_Stream* pImage) { - CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP"); - CPDF_Stream* pStream = pAPDict->GetStreamFor(sAPType); - CPDF_Dictionary* pStreamDict = pStream->GetDict(); - CFX_ByteString sImageAlias = "IMG"; - - if (CPDF_Dictionary* pImageDict = pImage->GetDict()) { - sImageAlias = pImageDict->GetStringFor("Name"); - if (sImageAlias.IsEmpty()) - sImageAlias = "IMG"; - } - - CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); - CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); - if (!pStreamResList) - pStreamResList = pStreamDict->SetNewFor("Resources"); - - CPDF_Dictionary* pXObject = - pStreamResList->SetNewFor("XObject"); - pXObject->SetNewFor(sImageAlias, pDoc, pImage->GetObjNum()); -} - -void CPDFSDK_Widget::RemoveAppearance(const CFX_ByteString& sAPType) { - if (CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDictFor("AP")) - pAPDict->RemoveFor(sAPType); -} - bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type, PDFSDK_FieldAction& data, CPDFSDK_PageView* pPageView) { diff --git a/fpdfsdk/cpdfsdk_widget.h b/fpdfsdk/cpdfsdk_widget.h index 8f031cf45f..954369da1d 100644 --- a/fpdfsdk/cpdfsdk_widget.h +++ b/fpdfsdk/cpdfsdk_widget.h @@ -139,28 +139,14 @@ class CPDFSDK_Widget : public CPDFSDK_BAAnnot { CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions) override; - private: - void ResetAppearance_PushButton(); - void ResetAppearance_CheckBox(); - void ResetAppearance_RadioButton(); - void ResetAppearance_ComboBox(const CFX_WideString* sValue); - void ResetAppearance_ListBox(); - void ResetAppearance_TextField(const CFX_WideString* sValue); - + CFX_Matrix GetMatrix() const; CFX_FloatRect GetClientRect() const; CFX_FloatRect GetRotatedRect() const; - - CFX_ByteString GetBackgroundAppStream() const; - CFX_ByteString GetBorderAppStream() const; - CFX_Matrix GetMatrix() const; - CFX_Color GetTextPWLColor() const; CFX_Color GetBorderPWLColor() const; CFX_Color GetFillPWLColor() const; - void AddImageToAppearance(const CFX_ByteString& sAPType, CPDF_Stream* pImage); - void RemoveAppearance(const CFX_ByteString& sAPType); - + private: CFX_UnownedPtr const m_pInterForm; bool m_bAppModified; int32_t m_nAppAge; diff --git a/fpdfsdk/pdfwindow/cpwl_appstream.cpp b/fpdfsdk/pdfwindow/cpwl_appstream.cpp new file mode 100644 index 0000000000..2b158cdfd0 --- /dev/null +++ b/fpdfsdk/pdfwindow/cpwl_appstream.cpp @@ -0,0 +1,1558 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fpdfsdk/pdfwindow/cpwl_appstream.h" + +#include + +#include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_number.h" +#include "core/fpdfapi/parser/cpdf_reference.h" +#include "core/fpdfapi/parser/cpdf_stream.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fpdfsdk/cpdfsdk_interform.h" +#include "fpdfsdk/cpdfsdk_pageview.h" +#include "fpdfsdk/cpdfsdk_widget.h" +#include "fpdfsdk/formfiller/cba_fontmap.h" +#include "fpdfsdk/fxedit/fxet_edit.h" +#include "fpdfsdk/pdfwindow/cpwl_edit.h" +#include "fpdfsdk/pdfwindow/cpwl_icon.h" +#include "fpdfsdk/pdfwindow/cpwl_utils.h" +#include "fpdfsdk/pdfwindow/cpwl_wnd.h" + +namespace { + +CFX_ByteString GetAP_Check(const CFX_FloatRect& crBBox) { + const float fWidth = crBBox.right - crBBox.left; + const float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f), + CFX_PointF(0.29f, 0.40f)}, + {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f), + CFX_PointF(0.31f, 0.28f)}, + {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f), + CFX_PointF(0.77f, 0.67f)}, + {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f), + CFX_PointF(0.76f, 0.75f)}, + {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f), + CFX_PointF(0.68f, 0.75f)}, + {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f), + CFX_PointF(0.44f, 0.47f)}, + {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f), + CFX_PointF(0.41f, 0.58f)}, + {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f), + CFX_PointF(0.30f, 0.56f)}}; + + for (size_t i = 0; i < FX_ArraySize(pts); ++i) { + for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) { + pts[i][j].x = pts[i][j].x * fWidth + crBBox.left; + pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom; + } + } + + std::ostringstream csAP; + csAP << pts[0][0].x << " " << pts[0][0].y << " m\n"; + + for (size_t i = 0; i < FX_ArraySize(pts); ++i) { + size_t nNext = i < FX_ArraySize(pts) - 1 ? i + 1 : 0; + + float px1 = pts[i][1].x - pts[i][0].x; + float py1 = pts[i][1].y - pts[i][0].y; + float px2 = pts[i][2].x - pts[nNext][0].x; + float py2 = pts[i][2].y - pts[nNext][0].y; + + csAP << pts[i][0].x + px1 * FX_BEZIER << " " + << pts[i][0].y + py1 * FX_BEZIER << " " + << pts[nNext][0].x + px2 * FX_BEZIER << " " + << pts[nNext][0].y + py2 * FX_BEZIER << " " << pts[nNext][0].x << " " + << pts[nNext][0].y << " c\n"; + } + + return CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_Circle(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); + CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); + CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); + CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); + + csAP << pt1.x << " " << pt1.y << " m\n"; + + float px = pt2.x - pt1.x; + float py = pt2.y - pt1.y; + + csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " + << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y + << " c\n"; + + px = pt3.x - pt2.x; + py = pt2.y - pt3.y; + + csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " + << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n"; + + px = pt3.x - pt4.x; + py = pt3.y - pt4.y; + + csAP << pt3.x << " " << pt3.y - py * FX_BEZIER << " " + << pt4.x + px * FX_BEZIER << " " << pt4.y << " " << pt4.x << " " << pt4.y + << " c\n"; + + px = pt4.x - pt1.x; + py = pt1.y - pt4.y; + + csAP << pt4.x - px * FX_BEZIER << " " << pt4.y << " " << pt1.x << " " + << pt1.y - py * FX_BEZIER << " " << pt1.x << " " << pt1.y << " c\n"; + + return CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_Cross(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + csAP << crBBox.left << " " << crBBox.top << " m\n"; + csAP << crBBox.right << " " << crBBox.bottom << " l\n"; + csAP << crBBox.left << " " << crBBox.bottom << " m\n"; + csAP << crBBox.right << " " << crBBox.top << " l\n"; + + return CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_Diamond(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); + CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); + CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); + CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); + + csAP << pt1.x << " " << pt1.y << " m\n"; + csAP << pt2.x << " " << pt2.y << " l\n"; + csAP << pt3.x << " " << pt3.y << " l\n"; + csAP << pt4.x << " " << pt4.y << " l\n"; + csAP << pt1.x << " " << pt1.y << " l\n"; + + return CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_Square(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + csAP << crBBox.left << " " << crBBox.top << " m\n"; + csAP << crBBox.right << " " << crBBox.top << " l\n"; + csAP << crBBox.right << " " << crBBox.bottom << " l\n"; + csAP << crBBox.left << " " << crBBox.bottom << " l\n"; + csAP << crBBox.left << " " << crBBox.top << " l\n"; + + return CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_Star(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fRadius = (crBBox.top - crBBox.bottom) / (1 + (float)cos(FX_PI / 5.0f)); + CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f, + (crBBox.top + crBBox.bottom) / 2.0f); + + float px[5]; + float py[5]; + float fAngel = FX_PI / 10.0f; + for (int32_t i = 0; i < 5; i++) { + px[i] = ptCenter.x + fRadius * (float)cos(fAngel); + py[i] = ptCenter.y + fRadius * (float)sin(fAngel); + fAngel += FX_PI * 2 / 5.0f; + } + + csAP << px[0] << " " << py[0] << " m\n"; + + int32_t nNext = 0; + for (int32_t j = 0; j < 5; j++) { + nNext += 2; + if (nNext >= 5) + nNext -= 5; + csAP << px[nNext] << " " << py[nNext] << " l\n"; + } + + return CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, float fRotate) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(-fWidth / 2, 0); + CFX_PointF pt2(0, fHeight / 2); + CFX_PointF pt3(fWidth / 2, 0); + + float px; + float py; + + csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " " + << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " " + << crBBox.bottom + fHeight / 2 << " cm\n"; + + csAP << pt1.x << " " << pt1.y << " m\n"; + + px = pt2.x - pt1.x; + py = pt2.y - pt1.y; + + csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " + << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y + << " c\n"; + + px = pt3.x - pt2.x; + py = pt2.y - pt3.y; + + csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " + << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n"; + + return CFX_ByteString(csAP); +} + +CFX_ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + sAP << "q\n" + << CPWL_Utils::GetColorAppStream(crText, true) << GetAP_Check(rcBBox) + << "f\nQ\n"; + return CFX_ByteString(sAP); +} + +CFX_ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + sAP << "q\n" + << CPWL_Utils::GetColorAppStream(crText, true) << GetAP_Circle(rcBBox) + << "f\nQ\n"; + return CFX_ByteString(sAP); +} + +CFX_ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + sAP << "q\n" + << CPWL_Utils::GetColorAppStream(crText, false) << GetAP_Cross(rcBBox) + << "S\nQ\n"; + return CFX_ByteString(sAP); +} + +CFX_ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + sAP << "q\n1 w\n" + << CPWL_Utils::GetColorAppStream(crText, true) << GetAP_Diamond(rcBBox) + << "f\nQ\n"; + return CFX_ByteString(sAP); +} + +CFX_ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + sAP << "q\n" + << CPWL_Utils::GetColorAppStream(crText, true) << GetAP_Square(rcBBox) + << "f\nQ\n"; + return CFX_ByteString(sAP); +} + +CFX_ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox, + const CFX_Color& crText) { + std::ostringstream sAP; + sAP << "q\n" + << CPWL_Utils::GetColorAppStream(crText, true) << GetAP_Star(rcBBox) + << "f\nQ\n"; + return CFX_ByteString(sAP); +} + +CFX_ByteString GetCircleFillAppStream(const CFX_FloatRect& rect, + const CFX_Color& color) { + std::ostringstream sAppStream; + CFX_ByteString sColor = CPWL_Utils::GetColorAppStream(color, true); + if (sColor.GetLength() > 0) + sAppStream << "q\n" << sColor << GetAP_Circle(rect) << "f\nQ\n"; + return CFX_ByteString(sAppStream); +} + +CFX_ByteString GetCircleBorderAppStream(const CFX_FloatRect& rect, + float fWidth, + const CFX_Color& color, + const CFX_Color& crLeftTop, + const CFX_Color& crRightBottom, + BorderStyle nStyle, + const CPWL_Dash& dash) { + std::ostringstream sAppStream; + CFX_ByteString sColor; + + if (fWidth > 0.0f) { + sAppStream << "q\n"; + + float fHalfWidth = fWidth / 2.0f; + CFX_FloatRect rect_by_2 = rect.GetDeflated(fHalfWidth, fHalfWidth); + + float div = fHalfWidth * 0.75f; + CFX_FloatRect rect_by_75 = rect.GetDeflated(div, div); + switch (nStyle) { + default: + case BorderStyle::SOLID: + case BorderStyle::UNDERLINE: { + sColor = CPWL_Utils::GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + sAppStream << "q\n" + << fWidth << " w\n" + << sColor << GetAP_Circle(rect_by_2) << " S\nQ\n"; + } + } break; + case BorderStyle::DASH: { + sColor = CPWL_Utils::GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + sAppStream << "q\n" + << fWidth << " w\n" + << "[" << dash.nDash << " " << dash.nGap << "] " + << dash.nPhase << " d\n" + << sColor << GetAP_Circle(rect_by_2) << " S\nQ\n"; + } + } break; + case BorderStyle::BEVELED: { + sColor = CPWL_Utils::GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + sAppStream << "q\n" + << fHalfWidth << " w\n" + << sColor << GetAP_Circle(rect) << " S\nQ\n"; + } + + sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false); + if (sColor.GetLength() > 0) { + sAppStream << "q\n" + << fHalfWidth << " w\n" + << sColor << GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f) + << " S\nQ\n"; + } + + sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false); + if (sColor.GetLength() > 0) { + sAppStream << "q\n" + << fHalfWidth << " w\n" + << sColor << GetAP_HalfCircle(rect_by_75, FX_PI * 5 / 4.0f) + << " S\nQ\n"; + } + } break; + case BorderStyle::INSET: { + sColor = CPWL_Utils::GetColorAppStream(color, false); + if (sColor.GetLength() > 0) { + sAppStream << "q\n" + << fHalfWidth << " w\n" + << sColor << GetAP_Circle(rect) << " S\nQ\n"; + } + + sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false); + if (sColor.GetLength() > 0) { + sAppStream << "q\n" + << fHalfWidth << " w\n" + << sColor << GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f) + << " S\nQ\n"; + } + + sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false); + if (sColor.GetLength() > 0) { + sAppStream << "q\n" + << fHalfWidth << " w\n" + << sColor << GetAP_HalfCircle(rect_by_75, FX_PI * 5 / 4.0f) + << " S\nQ\n"; + } + } break; + } + + sAppStream << "Q\n"; + } + return CFX_ByteString(sAppStream); +} + +CFX_ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox, + int32_t nStyle, + const CFX_Color& crText) { + CFX_FloatRect rcCenter = rcBBox.GetCenterSquare(); + switch (nStyle) { + default: + case PCS_CHECK: + return GetAppStream_Check(rcCenter, crText); + case PCS_CIRCLE: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Circle(rcCenter, crText); + case PCS_CROSS: + return GetAppStream_Cross(rcCenter, crText); + case PCS_DIAMOND: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Diamond(rcCenter, crText); + case PCS_SQUARE: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Square(rcCenter, crText); + case PCS_STAR: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Star(rcCenter, crText); + } +} + +CFX_ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox, + int32_t nStyle, + const CFX_Color& crText) { + CFX_FloatRect rcCenter = rcBBox.GetCenterSquare(); + switch (nStyle) { + default: + case PCS_CHECK: + return GetAppStream_Check(rcCenter, crText); + case PCS_CIRCLE: + rcCenter.Scale(1.0f / 2.0f); + return GetAppStream_Circle(rcCenter, crText); + case PCS_CROSS: + return GetAppStream_Cross(rcCenter, crText); + case PCS_DIAMOND: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Diamond(rcCenter, crText); + case PCS_SQUARE: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Square(rcCenter, crText); + case PCS_STAR: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Star(rcCenter, crText); + } +} + +CFX_ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox, + IPVT_FontMap* pFontMap, + CPDF_Stream* pIconStream, + CPDF_IconFit& IconFit, + const CFX_WideString& sLabel, + const CFX_Color& crText, + float fFontSize, + int32_t nLayOut) { + const float fAutoFontScale = 1.0f / 3.0f; + + auto pEdit = pdfium::MakeUnique(); + pEdit->SetFontMap(pFontMap); + pEdit->SetAlignmentH(1, true); + pEdit->SetAlignmentV(1, true); + pEdit->SetMultiLine(false, true); + pEdit->SetAutoReturn(false, true); + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + pEdit->SetText(sLabel); + + CFX_FloatRect rcLabelContent = pEdit->GetContentRect(); + CPWL_Icon Icon; + PWL_CREATEPARAM cp; + cp.dwFlags = PWS_VISIBLE; + Icon.Create(cp); + Icon.SetIconFit(&IconFit); + Icon.SetPDFStream(pIconStream); + + CFX_FloatRect rcLabel; + CFX_FloatRect rcIcon; + float fWidth = 0.0f; + float fHeight = 0.0f; + + switch (nLayOut) { + case PPBL_LABEL: + rcLabel = rcBBox; + break; + case PPBL_ICON: + rcIcon = rcBBox; + break; + case PPBL_ICONTOPLABELBOTTOM: + if (pIconStream) { + if (IsFloatZero(fFontSize)) { + fHeight = rcBBox.top - rcBBox.bottom; + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, + rcBBox.bottom + fHeight * fAutoFontScale); + rcIcon = + CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top); + } else { + fHeight = rcLabelContent.Height(); + + if (rcBBox.bottom + fHeight > rcBBox.top) { + rcLabel = rcBBox; + } else { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, + rcBBox.bottom + fHeight); + rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, + rcBBox.top); + } + } + } else { + rcLabel = rcBBox; + } + break; + case PPBL_LABELTOPICONBOTTOM: + if (pIconStream) { + if (IsFloatZero(fFontSize)) { + fHeight = rcBBox.top - rcBBox.bottom; + rcLabel = + CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale, + rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, + rcLabel.bottom); + } else { + fHeight = rcLabelContent.Height(); + + if (rcBBox.bottom + fHeight > rcBBox.top) { + rcLabel = rcBBox; + } else { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight, + rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, + rcLabel.bottom); + } + } + } else { + rcLabel = rcBBox; + } + break; + case PPBL_ICONLEFTLABELRIGHT: + if (pIconStream) { + if (IsFloatZero(fFontSize)) { + fWidth = rcBBox.right - rcBBox.left; + if (rcLabelContent.Width() < fWidth * fAutoFontScale) { + rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale, + rcBBox.bottom, rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, + rcBBox.top); + } else { + if (rcLabelContent.Width() < fWidth) { + rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(), + rcBBox.bottom, rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, + rcBBox.top); + } else { + rcLabel = rcBBox; + } + } + } else { + fWidth = rcLabelContent.Width(); + if (rcBBox.left + fWidth > rcBBox.right) { + rcLabel = rcBBox; + } else { + rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom, + rcBBox.right, rcBBox.top); + rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, + rcBBox.top); + } + } + } else { + rcLabel = rcBBox; + } + break; + case PPBL_LABELLEFTICONRIGHT: + if (pIconStream) { + if (IsFloatZero(fFontSize)) { + fWidth = rcBBox.right - rcBBox.left; + if (rcLabelContent.Width() < fWidth * fAutoFontScale) { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, + rcBBox.left + fWidth * fAutoFontScale, + rcBBox.top); + rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, + rcBBox.top); + } else { + if (rcLabelContent.Width() < fWidth) { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, + rcBBox.left + rcLabelContent.Width(), + rcBBox.top); + rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, + rcBBox.top); + } else { + rcLabel = rcBBox; + } + } + } else { + fWidth = rcLabelContent.Width(); + if (rcBBox.left + fWidth > rcBBox.right) { + rcLabel = rcBBox; + } else { + rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, + rcBBox.left + fWidth, rcBBox.top); + rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, + rcBBox.top); + } + } + } else { + rcLabel = rcBBox; + } + break; + case PPBL_LABELOVERICON: + rcLabel = rcBBox; + rcIcon = rcBBox; + break; + } + + std::ostringstream sTemp; + + if (!rcIcon.IsEmpty()) { + Icon.Move(rcIcon, false, false); + sTemp << Icon.GetImageAppStream(); + } + + Icon.Destroy(); + + if (!rcLabel.IsEmpty()) { + pEdit->SetPlateRect(rcLabel); + CFX_ByteString sEdit = + CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f)); + if (sEdit.GetLength() > 0) { + sTemp << "BT\n" + << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n"; + } + } + + if (sTemp.tellp() <= 0) + return CFX_ByteString(); + + std::ostringstream sAppStream; + sAppStream << "q\n" + << rcBBox.left << " " << rcBBox.bottom << " " + << rcBBox.right - rcBBox.left << " " << rcBBox.top - rcBBox.bottom + << " re W n\n"; + sAppStream << sTemp.str().c_str() << "Q\n"; + return CFX_ByteString(sAppStream); +} + +CFX_ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox) { + if (rcBBox.IsEmpty()) + return CFX_ByteString(); + + std::ostringstream sAppStream; + sAppStream << "q\n" + << CPWL_Utils::GetColorAppStream( + CFX_Color(COLORTYPE_RGB, 220.0f / 255.0f, 220.0f / 255.0f, + 220.0f / 255.0f), + true) + << rcBBox.left << " " << rcBBox.bottom << " " + << rcBBox.right - rcBBox.left << " " << rcBBox.top - rcBBox.bottom + << " re f\n" + << "Q\n"; + + sAppStream << "q\n" + << CPWL_Utils::GetBorderAppStream( + rcBBox, 2, CFX_Color(COLORTYPE_GRAY, 0), + CFX_Color(COLORTYPE_GRAY, 1), + CFX_Color(COLORTYPE_GRAY, 0.5), BorderStyle::BEVELED, + CPWL_Dash(3, 0, 0)) + << "Q\n"; + + CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2, + (rcBBox.top + rcBBox.bottom) / 2); + if (IsFloatBigger(rcBBox.right - rcBBox.left, 6) && + IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) { + sAppStream << "q\n" + << " 0 g\n" + << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n" + << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n" + << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n" + << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n" + << "Q\n"; + } + + return CFX_ByteString(sAppStream); +} + +} // namespace + +CPWL_AppStream::CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict) + : widget_(widget), dict_(dict) {} + +CPWL_AppStream::~CPWL_AppStream() {} + +void CPWL_AppStream::SetAsPushButton() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + int32_t nLayout = 0; + switch (pControl->GetTextPosition()) { + case TEXTPOS_ICON: + nLayout = PPBL_ICON; + break; + case TEXTPOS_BELOW: + nLayout = PPBL_ICONTOPLABELBOTTOM; + break; + case TEXTPOS_ABOVE: + nLayout = PPBL_LABELTOPICONBOTTOM; + break; + case TEXTPOS_RIGHT: + nLayout = PPBL_ICONLEFTLABELRIGHT; + break; + case TEXTPOS_LEFT: + nLayout = PPBL_LABELLEFTICONRIGHT; + break; + case TEXTPOS_OVERLAID: + nLayout = PPBL_LABELOVERICON; + break; + default: + nLayout = PPBL_LABEL; + break; + } + + CFX_Color crBackground; + CFX_Color crBorder; + int iColorType; + float fc[4]; + pControl->GetOriginalBackgroundColor(iColorType, fc); + if (iColorType > 0) + crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + pControl->GetOriginalBorderColor(iColorType, fc); + if (iColorType > 0) + crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CFX_Color crText(COLORTYPE_GRAY, 0); + CFX_ByteString csNameTag; + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + float fFontSize = 12.0f; + if (da.HasFont()) + csNameTag = da.GetFont(&fFontSize); + + CFX_WideString csWCaption; + CFX_WideString csNormalCaption; + CFX_WideString csRolloverCaption; + CFX_WideString csDownCaption; + if (pControl->HasMKEntry("CA")) + csNormalCaption = pControl->GetNormalCaption(); + + if (pControl->HasMKEntry("RC")) + csRolloverCaption = pControl->GetRolloverCaption(); + + if (pControl->HasMKEntry("AC")) + csDownCaption = pControl->GetDownCaption(); + + CPDF_Stream* pNormalIcon = nullptr; + CPDF_Stream* pRolloverIcon = nullptr; + CPDF_Stream* pDownIcon = nullptr; + if (pControl->HasMKEntry("I")) + pNormalIcon = pControl->GetNormalIcon(); + + if (pControl->HasMKEntry("RI")) + pRolloverIcon = pControl->GetRolloverIcon(); + + if (pControl->HasMKEntry("IX")) + pDownIcon = pControl->GetDownIcon(); + + if (pNormalIcon) { + if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgA", false); + } + } + + if (pRolloverIcon) { + if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgB", false); + } + } + + if (pDownIcon) { + if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgC", false); + } + } + + CPDF_IconFit iconFit = pControl->GetIconFit(); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + font_map.SetAPType("N"); + + CFX_ByteString csAP = + CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + + CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, + crLeftTop, crRightBottom, nBorderStyle, + dsBorder) + + GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient, + &font_map, pNormalIcon, iconFit, csNormalCaption, + crText, fFontSize, nLayout); + + Write("N", csAP, ""); + if (pNormalIcon) + AddImage("N", pNormalIcon); + + CPDF_FormControl::HighlightingMode eHLM = pControl->GetHighlightingMode(); + if (eHLM == CPDF_FormControl::Push || eHLM == CPDF_FormControl::Toggle) { + if (csRolloverCaption.IsEmpty() && !pRolloverIcon) { + csRolloverCaption = csNormalCaption; + pRolloverIcon = pNormalIcon; + } + + font_map.SetAPType("R"); + + csAP = + CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + + CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, + crLeftTop, crRightBottom, nBorderStyle, + dsBorder) + + GetPushButtonAppStream(iconFit.GetFittingBounds() ? rcWindow : rcClient, + &font_map, pRolloverIcon, iconFit, + csRolloverCaption, crText, fFontSize, nLayout); + + Write("R", csAP, ""); + if (pRolloverIcon) + AddImage("R", pRolloverIcon); + + if (csDownCaption.IsEmpty() && !pDownIcon) { + csDownCaption = csNormalCaption; + pDownIcon = pNormalIcon; + } + + switch (nBorderStyle) { + case BorderStyle::BEVELED: { + CFX_Color crTemp = crLeftTop; + crLeftTop = crRightBottom; + crRightBottom = crTemp; + break; + } + case BorderStyle::INSET: { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + break; + } + default: + break; + } + + font_map.SetAPType("D"); + + csAP = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + + CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, + crLeftTop, crRightBottom, + nBorderStyle, dsBorder) + + GetPushButtonAppStream( + iconFit.GetFittingBounds() ? rcWindow : rcClient, &font_map, + pDownIcon, iconFit, csDownCaption, crText, fFontSize, nLayout); + + Write("D", csAP, ""); + if (pDownIcon) + AddImage("D", pDownIcon); + } else { + Remove("D"); + Remove("R"); + } +} + +void CPWL_AppStream::SetAsCheckBox() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CFX_Color crBackground, crBorder, crText; + int iColorType; + float fc[4]; + + pControl->GetOriginalBackgroundColor(iColorType, fc); + if (iColorType > 0) + crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + pControl->GetOriginalBorderColor(iColorType, fc); + if (iColorType > 0) + crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop, crRightBottom; + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + + int32_t nStyle = 0; + CFX_WideString csWCaption = pControl->GetNormalCaption(); + if (csWCaption.GetLength() > 0) { + switch (csWCaption[0]) { + case L'l': + nStyle = PCS_CIRCLE; + break; + case L'8': + nStyle = PCS_CROSS; + break; + case L'u': + nStyle = PCS_DIAMOND; + break; + case L'n': + nStyle = PCS_SQUARE; + break; + case L'H': + nStyle = PCS_STAR; + break; + default: // L'4' + nStyle = PCS_CHECK; + break; + } + } else { + nStyle = PCS_CHECK; + } + + CFX_ByteString csAP_N_ON = + CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + + CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, + crLeftTop, crRightBottom, nBorderStyle, + dsBorder); + + CFX_ByteString csAP_N_OFF = csAP_N_ON; + + switch (nBorderStyle) { + case BorderStyle::BEVELED: { + CFX_Color crTemp = crLeftTop; + crLeftTop = crRightBottom; + crRightBottom = crTemp; + break; + } + case BorderStyle::INSET: { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + break; + } + default: + break; + } + + CFX_ByteString csAP_D_ON = + CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + + CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, + crLeftTop, crRightBottom, nBorderStyle, + dsBorder); + + CFX_ByteString csAP_D_OFF = csAP_D_ON; + + csAP_N_ON += GetCheckBoxAppStream(rcClient, nStyle, crText); + csAP_D_ON += GetCheckBoxAppStream(rcClient, nStyle, crText); + + Write("N", csAP_N_ON, pControl->GetCheckedAPState()); + Write("N", csAP_N_OFF, "Off"); + + Write("D", csAP_D_ON, pControl->GetCheckedAPState()); + Write("D", csAP_D_OFF, "Off"); + + CFX_ByteString csAS = widget_->GetAppState(); + if (csAS.IsEmpty()) + widget_->SetAppState("Off"); +} + +void CPWL_AppStream::SetAsRadioButton() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CFX_Color crBackground; + CFX_Color crBorder; + CFX_Color crText; + int iColorType; + float fc[4]; + + pControl->GetOriginalBackgroundColor(iColorType, fc); + if (iColorType > 0) + crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + pControl->GetOriginalBorderColor(iColorType, fc); + if (iColorType > 0) + crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + + int32_t nStyle = 0; + CFX_WideString csWCaption = pControl->GetNormalCaption(); + if (csWCaption.GetLength() > 0) { + switch (csWCaption[0]) { + default: // L'l': + nStyle = PCS_CIRCLE; + break; + case L'8': + nStyle = PCS_CROSS; + break; + case L'u': + nStyle = PCS_DIAMOND; + break; + case L'n': + nStyle = PCS_SQUARE; + break; + case L'H': + nStyle = PCS_STAR; + break; + case L'4': + nStyle = PCS_CHECK; + break; + } + } else { + nStyle = PCS_CIRCLE; + } + + CFX_ByteString csAP_N_ON; + CFX_FloatRect rcCenter = rcWindow.GetCenterSquare().GetDeflated(1.0f, 1.0f); + if (nStyle == PCS_CIRCLE) { + if (nBorderStyle == BorderStyle::BEVELED) { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground - 0.25f; + } else if (nBorderStyle == BorderStyle::INSET) { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5f); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75f); + } + + csAP_N_ON = + GetCircleFillAppStream(rcCenter, crBackground) + + GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } else { + csAP_N_ON = CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground) + + CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, + crLeftTop, crRightBottom, + nBorderStyle, dsBorder); + } + + CFX_ByteString csAP_N_OFF = csAP_N_ON; + + switch (nBorderStyle) { + case BorderStyle::BEVELED: { + CFX_Color crTemp = crLeftTop; + crLeftTop = crRightBottom; + crRightBottom = crTemp; + break; + } + case BorderStyle::INSET: { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + break; + } + default: + break; + } + + CFX_ByteString csAP_D_ON; + + if (nStyle == PCS_CIRCLE) { + CFX_Color crBK = crBackground - 0.25f; + if (nBorderStyle == BorderStyle::BEVELED) { + crLeftTop = crBackground - 0.25f; + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + crBK = crBackground; + } else if (nBorderStyle == BorderStyle::INSET) { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + } + + csAP_D_ON = + GetCircleFillAppStream(rcCenter, crBK) + + GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } else { + csAP_D_ON = + CPWL_Utils::GetRectFillAppStream(rcWindow, crBackground - 0.25f) + + CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, + crLeftTop, crRightBottom, nBorderStyle, + dsBorder); + } + + CFX_ByteString csAP_D_OFF = csAP_D_ON; + + csAP_N_ON += GetRadioButtonAppStream(rcClient, nStyle, crText); + csAP_D_ON += GetRadioButtonAppStream(rcClient, nStyle, crText); + + Write("N", csAP_N_ON, pControl->GetCheckedAPState()); + Write("N", csAP_N_OFF, "Off"); + + Write("D", csAP_D_ON, pControl->GetCheckedAPState()); + Write("D", csAP_D_OFF, "Off"); + + CFX_ByteString csAS = widget_->GetAppState(); + if (csAS.IsEmpty()) + widget_->SetAppState("Off"); +} + +void CPWL_AppStream::SetAsComboBox(const CFX_WideString* sValue) { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + std::ostringstream sBody; + + CFX_FloatRect rcClient = widget_->GetClientRect(); + CFX_FloatRect rcButton = rcClient; + rcButton.left = rcButton.right - 13; + rcButton.Normalize(); + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + + CFX_FloatRect rcEdit = rcClient; + rcEdit.right = rcButton.left; + rcEdit.Normalize(); + + pEdit->SetPlateRect(rcEdit); + pEdit->SetAlignmentV(1, true); + + float fFontSize = widget_->GetFontSize(); + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + + if (sValue) { + pEdit->SetText(*sValue); + } else { + int32_t nCurSel = pField->GetSelectedIndex(0); + if (nCurSel < 0) + pEdit->SetText(pField->GetValue()); + else + pEdit->SetText(pField->GetOptionLabel(nCurSel)); + } + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + CFX_ByteString sEdit = + CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF()); + if (sEdit.GetLength() > 0) { + sBody << "/Tx BMC\n" + << "q\n"; + if (rcContent.Width() > rcEdit.Width() || + rcContent.Height() > rcEdit.Height()) { + sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width() + << " " << rcEdit.Height() << " re\nW\nn\n"; + } + + CFX_Color crText = widget_->GetTextPWLColor(); + sBody << "BT\n" + << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n" + << "Q\nEMC\n"; + } + + sBody << GetDropButtonAppStream(rcButton); + Write("N", + GetBackgroundAppStream() + GetBorderAppStream() + CFX_ByteString(sBody), + ""); +} + +void CPWL_AppStream::SetAsListBox() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + CFX_FloatRect rcClient = widget_->GetClientRect(); + std::ostringstream sBody; + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f)); + + float fFontSize = widget_->GetFontSize(); + pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); + pEdit->Initialize(); + + std::ostringstream sList; + float fy = rcClient.top; + + int32_t nTop = pField->GetTopVisibleIndex(); + int32_t nCount = pField->CountOptions(); + int32_t nSelCount = pField->CountSelectedItems(); + + for (int32_t i = nTop; i < nCount; ++i) { + bool bSelected = false; + for (int32_t j = 0; j < nSelCount; ++j) { + if (pField->GetSelectedIndex(j) == i) { + bSelected = true; + break; + } + } + + pEdit->SetText(pField->GetOptionLabel(i)); + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + float fItemHeight = rcContent.Height(); + + if (bSelected) { + CFX_FloatRect rcItem = + CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy); + sList << "q\n" + << CPWL_Utils::GetColorAppStream( + CFX_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f, 113.0f / 255.0f), + true) + << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width() + << " " << rcItem.Height() << " re f\n" + << "Q\n"; + + sList << "BT\n" + << CPWL_Utils::GetColorAppStream(CFX_Color(COLORTYPE_GRAY, 1), true) + << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy)) + << "ET\n"; + } else { + CFX_Color crText = widget_->GetTextPWLColor(); + sList << "BT\n" + << CPWL_Utils::GetColorAppStream(crText, true) + << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy)) + << "ET\n"; + } + + fy -= fItemHeight; + } + + if (sList.tellp() > 0) { + sBody << "/Tx BMC\n" + << "q\n" + << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width() + << " " << rcClient.Height() << " re\nW\nn\n"; + sBody << sList.str() << "Q\nEMC\n"; + } + Write("N", + GetBackgroundAppStream() + GetBorderAppStream() + CFX_ByteString(sBody), + ""); +} + +void CPWL_AppStream::SetAsTextField(const CFX_WideString* sValue) { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + std::ostringstream sBody; + std::ostringstream sLines; + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + + CFX_FloatRect rcClient = widget_->GetClientRect(); + pEdit->SetPlateRect(rcClient); + pEdit->SetAlignmentH(pControl->GetControlAlignment(), true); + + uint32_t dwFieldFlags = pField->GetFieldFlags(); + bool bMultiLine = (dwFieldFlags >> 12) & 1; + if (bMultiLine) { + pEdit->SetMultiLine(true, true); + pEdit->SetAutoReturn(true, true); + } else { + pEdit->SetAlignmentV(1, true); + } + + uint16_t subWord = 0; + if ((dwFieldFlags >> 13) & 1) { + subWord = '*'; + pEdit->SetPasswordChar(subWord, true); + } + + int nMaxLen = pField->GetMaxLen(); + bool bCharArray = (dwFieldFlags >> 24) & 1; + float fFontSize = widget_->GetFontSize(); + +#ifdef PDF_ENABLE_XFA + CFX_WideString sValueTmp; + if (!sValue && widget_->GetMixXFAWidget()) { + sValueTmp = widget_->GetValue(true); + sValue = &sValueTmp; + } +#endif // PDF_ENABLE_XFA + + if (nMaxLen > 0) { + if (bCharArray) { + pEdit->SetCharArray(nMaxLen); + + if (IsFloatZero(fFontSize)) { + fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0), + rcClient, nMaxLen); + } + } else { + if (sValue) + nMaxLen = sValue->GetLength(); + pEdit->SetLimitChar(nMaxLen); + } + } + + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + pEdit->SetText(sValue ? *sValue : pField->GetValue()); + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream( + pEdit.get(), CFX_PointF(), nullptr, !bCharArray, subWord); + + if (sEdit.GetLength() > 0) { + sBody << "/Tx BMC\n" + << "q\n"; + if (rcContent.Width() > rcClient.Width() || + rcContent.Height() > rcClient.Height()) { + sBody << rcClient.left << " " << rcClient.bottom << " " + << rcClient.Width() << " " << rcClient.Height() << " re\nW\nn\n"; + } + CFX_Color crText = widget_->GetTextPWLColor(); + sBody << "BT\n" + << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n" + << "Q\nEMC\n"; + } + + if (bCharArray) { + switch (widget_->GetBorderStyle()) { + case BorderStyle::SOLID: { + CFX_ByteString sColor = + CPWL_Utils::GetColorAppStream(widget_->GetBorderPWLColor(), false); + if (sColor.GetLength() > 0) { + sLines << "q\n" + << widget_->GetBorderWidth() << " w\n" + << CPWL_Utils::GetColorAppStream(widget_->GetBorderPWLColor(), + false) + << " 2 J 0 j\n"; + + for (int32_t i = 1; i < nMaxLen; ++i) { + sLines << rcClient.left + + ((rcClient.right - rcClient.left) / nMaxLen) * i + << " " << rcClient.bottom << " m\n" + << rcClient.left + + ((rcClient.right - rcClient.left) / nMaxLen) * i + << " " << rcClient.top << " l S\n"; + } + + sLines << "Q\n"; + } + break; + } + case BorderStyle::DASH: { + CFX_ByteString sColor = + CPWL_Utils::GetColorAppStream(widget_->GetBorderPWLColor(), false); + if (sColor.GetLength() > 0) { + CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0); + + sLines << "q\n" + << widget_->GetBorderWidth() << " w\n" + << CPWL_Utils::GetColorAppStream(widget_->GetBorderPWLColor(), + false) + << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] " + << dsBorder.nPhase << " d\n"; + + for (int32_t i = 1; i < nMaxLen; ++i) { + sLines << rcClient.left + + ((rcClient.right - rcClient.left) / nMaxLen) * i + << " " << rcClient.bottom << " m\n" + << rcClient.left + + ((rcClient.right - rcClient.left) / nMaxLen) * i + << " " << rcClient.top << " l S\n"; + } + + sLines << "Q\n"; + } + break; + } + default: + break; + } + } + + Write("N", + GetBackgroundAppStream() + GetBorderAppStream() + + CFX_ByteString(sLines) + CFX_ByteString(sBody), + ""); +} + +void CPWL_AppStream::AddImage(const CFX_ByteString& sAPType, + CPDF_Stream* pImage) { + CPDF_Stream* pStream = dict_->GetStreamFor(sAPType); + CPDF_Dictionary* pStreamDict = pStream->GetDict(); + CFX_ByteString sImageAlias = "IMG"; + + if (CPDF_Dictionary* pImageDict = pImage->GetDict()) { + sImageAlias = pImageDict->GetStringFor("Name"); + if (sImageAlias.IsEmpty()) + sImageAlias = "IMG"; + } + + CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); + if (!pStreamResList) + pStreamResList = pStreamDict->SetNewFor("Resources"); + + CPDF_Dictionary* pXObject = + pStreamResList->SetNewFor("XObject"); + pXObject->SetNewFor(sImageAlias, + widget_->GetPageView()->GetPDFDocument(), + pImage->GetObjNum()); +} + +void CPWL_AppStream::Write(const CFX_ByteString& sAPType, + const CFX_ByteString& sContents, + const CFX_ByteString& sAPState) { + CPDF_Stream* pStream = nullptr; + CPDF_Dictionary* pParentDict = nullptr; + if (sAPState.IsEmpty()) { + pParentDict = dict_.Get(); + pStream = dict_->GetStreamFor(sAPType); + } else { + CPDF_Dictionary* pAPTypeDict = dict_->GetDictFor(sAPType); + if (!pAPTypeDict) + pAPTypeDict = dict_->SetNewFor(sAPType); + + pParentDict = pAPTypeDict; + pStream = pAPTypeDict->GetStreamFor(sAPState); + } + + if (!pStream) { + CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument(); + pStream = doc->NewIndirect(); + pParentDict->SetNewFor(sAPType, doc, pStream->GetObjNum()); + } + + CPDF_Dictionary* pStreamDict = pStream->GetDict(); + if (!pStreamDict) { + auto pNewDict = pdfium::MakeUnique( + widget_->GetPDFAnnot()->GetDocument()->GetByteStringPool()); + pStreamDict = pNewDict.get(); + pStreamDict->SetNewFor("Type", "XObject"); + pStreamDict->SetNewFor("Subtype", "Form"); + pStreamDict->SetNewFor("FormType", 1); + pStream->InitStream(nullptr, 0, std::move(pNewDict)); + } + pStreamDict->SetMatrixFor("Matrix", widget_->GetMatrix()); + pStreamDict->SetRectFor("BBox", widget_->GetRotatedRect()); + pStream->SetData((uint8_t*)(sContents.c_str()), sContents.GetLength()); +} + +void CPWL_AppStream::Remove(const CFX_ByteString& sAPType) { + dict_->RemoveFor(sAPType); +} + +CFX_ByteString CPWL_AppStream::GetBackgroundAppStream() const { + CFX_Color crBackground = widget_->GetFillPWLColor(); + if (crBackground.nColorType != COLORTYPE_TRANSPARENT) + return CPWL_Utils::GetRectFillAppStream(widget_->GetRotatedRect(), + crBackground); + + return CFX_ByteString(); +} + +CFX_ByteString CPWL_AppStream::GetBorderAppStream() const { + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_Color crBorder = widget_->GetBorderPWLColor(); + CFX_Color crBackground = widget_->GetFillPWLColor(); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); + break; + default: + break; + } + + return CPWL_Utils::GetBorderAppStream(rcWindow, fBorderWidth, crBorder, + crLeftTop, crRightBottom, nBorderStyle, + dsBorder); +} diff --git a/fpdfsdk/pdfwindow/cpwl_appstream.h b/fpdfsdk/pdfwindow/cpwl_appstream.h new file mode 100644 index 0000000000..56137864ec --- /dev/null +++ b/fpdfsdk/pdfwindow/cpwl_appstream.h @@ -0,0 +1,43 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef FPDFSDK_PDFWINDOW_CPWL_APPSTREAM_H_ +#define FPDFSDK_PDFWINDOW_CPWL_APPSTREAM_H_ + +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_string.h" + +class CPDFSDK_Widget; +class CPDF_Dictionary; +class CPDF_Stream; + +class CPWL_AppStream { + public: + CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict); + ~CPWL_AppStream(); + + void SetAsPushButton(); + void SetAsCheckBox(); + void SetAsRadioButton(); + void SetAsComboBox(const CFX_WideString* sValue); + void SetAsListBox(); + void SetAsTextField(const CFX_WideString* sValue); + + private: + void AddImage(const CFX_ByteString& sAPType, CPDF_Stream* pImage); + void Write(const CFX_ByteString& sAPType, + const CFX_ByteString& sContents, + const CFX_ByteString& sAPState); + void Remove(const CFX_ByteString& sAPType); + + CFX_ByteString GetBackgroundAppStream() const; + CFX_ByteString GetBorderAppStream() const; + + CFX_UnownedPtr widget_; + CFX_UnownedPtr dict_; +}; + +#endif // FPDFSDK_PDFWINDOW_CPWL_APPSTREAM_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_utils.cpp b/fpdfsdk/pdfwindow/cpwl_utils.cpp index b21047b623..b628b292c9 100644 --- a/fpdfsdk/pdfwindow/cpwl_utils.cpp +++ b/fpdfsdk/pdfwindow/cpwl_utils.cpp @@ -14,206 +14,6 @@ #include "fpdfsdk/fxedit/fxet_edit.h" #include "fpdfsdk/pdfwindow/cpwl_icon.h" -CFX_ByteString CPWL_Utils::GetAP_Check(const CFX_FloatRect& crBBox) { - const float fWidth = crBBox.right - crBBox.left; - const float fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f), - CFX_PointF(0.29f, 0.40f)}, - {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f), - CFX_PointF(0.31f, 0.28f)}, - {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f), - CFX_PointF(0.77f, 0.67f)}, - {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f), - CFX_PointF(0.76f, 0.75f)}, - {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f), - CFX_PointF(0.68f, 0.75f)}, - {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f), - CFX_PointF(0.44f, 0.47f)}, - {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f), - CFX_PointF(0.41f, 0.58f)}, - {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f), - CFX_PointF(0.30f, 0.56f)}}; - - for (size_t i = 0; i < FX_ArraySize(pts); ++i) { - for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) { - pts[i][j].x = pts[i][j].x * fWidth + crBBox.left; - pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom; - } - } - - std::ostringstream csAP; - csAP << pts[0][0].x << " " << pts[0][0].y << " m\n"; - - for (size_t i = 0; i < FX_ArraySize(pts); ++i) { - size_t nNext = i < FX_ArraySize(pts) - 1 ? i + 1 : 0; - - float px1 = pts[i][1].x - pts[i][0].x; - float py1 = pts[i][1].y - pts[i][0].y; - float px2 = pts[i][2].x - pts[nNext][0].x; - float py2 = pts[i][2].y - pts[nNext][0].y; - - csAP << pts[i][0].x + px1 * FX_BEZIER << " " - << pts[i][0].y + py1 * FX_BEZIER << " " - << pts[nNext][0].x + px2 * FX_BEZIER << " " - << pts[nNext][0].y + py2 * FX_BEZIER << " " << pts[nNext][0].x << " " - << pts[nNext][0].y << " c\n"; - } - - return CFX_ByteString(csAP); -} - -CFX_ByteString CPWL_Utils::GetAP_Circle(const CFX_FloatRect& crBBox) { - std::ostringstream csAP; - - float fWidth = crBBox.right - crBBox.left; - float fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); - CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); - CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); - CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); - - csAP << pt1.x << " " << pt1.y << " m\n"; - - float px = pt2.x - pt1.x; - float py = pt2.y - pt1.y; - - csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " - << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y - << " c\n"; - - px = pt3.x - pt2.x; - py = pt2.y - pt3.y; - - csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " - << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n"; - - px = pt3.x - pt4.x; - py = pt3.y - pt4.y; - - csAP << pt3.x << " " << pt3.y - py * FX_BEZIER << " " - << pt4.x + px * FX_BEZIER << " " << pt4.y << " " << pt4.x << " " << pt4.y - << " c\n"; - - px = pt4.x - pt1.x; - py = pt1.y - pt4.y; - - csAP << pt4.x - px * FX_BEZIER << " " << pt4.y << " " << pt1.x << " " - << pt1.y - py * FX_BEZIER << " " << pt1.x << " " << pt1.y << " c\n"; - - return CFX_ByteString(csAP); -} - -CFX_ByteString CPWL_Utils::GetAP_Cross(const CFX_FloatRect& crBBox) { - std::ostringstream csAP; - - csAP << crBBox.left << " " << crBBox.top << " m\n"; - csAP << crBBox.right << " " << crBBox.bottom << " l\n"; - csAP << crBBox.left << " " << crBBox.bottom << " m\n"; - csAP << crBBox.right << " " << crBBox.top << " l\n"; - - return CFX_ByteString(csAP); -} - -CFX_ByteString CPWL_Utils::GetAP_Diamond(const CFX_FloatRect& crBBox) { - std::ostringstream csAP; - - float fWidth = crBBox.right - crBBox.left; - float fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); - CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); - CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); - CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); - - csAP << pt1.x << " " << pt1.y << " m\n"; - csAP << pt2.x << " " << pt2.y << " l\n"; - csAP << pt3.x << " " << pt3.y << " l\n"; - csAP << pt4.x << " " << pt4.y << " l\n"; - csAP << pt1.x << " " << pt1.y << " l\n"; - - return CFX_ByteString(csAP); -} - -CFX_ByteString CPWL_Utils::GetAP_Square(const CFX_FloatRect& crBBox) { - std::ostringstream csAP; - - csAP << crBBox.left << " " << crBBox.top << " m\n"; - csAP << crBBox.right << " " << crBBox.top << " l\n"; - csAP << crBBox.right << " " << crBBox.bottom << " l\n"; - csAP << crBBox.left << " " << crBBox.bottom << " l\n"; - csAP << crBBox.left << " " << crBBox.top << " l\n"; - - return CFX_ByteString(csAP); -} - -CFX_ByteString CPWL_Utils::GetAP_Star(const CFX_FloatRect& crBBox) { - std::ostringstream csAP; - - float fRadius = (crBBox.top - crBBox.bottom) / (1 + (float)cos(FX_PI / 5.0f)); - CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f, - (crBBox.top + crBBox.bottom) / 2.0f); - - float px[5], py[5]; - - float fAngel = FX_PI / 10.0f; - - for (int32_t i = 0; i < 5; i++) { - px[i] = ptCenter.x + fRadius * (float)cos(fAngel); - py[i] = ptCenter.y + fRadius * (float)sin(fAngel); - - fAngel += FX_PI * 2 / 5.0f; - } - - csAP << px[0] << " " << py[0] << " m\n"; - - int32_t nNext = 0; - for (int32_t j = 0; j < 5; j++) { - nNext += 2; - if (nNext >= 5) - nNext -= 5; - csAP << px[nNext] << " " << py[nNext] << " l\n"; - } - - return CFX_ByteString(csAP); -} - -CFX_ByteString CPWL_Utils::GetAP_HalfCircle(const CFX_FloatRect& crBBox, - float fRotate) { - std::ostringstream csAP; - - float fWidth = crBBox.right - crBBox.left; - float fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(-fWidth / 2, 0); - CFX_PointF pt2(0, fHeight / 2); - CFX_PointF pt3(fWidth / 2, 0); - - float px, py; - - csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " " - << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " " - << crBBox.bottom + fHeight / 2 << " cm\n"; - - csAP << pt1.x << " " << pt1.y << " m\n"; - - px = pt2.x - pt1.x; - py = pt2.y - pt1.y; - - csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " - << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y - << " c\n"; - - px = pt3.x - pt2.x; - py = pt2.y - pt3.y; - - csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " - << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n"; - - return CFX_ByteString(csAP); -} - CFX_ByteString CPWL_Utils::GetRectFillAppStream(const CFX_FloatRect& rect, const CFX_Color& color) { std::ostringstream sAppStream; @@ -228,15 +28,6 @@ CFX_ByteString CPWL_Utils::GetRectFillAppStream(const CFX_FloatRect& rect, return CFX_ByteString(sAppStream); } -CFX_ByteString CPWL_Utils::GetCircleFillAppStream(const CFX_FloatRect& rect, - const CFX_Color& color) { - std::ostringstream sAppStream; - CFX_ByteString sColor = GetColorAppStream(color, true); - if (sColor.GetLength() > 0) - sAppStream << "q\n" << sColor << CPWL_Utils::GetAP_Circle(rect) << "f\nQ\n"; - return CFX_ByteString(sAppStream); -} - CFX_ByteString CPWL_Utils::GetEditAppStream(CFX_Edit* pEdit, const CFX_PointF& ptOffset, const CPVT_WordRange* pRange, @@ -252,206 +43,6 @@ CFX_ByteString CPWL_Utils::GetEditSelAppStream(CFX_Edit* pEdit, return CFX_Edit::GetSelectAppearanceStream(pEdit, ptOffset, pRange); } -CFX_ByteString CPWL_Utils::GetPushButtonAppStream(const CFX_FloatRect& rcBBox, - IPVT_FontMap* pFontMap, - CPDF_Stream* pIconStream, - CPDF_IconFit& IconFit, - const CFX_WideString& sLabel, - const CFX_Color& crText, - float fFontSize, - int32_t nLayOut) { - const float fAutoFontScale = 1.0f / 3.0f; - - auto pEdit = pdfium::MakeUnique(); - pEdit->SetFontMap(pFontMap); - pEdit->SetAlignmentH(1, true); - pEdit->SetAlignmentV(1, true); - pEdit->SetMultiLine(false, true); - pEdit->SetAutoReturn(false, true); - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - pEdit->SetText(sLabel); - - CFX_FloatRect rcLabelContent = pEdit->GetContentRect(); - CPWL_Icon Icon; - PWL_CREATEPARAM cp; - cp.dwFlags = PWS_VISIBLE; - Icon.Create(cp); - Icon.SetIconFit(&IconFit); - Icon.SetPDFStream(pIconStream); - - CFX_FloatRect rcLabel; - CFX_FloatRect rcIcon; - float fWidth = 0.0f; - float fHeight = 0.0f; - - switch (nLayOut) { - case PPBL_LABEL: - rcLabel = rcBBox; - break; - case PPBL_ICON: - rcIcon = rcBBox; - break; - case PPBL_ICONTOPLABELBOTTOM: - if (pIconStream) { - if (IsFloatZero(fFontSize)) { - fHeight = rcBBox.top - rcBBox.bottom; - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, - rcBBox.bottom + fHeight * fAutoFontScale); - rcIcon = - CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top); - } else { - fHeight = rcLabelContent.Height(); - - if (rcBBox.bottom + fHeight > rcBBox.top) { - rcLabel = rcBBox; - } else { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, - rcBBox.bottom + fHeight); - rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, - rcBBox.top); - } - } - } else { - rcLabel = rcBBox; - } - break; - case PPBL_LABELTOPICONBOTTOM: - if (pIconStream) { - if (IsFloatZero(fFontSize)) { - fHeight = rcBBox.top - rcBBox.bottom; - rcLabel = - CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale, - rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, - rcLabel.bottom); - } else { - fHeight = rcLabelContent.Height(); - - if (rcBBox.bottom + fHeight > rcBBox.top) { - rcLabel = rcBBox; - } else { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight, - rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, - rcLabel.bottom); - } - } - } else { - rcLabel = rcBBox; - } - break; - case PPBL_ICONLEFTLABELRIGHT: - if (pIconStream) { - if (IsFloatZero(fFontSize)) { - fWidth = rcBBox.right - rcBBox.left; - if (rcLabelContent.Width() < fWidth * fAutoFontScale) { - rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale, - rcBBox.bottom, rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, - rcBBox.top); - } else { - if (rcLabelContent.Width() < fWidth) { - rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(), - rcBBox.bottom, rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, - rcBBox.top); - } else { - rcLabel = rcBBox; - } - } - } else { - fWidth = rcLabelContent.Width(); - if (rcBBox.left + fWidth > rcBBox.right) { - rcLabel = rcBBox; - } else { - rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom, - rcBBox.right, rcBBox.top); - rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, - rcBBox.top); - } - } - } else { - rcLabel = rcBBox; - } - break; - case PPBL_LABELLEFTICONRIGHT: - if (pIconStream) { - if (IsFloatZero(fFontSize)) { - fWidth = rcBBox.right - rcBBox.left; - if (rcLabelContent.Width() < fWidth * fAutoFontScale) { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, - rcBBox.left + fWidth * fAutoFontScale, - rcBBox.top); - rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, - rcBBox.top); - } else { - if (rcLabelContent.Width() < fWidth) { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, - rcBBox.left + rcLabelContent.Width(), - rcBBox.top); - rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, - rcBBox.top); - } else { - rcLabel = rcBBox; - } - } - } else { - fWidth = rcLabelContent.Width(); - if (rcBBox.left + fWidth > rcBBox.right) { - rcLabel = rcBBox; - } else { - rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, - rcBBox.left + fWidth, rcBBox.top); - rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, - rcBBox.top); - } - } - } else { - rcLabel = rcBBox; - } - break; - case PPBL_LABELOVERICON: - rcLabel = rcBBox; - rcIcon = rcBBox; - break; - } - - std::ostringstream sTemp; - - if (!rcIcon.IsEmpty()) { - Icon.Move(rcIcon, false, false); - sTemp << Icon.GetImageAppStream(); - } - - Icon.Destroy(); - - if (!rcLabel.IsEmpty()) { - pEdit->SetPlateRect(rcLabel); - CFX_ByteString sEdit = - CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f)); - if (sEdit.GetLength() > 0) { - sTemp << "BT\n" - << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n"; - } - } - - if (sTemp.tellp() <= 0) - return CFX_ByteString(); - - std::ostringstream sAppStream; - sAppStream << "q\n" - << rcBBox.left << " " << rcBBox.bottom << " " - << rcBBox.right - rcBBox.left << " " << rcBBox.top - rcBBox.bottom - << " re W n\n"; - sAppStream << sTemp.str().c_str() << "Q\n"; - return CFX_ByteString(sAppStream); -} - CFX_ByteString CPWL_Utils::GetColorAppStream(const CFX_Color& color, const bool& bFillOrStroke) { std::ostringstream sColorStream; @@ -591,250 +182,3 @@ CFX_ByteString CPWL_Utils::GetBorderAppStream(const CFX_FloatRect& rect, return CFX_ByteString(sAppStream); } - -CFX_ByteString CPWL_Utils::GetCircleBorderAppStream( - const CFX_FloatRect& rect, - float fWidth, - const CFX_Color& color, - const CFX_Color& crLeftTop, - const CFX_Color& crRightBottom, - BorderStyle nStyle, - const CPWL_Dash& dash) { - std::ostringstream sAppStream; - CFX_ByteString sColor; - - if (fWidth > 0.0f) { - sAppStream << "q\n"; - - float fHalfWidth = fWidth / 2.0f; - CFX_FloatRect rect_by_2 = rect.GetDeflated(fHalfWidth, fHalfWidth); - - float div = fHalfWidth * 0.75f; - CFX_FloatRect rect_by_75 = rect.GetDeflated(div, div); - switch (nStyle) { - default: - case BorderStyle::SOLID: - case BorderStyle::UNDERLINE: { - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" - << fWidth << " w\n" - << sColor << CPWL_Utils::GetAP_Circle(rect_by_2) - << " S\nQ\n"; - } - } break; - case BorderStyle::DASH: { - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" - << fWidth << " w\n" - << "[" << dash.nDash << " " << dash.nGap << "] " - << dash.nPhase << " d\n" - << sColor << CPWL_Utils::GetAP_Circle(rect_by_2) - << " S\nQ\n"; - } - } break; - case BorderStyle::BEVELED: { - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" - << fHalfWidth << " w\n" - << sColor << CPWL_Utils::GetAP_Circle(rect) << " S\nQ\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" - << fHalfWidth << " w\n" - << sColor - << CPWL_Utils::GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f) - << " S\nQ\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" - << fHalfWidth << " w\n" - << sColor - << CPWL_Utils::GetAP_HalfCircle(rect_by_75, - FX_PI * 5 / 4.0f) - << " S\nQ\n"; - } - } break; - case BorderStyle::INSET: { - sColor = CPWL_Utils::GetColorAppStream(color, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" - << fHalfWidth << " w\n" - << sColor << CPWL_Utils::GetAP_Circle(rect) << " S\nQ\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" - << fHalfWidth << " w\n" - << sColor - << CPWL_Utils::GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f) - << " S\nQ\n"; - } - - sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false); - if (sColor.GetLength() > 0) { - sAppStream << "q\n" - << fHalfWidth << " w\n" - << sColor - << CPWL_Utils::GetAP_HalfCircle(rect_by_75, - FX_PI * 5 / 4.0f) - << " S\nQ\n"; - } - } break; - } - - sAppStream << "Q\n"; - } - - return CFX_ByteString(sAppStream); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Check(const CFX_FloatRect& rcBBox, - const CFX_Color& crText) { - std::ostringstream sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Check(rcBBox) << "f\nQ\n"; - return CFX_ByteString(sAP); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Circle(const CFX_FloatRect& rcBBox, - const CFX_Color& crText) { - std::ostringstream sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Circle(rcBBox) << "f\nQ\n"; - return CFX_ByteString(sAP); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Cross(const CFX_FloatRect& rcBBox, - const CFX_Color& crText) { - std::ostringstream sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, false) - << CPWL_Utils::GetAP_Cross(rcBBox) << "S\nQ\n"; - return CFX_ByteString(sAP); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Diamond(const CFX_FloatRect& rcBBox, - const CFX_Color& crText) { - std::ostringstream sAP; - sAP << "q\n1 w\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Diamond(rcBBox) << "f\nQ\n"; - return CFX_ByteString(sAP); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Square(const CFX_FloatRect& rcBBox, - const CFX_Color& crText) { - std::ostringstream sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Square(rcBBox) << "f\nQ\n"; - return CFX_ByteString(sAP); -} - -CFX_ByteString CPWL_Utils::GetAppStream_Star(const CFX_FloatRect& rcBBox, - const CFX_Color& crText) { - std::ostringstream sAP; - sAP << "q\n" - << CPWL_Utils::GetColorAppStream(crText, true) - << CPWL_Utils::GetAP_Star(rcBBox) << "f\nQ\n"; - return CFX_ByteString(sAP); -} - -CFX_ByteString CPWL_Utils::GetCheckBoxAppStream(const CFX_FloatRect& rcBBox, - int32_t nStyle, - const CFX_Color& crText) { - CFX_FloatRect rcCenter = rcBBox.GetCenterSquare(); - switch (nStyle) { - default: - case PCS_CHECK: - return GetAppStream_Check(rcCenter, crText); - case PCS_CIRCLE: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Circle(rcCenter, crText); - case PCS_CROSS: - return GetAppStream_Cross(rcCenter, crText); - case PCS_DIAMOND: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Diamond(rcCenter, crText); - case PCS_SQUARE: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Square(rcCenter, crText); - case PCS_STAR: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Star(rcCenter, crText); - } -} - -CFX_ByteString CPWL_Utils::GetRadioButtonAppStream(const CFX_FloatRect& rcBBox, - int32_t nStyle, - const CFX_Color& crText) { - CFX_FloatRect rcCenter = rcBBox.GetCenterSquare(); - switch (nStyle) { - default: - case PCS_CHECK: - return GetAppStream_Check(rcCenter, crText); - case PCS_CIRCLE: - rcCenter.Scale(1.0f / 2.0f); - return GetAppStream_Circle(rcCenter, crText); - case PCS_CROSS: - return GetAppStream_Cross(rcCenter, crText); - case PCS_DIAMOND: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Diamond(rcCenter, crText); - case PCS_SQUARE: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Square(rcCenter, crText); - case PCS_STAR: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Star(rcCenter, crText); - } -} - -CFX_ByteString CPWL_Utils::GetDropButtonAppStream(const CFX_FloatRect& rcBBox) { - if (rcBBox.IsEmpty()) - return CFX_ByteString(); - - std::ostringstream sAppStream; - sAppStream << "q\n" - << CPWL_Utils::GetColorAppStream( - CFX_Color(COLORTYPE_RGB, 220.0f / 255.0f, 220.0f / 255.0f, - 220.0f / 255.0f), - true) - << rcBBox.left << " " << rcBBox.bottom << " " - << rcBBox.right - rcBBox.left << " " << rcBBox.top - rcBBox.bottom - << " re f\n" - << "Q\n"; - - sAppStream << "q\n" - << CPWL_Utils::GetBorderAppStream( - rcBBox, 2, CFX_Color(COLORTYPE_GRAY, 0), - CFX_Color(COLORTYPE_GRAY, 1), - CFX_Color(COLORTYPE_GRAY, 0.5), BorderStyle::BEVELED, - CPWL_Dash(3, 0, 0)) - << "Q\n"; - - CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2, - (rcBBox.top + rcBBox.bottom) / 2); - if (IsFloatBigger(rcBBox.right - rcBBox.left, 6) && - IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) { - sAppStream << "q\n" - << " 0 g\n" - << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n" - << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n" - << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n" - << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n" - << "Q\n"; - } - - return CFX_ByteString(sAppStream); -} diff --git a/fpdfsdk/pdfwindow/cpwl_utils.h b/fpdfsdk/pdfwindow/cpwl_utils.h index 67876edbc3..9445de3277 100644 --- a/fpdfsdk/pdfwindow/cpwl_utils.h +++ b/fpdfsdk/pdfwindow/cpwl_utils.h @@ -41,31 +41,8 @@ class CPWL_Utils { const CFX_Color& crRightBottom, BorderStyle nStyle, const CPWL_Dash& dash); - static CFX_ByteString GetCircleBorderAppStream(const CFX_FloatRect& rect, - float fWidth, - const CFX_Color& color, - const CFX_Color& crLeftTop, - const CFX_Color& crRightBottom, - BorderStyle nStyle, - const CPWL_Dash& dash); static CFX_ByteString GetRectFillAppStream(const CFX_FloatRect& rect, const CFX_Color& color); - static CFX_ByteString GetCircleFillAppStream(const CFX_FloatRect& rect, - const CFX_Color& color); - static CFX_ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox, - IPVT_FontMap* pFontMap, - CPDF_Stream* pIconStream, - CPDF_IconFit& IconFit, - const CFX_WideString& sLabel, - const CFX_Color& crText, - float fFontSize, - int32_t nLayOut); - static CFX_ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox, - int32_t nStyle, - const CFX_Color& crText); - static CFX_ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox, - int32_t nStyle, - const CFX_Color& crText); static CFX_ByteString GetEditAppStream(CFX_Edit* pEdit, const CFX_PointF& ptOffset, const CPVT_WordRange* pRange = nullptr, @@ -75,30 +52,6 @@ class CPWL_Utils { CFX_Edit* pEdit, const CFX_PointF& ptOffset, const CPVT_WordRange* pRange = nullptr); - static CFX_ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox); - - private: - static CFX_ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox, - const CFX_Color& crText); - static CFX_ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox, - const CFX_Color& crText); - static CFX_ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox, - const CFX_Color& crText); - static CFX_ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox, - const CFX_Color& crText); - static CFX_ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox, - const CFX_Color& crText); - static CFX_ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox, - const CFX_Color& crText); - - static CFX_ByteString GetAP_Check(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Circle(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Cross(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Diamond(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Square(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_Star(const CFX_FloatRect& crBBox); - static CFX_ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, - float fRotate); }; #endif // FPDFSDK_PDFWINDOW_CPWL_UTILS_H_ -- cgit v1.2.3