Pdfium 27d718ebb2989631d6b4d3425e1fceb4b3bc795b
Same as used by Chrome for Android 65.0.3325.109
- use system's zlib, freetype, libjpeg
- don't use xfa, v8, skia
Test: atest CtsPdfTestCases
Fixes: 72134075
Change-Id: Ic144d41e667a0c9310b69625b53850dec5fb3006
diff --git a/fpdfsdk/DEPS b/fpdfsdk/DEPS
index e077225..95ddfe1 100644
--- a/fpdfsdk/DEPS
+++ b/fpdfsdk/DEPS
@@ -1,9 +1,10 @@
include_rules = [
'+core',
+ '+fxjs',
'+public',
'+v8',
'+xfa/fwl',
- '+xfa/fxbarcode',
+ '+fxbarcode',
'+xfa/fxfa',
'+xfa/fxgraphics',
]
diff --git a/fpdfsdk/cba_annotiterator.cpp b/fpdfsdk/cba_annotiterator.cpp
index cc842ba..d1c9599 100644
--- a/fpdfsdk/cba_annotiterator.cpp
+++ b/fpdfsdk/cba_annotiterator.cpp
@@ -34,7 +34,7 @@
m_pPageView(pPageView),
m_nAnnotSubtype(nAnnotSubtype) {
CPDF_Page* pPDFPage = m_pPageView->GetPDFPage();
- CFX_ByteString sTabs = pPDFPage->m_pFormDict->GetStringFor("Tabs");
+ ByteString sTabs = pPDFPage->m_pFormDict->GetStringFor("Tabs");
if (sTabs == "R")
m_eTabOrder = ROW;
else if (sTabs == "C")
@@ -73,7 +73,7 @@
}
void CBA_AnnotIterator::CollectAnnots(std::vector<CPDFSDK_Annot*>* pArray) {
- for (auto pAnnot : m_pPageView->GetAnnotList()) {
+ for (auto* pAnnot : m_pPageView->GetAnnotList()) {
if (pAnnot->GetAnnotSubtype() == m_nAnnotSubtype &&
!pAnnot->IsSignatureWidget()) {
pArray->push_back(pAnnot);
@@ -113,7 +113,7 @@
while (!sa.empty()) {
int nLeftTopIndex = -1;
- FX_FLOAT fTop = 0.0f;
+ float fTop = 0.0f;
for (int i = sa.size() - 1; i >= 0; i--) {
CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
if (rcAnnot.top > fTop) {
@@ -129,7 +129,7 @@
std::vector<size_t> aSelect;
for (size_t i = 0; i < sa.size(); ++i) {
CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
- FX_FLOAT fCenterY = (rcAnnot.top + rcAnnot.bottom) / 2.0f;
+ float fCenterY = (rcAnnot.top + rcAnnot.bottom) / 2.0f;
if (fCenterY > rcLeftTop.bottom && fCenterY < rcLeftTop.top)
aSelect.push_back(i);
}
@@ -145,7 +145,7 @@
while (!sa.empty()) {
int nLeftTopIndex = -1;
- FX_FLOAT fLeft = -1.0f;
+ float fLeft = -1.0f;
for (int i = sa.size() - 1; i >= 0; --i) {
CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
if (fLeft < 0) {
@@ -164,7 +164,7 @@
std::vector<size_t> aSelect;
for (size_t i = 0; i < sa.size(); ++i) {
CFX_FloatRect rcAnnot = GetAnnotRect(sa[i]);
- FX_FLOAT fCenterX = (rcAnnot.left + rcAnnot.right) / 2.0f;
+ float fCenterX = (rcAnnot.left + rcAnnot.right) / 2.0f;
if (fCenterX > rcLeftTop.left && fCenterX < rcLeftTop.right)
aSelect.push_back(i);
}
diff --git a/fpdfsdk/cba_annotiterator.h b/fpdfsdk/cba_annotiterator.h
index 5cbe8e3..8f9768d 100644
--- a/fpdfsdk/cba_annotiterator.h
+++ b/fpdfsdk/cba_annotiterator.h
@@ -12,6 +12,7 @@
#include "core/fpdfdoc/cpdf_annot.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/unowned_ptr.h"
class CPDFSDK_Annot;
class CPDFSDK_PageView;
@@ -37,7 +38,7 @@
std::vector<size_t>* aSelect);
TabOrder m_eTabOrder;
- CPDFSDK_PageView* m_pPageView;
+ UnownedPtr<CPDFSDK_PageView> m_pPageView;
CPDF_Annot::Subtype m_nAnnotSubtype;
std::vector<CPDFSDK_Annot*> m_Annots;
};
diff --git a/fpdfsdk/cfx_systemhandler.cpp b/fpdfsdk/cfx_systemhandler.cpp
index b6dc19d..bbb0293 100644
--- a/fpdfsdk/cfx_systemhandler.cpp
+++ b/fpdfsdk/cfx_systemhandler.cpp
@@ -9,6 +9,8 @@
#include <memory>
#include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fxcrt/fx_codepage.h"
+#include "core/fxge/cfx_font.h"
#include "core/fxge/cfx_fontmapper.h"
#include "core/fxge/cfx_fontmgr.h"
#include "core/fxge/cfx_gemodule.h"
@@ -21,20 +23,26 @@
namespace {
int CharSet2CP(int charset) {
- if (charset == FXFONT_SHIFTJIS_CHARSET)
- return 932;
- if (charset == FXFONT_GB2312_CHARSET)
- return 936;
- if (charset == FXFONT_HANGUL_CHARSET)
- return 949;
- if (charset == FXFONT_CHINESEBIG5_CHARSET)
- return 950;
- return 0;
+ if (charset == FX_CHARSET_ShiftJIS)
+ return FX_CODEPAGE_ShiftJIS;
+ if (charset == FX_CHARSET_ChineseSimplified)
+ return FX_CODEPAGE_ChineseSimplified;
+ if (charset == FX_CHARSET_Hangul)
+ return FX_CODEPAGE_Hangul;
+ if (charset == FX_CHARSET_ChineseTraditional)
+ return FX_CODEPAGE_ChineseTraditional;
+ return FX_CODEPAGE_DefANSI;
}
} // namespace
-void CFX_SystemHandler::InvalidateRect(CPDFSDK_Widget* widget, FX_RECT rect) {
+CFX_SystemHandler::CFX_SystemHandler(CPDFSDK_FormFillEnvironment* pFormFillEnv)
+ : m_pFormFillEnv(pFormFillEnv) {}
+
+CFX_SystemHandler::~CFX_SystemHandler() {}
+
+void CFX_SystemHandler::InvalidateRect(CPDFSDK_Widget* widget,
+ const CFX_FloatRect& rect) {
CPDFSDK_PageView* pPageView = widget->GetPageView();
UnderlyingPageType* pPage = widget->GetUnderlyingPage();
if (!pPage || !pPageView)
@@ -43,17 +51,15 @@
CFX_Matrix page2device;
pPageView->GetCurrentMatrix(page2device);
- CFX_Matrix device2page;
- device2page.SetReverse(page2device);
+ CFX_Matrix device2page = page2device.GetInverse();
- CFX_PointF left_top = device2page.Transform(CFX_PointF(
- static_cast<FX_FLOAT>(rect.left), static_cast<FX_FLOAT>(rect.top)));
- CFX_PointF right_bottom = device2page.Transform(CFX_PointF(
- static_cast<FX_FLOAT>(rect.right), static_cast<FX_FLOAT>(rect.bottom)));
+ CFX_PointF left_top = device2page.Transform(CFX_PointF(rect.left, rect.top));
+ CFX_PointF right_bottom =
+ device2page.Transform(CFX_PointF(rect.right, rect.bottom));
CFX_FloatRect rcPDF(left_top.x, right_bottom.y, right_bottom.x, left_top.y);
rcPDF.Normalize();
- m_pFormFillEnv->Invalidate(pPage, rcPDF.ToFxRect());
+ m_pFormFillEnv->Invalidate(pPage, rcPDF.GetOuterRect());
}
void CFX_SystemHandler::OutputSelectedRect(CFFL_FormFiller* pFormFiller,
@@ -84,7 +90,7 @@
m_pFormFillEnv->SetCursor(nCursorType);
}
-bool CFX_SystemHandler::FindNativeTrueTypeFont(CFX_ByteString sFontFaceName) {
+bool CFX_SystemHandler::FindNativeTrueTypeFont(ByteString sFontFaceName) {
CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr();
if (!pFontMgr)
return false;
@@ -97,11 +103,11 @@
pFontMapper->LoadInstalledFonts();
for (const auto& font : pFontMapper->m_InstalledTTFonts) {
- if (font.Compare(sFontFaceName.AsStringC()))
+ if (font.Compare(sFontFaceName.AsStringView()))
return true;
}
for (const auto& fontPair : pFontMapper->m_LocalizedTTFonts) {
- if (fontPair.first.Compare(sFontFaceName.AsStringC()))
+ if (fontPair.first.Compare(sFontFaceName.AsStringView()))
return true;
}
return false;
@@ -109,12 +115,12 @@
CPDF_Font* CFX_SystemHandler::AddNativeTrueTypeFontToPDF(
CPDF_Document* pDoc,
- CFX_ByteString sFontFaceName,
+ ByteString sFontFaceName,
uint8_t nCharset) {
if (!pDoc)
return nullptr;
- std::unique_ptr<CFX_Font> pFXFont(new CFX_Font);
+ auto pFXFont = pdfium::MakeUnique<CFX_Font>();
pFXFont->LoadSubst(sFontFaceName, true, 0, 0, 0, CharSet2CP(nCharset), false);
return pDoc->AddFont(pFXFont.get(), nCharset, false);
}
@@ -127,15 +133,3 @@
void CFX_SystemHandler::KillTimer(int32_t nID) {
m_pFormFillEnv->KillTimer(nID);
}
-
-bool CFX_SystemHandler::IsSHIFTKeyDown(uint32_t nFlag) const {
- return !!m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
-}
-
-bool CFX_SystemHandler::IsCTRLKeyDown(uint32_t nFlag) const {
- return !!m_pFormFillEnv->IsCTRLKeyDown(nFlag);
-}
-
-bool CFX_SystemHandler::IsALTKeyDown(uint32_t nFlag) const {
- return !!m_pFormFillEnv->IsALTKeyDown(nFlag);
-}
diff --git a/fpdfsdk/cfx_systemhandler.h b/fpdfsdk/cfx_systemhandler.h
index 82cfc53..f9138cc 100644
--- a/fpdfsdk/cfx_systemhandler.h
+++ b/fpdfsdk/cfx_systemhandler.h
@@ -8,7 +8,9 @@
#define FPDFSDK_CFX_SYSTEMHANDLER_H_
#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/unowned_ptr.h"
using TimerCallback = void (*)(int32_t idEvent);
@@ -49,30 +51,23 @@
class CFX_SystemHandler {
public:
- explicit CFX_SystemHandler(CPDFSDK_FormFillEnvironment* pFormFillEnv)
- : m_pFormFillEnv(pFormFillEnv) {}
- ~CFX_SystemHandler() {}
+ explicit CFX_SystemHandler(CPDFSDK_FormFillEnvironment* pFormFillEnv);
+ ~CFX_SystemHandler();
- void InvalidateRect(CPDFSDK_Widget* widget, FX_RECT rect);
+ void InvalidateRect(CPDFSDK_Widget* widget, const CFX_FloatRect& rect);
void OutputSelectedRect(CFFL_FormFiller* pFormFiller, CFX_FloatRect& rect);
bool IsSelectionImplemented() const;
-
void SetCursor(int32_t nCursorType);
-
- bool FindNativeTrueTypeFont(CFX_ByteString sFontFaceName);
+ bool FindNativeTrueTypeFont(ByteString sFontFaceName);
CPDF_Font* AddNativeTrueTypeFontToPDF(CPDF_Document* pDoc,
- CFX_ByteString sFontFaceName,
+ ByteString sFontFaceName,
uint8_t nCharset);
int32_t SetTimer(int32_t uElapse, TimerCallback lpTimerFunc);
void KillTimer(int32_t nID);
- bool IsSHIFTKeyDown(uint32_t nFlag) const;
- bool IsCTRLKeyDown(uint32_t nFlag) const;
- bool IsALTKeyDown(uint32_t nFlag) const;
-
private:
- CPDFSDK_FormFillEnvironment* const m_pFormFillEnv;
+ UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
};
#endif // FPDFSDK_CFX_SYSTEMHANDLER_H_
diff --git a/fpdfsdk/cpdfsdk_annot.cpp b/fpdfsdk/cpdfsdk_annot.cpp
index 4dcce48..e105ed9 100644
--- a/fpdfsdk/cpdfsdk_annot.cpp
+++ b/fpdfsdk/cpdfsdk_annot.cpp
@@ -23,7 +23,7 @@
} // namespace
CPDFSDK_Annot::CPDFSDK_Annot(CPDFSDK_PageView* pPageView)
- : m_pPageView(pPageView), m_bSelected(false) {}
+ : m_pPageView(pPageView) {}
CPDFSDK_Annot::~CPDFSDK_Annot() {}
@@ -43,11 +43,11 @@
#endif // PDF_ENABLE_XFA
-FX_FLOAT CPDFSDK_Annot::GetMinWidth() const {
+float CPDFSDK_Annot::GetMinWidth() const {
return kMinWidth;
}
-FX_FLOAT CPDFSDK_Annot::GetMinHeight() const {
+float CPDFSDK_Annot::GetMinHeight() const {
return kMinHeight;
}
@@ -73,18 +73,6 @@
return CFX_FloatRect();
}
-void CPDFSDK_Annot::Annot_OnDraw(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- CPDF_RenderOptions* pOptions) {}
-
-bool CPDFSDK_Annot::IsSelected() {
- return m_bSelected;
-}
-
-void CPDFSDK_Annot::SetSelected(bool bSelected) {
- m_bSelected = bSelected;
-}
-
UnderlyingPageType* CPDFSDK_Annot::GetUnderlyingPage() {
#ifdef PDF_ENABLE_XFA
return GetPDFXFAPage();
diff --git a/fpdfsdk/cpdfsdk_annot.h b/fpdfsdk/cpdfsdk_annot.h
index 36e7b56..a6c4066 100644
--- a/fpdfsdk/cpdfsdk_annot.h
+++ b/fpdfsdk/cpdfsdk_annot.h
@@ -10,8 +10,8 @@
#include "core/fpdfdoc/cpdf_aaction.h"
#include "core/fpdfdoc/cpdf_annot.h"
#include "core/fpdfdoc/cpdf_defaultappearance.h"
-#include "core/fxcrt/cfx_observable.h"
-#include "core/fxcrt/fx_basic.h"
+#include "core/fxcrt/observable.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/cfx_systemhandler.h"
#include "fpdfsdk/fsdk_common.h"
#include "fpdfsdk/fsdk_define.h"
@@ -22,7 +22,7 @@
class CPDF_RenderOptions;
class CPDFSDK_PageView;
-class CPDFSDK_Annot : public CFX_Observable<CPDFSDK_Annot> {
+class CPDFSDK_Annot : public Observable<CPDFSDK_Annot> {
public:
explicit CPDFSDK_Annot(CPDFSDK_PageView* pPageView);
virtual ~CPDFSDK_Annot();
@@ -32,18 +32,14 @@
virtual CXFA_FFWidget* GetXFAWidget() const;
#endif // PDF_ENABLE_XFA
- virtual FX_FLOAT GetMinWidth() const;
- virtual FX_FLOAT GetMinHeight() const;
+ virtual float GetMinWidth() const;
+ virtual float GetMinHeight() const;
virtual int GetLayoutOrder() const;
virtual CPDF_Annot* GetPDFAnnot() const;
virtual CPDF_Annot::Subtype GetAnnotSubtype() const;
virtual bool IsSignatureWidget() const;
virtual CFX_FloatRect GetRect() const;
-
virtual void SetRect(const CFX_FloatRect& rect);
- virtual void Annot_OnDraw(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- CPDF_RenderOptions* pOptions);
UnderlyingPageType* GetUnderlyingPage();
CPDF_Page* GetPDFPage();
@@ -51,15 +47,10 @@
CPDFXFA_Page* GetPDFXFAPage();
#endif // PDF_ENABLE_XFA
- void SetPage(CPDFSDK_PageView* pPageView);
- CPDFSDK_PageView* GetPageView() const { return m_pPageView; }
-
- bool IsSelected();
- void SetSelected(bool bSelected);
+ CPDFSDK_PageView* GetPageView() const { return m_pPageView.Get(); }
protected:
- CPDFSDK_PageView* m_pPageView;
- bool m_bSelected;
+ UnownedPtr<CPDFSDK_PageView> const m_pPageView;
};
#endif // FPDFSDK_CPDFSDK_ANNOT_H_
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
index c499067..2966b4d 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
@@ -17,23 +17,25 @@
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "fpdfsdk/cpdfsdk_widgethandler.h"
+#include "third_party/base/ptr_util.h"
#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/cpdfsdk_xfawidgethandler.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
-#include "xfa/fxfa/xfa_ffpageview.h"
-#include "xfa/fxfa/xfa_ffwidget.h"
+#include "xfa/fxfa/cxfa_ffpageview.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
#endif // PDF_ENABLE_XFA
CPDFSDK_AnnotHandlerMgr::CPDFSDK_AnnotHandlerMgr(
CPDFSDK_FormFillEnvironment* pFormFillEnv)
- : m_pBAAnnotHandler(new CPDFSDK_BAAnnotHandler()),
- m_pWidgetHandler(new CPDFSDK_WidgetHandler(pFormFillEnv)),
+ : m_pBAAnnotHandler(pdfium::MakeUnique<CPDFSDK_BAAnnotHandler>()),
+ m_pWidgetHandler(pdfium::MakeUnique<CPDFSDK_WidgetHandler>(pFormFillEnv))
#ifdef PDF_ENABLE_XFA
- m_pXFAWidgetHandler(new CPDFSDK_XFAWidgetHandler(pFormFillEnv)),
+ ,
+ m_pXFAWidgetHandler(
+ pdfium::MakeUnique<CPDFSDK_XFAWidgetHandler>(pFormFillEnv))
#endif // PDF_ENABLE_XFA
- m_pFormFillEnv(pFormFillEnv) {
- m_pWidgetHandler->SetFormFiller(m_pFormFillEnv->GetInteractiveFormFiller());
+{
}
CPDFSDK_AnnotHandlerMgr::~CPDFSDK_AnnotHandlerMgr() {}
@@ -74,6 +76,16 @@
GetAnnotHandler(pAnnot)->OnLoad(pAnnot);
}
+WideString CPDFSDK_AnnotHandlerMgr::Annot_GetSelectedText(
+ CPDFSDK_Annot* pAnnot) {
+ return GetAnnotHandler(pAnnot)->GetSelectedText(pAnnot);
+}
+
+void CPDFSDK_AnnotHandlerMgr::Annot_ReplaceSelection(CPDFSDK_Annot* pAnnot,
+ const WideString& text) {
+ GetAnnotHandler(pAnnot)->ReplaceSelection(pAnnot, text);
+}
+
IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler(
CPDFSDK_Annot* pAnnot) const {
return GetAnnotHandler(pAnnot->GetAnnotSubtype());
@@ -198,16 +210,16 @@
bool CPDFSDK_AnnotHandlerMgr::Annot_OnKeyDown(CPDFSDK_Annot* pAnnot,
int nKeyCode,
int nFlag) {
- if (m_pFormFillEnv->IsCTRLKeyDown(nFlag) ||
- m_pFormFillEnv->IsALTKeyDown(nFlag)) {
+ if (CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag) ||
+ CPDFSDK_FormFillEnvironment::IsALTKeyDown(nFlag)) {
return GetAnnotHandler(pAnnot)->OnKeyDown(pAnnot, nKeyCode, nFlag);
}
CPDFSDK_PageView* pPage = pAnnot->GetPageView();
CPDFSDK_Annot* pFocusAnnot = pPage->GetFocusAnnot();
if (pFocusAnnot && (nKeyCode == FWL_VKEY_Tab)) {
- CPDFSDK_Annot::ObservedPtr pNext(
- GetNextAnnot(pFocusAnnot, !m_pFormFillEnv->IsSHIFTKeyDown(nFlag)));
+ CPDFSDK_Annot::ObservedPtr pNext(GetNextAnnot(
+ pFocusAnnot, !CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag)));
if (pNext && pNext.Get() != pFocusAnnot) {
pPage->GetFormFillEnv()->SetFocusAnnot(&pNext);
return true;
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.h b/fpdfsdk/cpdfsdk_annothandlermgr.h
index cbda02c..df4e1a2 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.h
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.h
@@ -11,8 +11,8 @@
#include <memory>
#include "core/fpdfdoc/cpdf_annot.h"
-#include "core/fxcrt/fx_basic.h"
#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/cpdfsdk_annot.h"
class CFX_Matrix;
@@ -42,6 +42,9 @@
void Annot_OnCreate(CPDFSDK_Annot* pAnnot);
void Annot_OnLoad(CPDFSDK_Annot* pAnnot);
+ WideString Annot_GetSelectedText(CPDFSDK_Annot* pAnnot);
+ void Annot_ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text);
+
IPDFSDK_AnnotHandler* GetAnnotHandler(CPDFSDK_Annot* pAnnot) const;
void Annot_OnDraw(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
@@ -111,8 +114,6 @@
#ifdef PDF_ENABLE_XFA
std::unique_ptr<CPDFSDK_XFAWidgetHandler> m_pXFAWidgetHandler;
#endif // PDF_ENABLE_XFA
-
- CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
};
#endif // FPDFSDK_CPDFSDK_ANNOTHANDLERMGR_H_
diff --git a/fpdfsdk/cpdfsdk_annotiteration.cpp b/fpdfsdk/cpdfsdk_annotiteration.cpp
index dd99ade..d256950 100644
--- a/fpdfsdk/cpdfsdk_annotiteration.cpp
+++ b/fpdfsdk/cpdfsdk_annotiteration.cpp
@@ -33,7 +33,7 @@
std::reverse(copiedList.begin(), copiedList.end());
m_List.reserve(copiedList.size());
- for (const auto& pAnnot : copiedList)
+ for (auto* pAnnot : copiedList)
m_List.emplace_back(pAnnot);
}
diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp
index 3eedf15..a157880 100644
--- a/fpdfsdk/cpdfsdk_baannot.cpp
+++ b/fpdfsdk/cpdfsdk_baannot.cpp
@@ -27,7 +27,7 @@
CPDFSDK_BAAnnot::~CPDFSDK_BAAnnot() {}
CPDF_Annot* CPDFSDK_BAAnnot::GetPDFAnnot() const {
- return m_pAnnot;
+ return m_pAnnot.Get();
}
CPDF_Annot* CPDFSDK_BAAnnot::GetPDFPopupAnnot() const {
@@ -38,6 +38,13 @@
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<CPDF_Dictionary>("AP");
+ return pAPDict;
+}
+
void CPDFSDK_BAAnnot::SetRect(const CFX_FloatRect& rect) {
ASSERT(rect.right - rect.left >= GetMinWidth());
ASSERT(rect.top - rect.bottom >= GetMinHeight());
@@ -54,10 +61,10 @@
}
void CPDFSDK_BAAnnot::DrawAppearance(CFX_RenderDevice* pDevice,
- const CFX_Matrix* pUser2Device,
+ const CFX_Matrix& mtUser2Device,
CPDF_Annot::AppearanceMode mode,
const CPDF_RenderOptions* pOptions) {
- m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device,
+ m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, mtUser2Device,
mode, pOptions);
}
@@ -71,7 +78,7 @@
return false;
// Choose the right sub-ap
- const FX_CHAR* ap_entry = "N";
+ const char* ap_entry = "N";
if (mode == CPDF_Annot::Down)
ap_entry = "D";
else if (mode == CPDF_Annot::Rollover)
@@ -94,7 +101,7 @@
m_pAnnot->ClearCachedAP();
}
-void CPDFSDK_BAAnnot::SetContents(const CFX_WideString& sContents) {
+void CPDFSDK_BAAnnot::SetContents(const WideString& sContents) {
if (sContents.IsEmpty()) {
m_pAnnot->GetAnnotDict()->RemoveFor("Contents");
} else {
@@ -103,11 +110,11 @@
}
}
-CFX_WideString CPDFSDK_BAAnnot::GetContents() const {
+WideString CPDFSDK_BAAnnot::GetContents() const {
return m_pAnnot->GetAnnotDict()->GetUnicodeTextFor("Contents");
}
-void CPDFSDK_BAAnnot::SetAnnotName(const CFX_WideString& sName) {
+void CPDFSDK_BAAnnot::SetAnnotName(const WideString& sName) {
if (sName.IsEmpty()) {
m_pAnnot->GetAnnotDict()->RemoveFor("NM");
} else {
@@ -116,13 +123,13 @@
}
}
-CFX_WideString CPDFSDK_BAAnnot::GetAnnotName() const {
+WideString CPDFSDK_BAAnnot::GetAnnotName() const {
return m_pAnnot->GetAnnotDict()->GetUnicodeTextFor("NM");
}
void CPDFSDK_BAAnnot::SetModifiedDate(const FX_SYSTEMTIME& st) {
CPDFSDK_DateTime dt(st);
- CFX_ByteString str = dt.ToPDFDateTimeString();
+ ByteString str = dt.ToPDFDateTimeString();
if (str.IsEmpty())
m_pAnnot->GetAnnotDict()->RemoveFor("M");
else
@@ -131,7 +138,7 @@
FX_SYSTEMTIME CPDFSDK_BAAnnot::GetModifiedDate() const {
FX_SYSTEMTIME systime;
- CFX_ByteString str = m_pAnnot->GetAnnotDict()->GetStringFor("M");
+ ByteString str = m_pAnnot->GetAnnotDict()->GetStringFor("M");
CPDFSDK_DateTime dt(str);
dt.ToSystemTime(systime);
return systime;
@@ -146,14 +153,14 @@
return m_pAnnot->GetAnnotDict()->GetIntegerFor("F");
}
-void CPDFSDK_BAAnnot::SetAppState(const CFX_ByteString& str) {
+void CPDFSDK_BAAnnot::SetAppState(const ByteString& str) {
if (str.IsEmpty())
m_pAnnot->GetAnnotDict()->RemoveFor("AS");
else
m_pAnnot->GetAnnotDict()->SetNewFor<CPDF_String>("AS", str, false);
}
-CFX_ByteString CPDFSDK_BAAnnot::GetAppState() const {
+ByteString CPDFSDK_BAAnnot::GetAppState() const {
return m_pAnnot->GetAnnotDict()->GetStringFor("AS");
}
@@ -218,7 +225,7 @@
BorderStyle CPDFSDK_BAAnnot::GetBorderStyle() const {
CPDF_Dictionary* pBSDict = m_pAnnot->GetAnnotDict()->GetDictFor("BS");
if (pBSDict) {
- CFX_ByteString sBorderStyle = pBSDict->GetStringFor("S", "S");
+ ByteString sBorderStyle = pBSDict->GetStringFor("S", "S");
if (sBorderStyle == "S")
return BorderStyle::SOLID;
if (sBorderStyle == "D")
@@ -245,11 +252,11 @@
void CPDFSDK_BAAnnot::SetColor(FX_COLORREF color) {
CPDF_Array* pArray = m_pAnnot->GetAnnotDict()->SetNewFor<CPDF_Array>("C");
- pArray->AddNew<CPDF_Number>(static_cast<FX_FLOAT>(FXSYS_GetRValue(color)) /
+ pArray->AddNew<CPDF_Number>(static_cast<float>(FXSYS_GetRValue(color)) /
255.0f);
- pArray->AddNew<CPDF_Number>(static_cast<FX_FLOAT>(FXSYS_GetGValue(color)) /
+ pArray->AddNew<CPDF_Number>(static_cast<float>(FXSYS_GetGValue(color)) /
255.0f);
- pArray->AddNew<CPDF_Number>(static_cast<FX_FLOAT>(FXSYS_GetBValue(color)) /
+ pArray->AddNew<CPDF_Number>(static_cast<float>(FXSYS_GetBValue(color)) /
255.0f);
}
@@ -261,28 +268,28 @@
if (CPDF_Array* pEntry = m_pAnnot->GetAnnotDict()->GetArrayFor("C")) {
size_t nCount = pEntry->GetCount();
if (nCount == 1) {
- FX_FLOAT g = pEntry->GetNumberAt(0) * 255;
+ float g = pEntry->GetNumberAt(0) * 255;
color = FXSYS_RGB((int)g, (int)g, (int)g);
return true;
} else if (nCount == 3) {
- FX_FLOAT r = pEntry->GetNumberAt(0) * 255;
- FX_FLOAT g = pEntry->GetNumberAt(1) * 255;
- FX_FLOAT b = pEntry->GetNumberAt(2) * 255;
+ float r = pEntry->GetNumberAt(0) * 255;
+ float g = pEntry->GetNumberAt(1) * 255;
+ float b = pEntry->GetNumberAt(2) * 255;
color = FXSYS_RGB((int)r, (int)g, (int)b);
return true;
} else if (nCount == 4) {
- FX_FLOAT c = pEntry->GetNumberAt(0);
- FX_FLOAT m = pEntry->GetNumberAt(1);
- FX_FLOAT y = pEntry->GetNumberAt(2);
- FX_FLOAT k = pEntry->GetNumberAt(3);
+ float c = pEntry->GetNumberAt(0);
+ float m = pEntry->GetNumberAt(1);
+ float y = pEntry->GetNumberAt(2);
+ float k = pEntry->GetNumberAt(3);
- FX_FLOAT r = 1.0f - std::min(1.0f, c + k);
- FX_FLOAT g = 1.0f - std::min(1.0f, m + k);
- FX_FLOAT b = 1.0f - std::min(1.0f, y + k);
+ float r = 1.0f - std::min(1.0f, c + k);
+ float g = 1.0f - std::min(1.0f, m + k);
+ float b = 1.0f - std::min(1.0f, y + k);
color = FXSYS_RGB((int)(r * 255), (int)(g * 255), (int)(b * 255));
@@ -293,50 +300,6 @@
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<CPDF_Dictionary>("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<CPDF_Dictionary>(sAPType);
-
- pParentDict = pAPTypeDict;
- pStream = pAPTypeDict->GetStreamFor(sAPState);
- }
-
- if (!pStream) {
- CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
- pStream = pDoc->NewIndirect<CPDF_Stream>();
- pParentDict->SetNewFor<CPDF_Reference>(sAPType, pDoc, pStream->GetObjNum());
- }
-
- CPDF_Dictionary* pStreamDict = pStream->GetDict();
- if (!pStreamDict) {
- auto pNewDict = pdfium::MakeUnique<CPDF_Dictionary>(
- m_pAnnot->GetDocument()->GetByteStringPool());
- pStreamDict = pNewDict.get();
- pStreamDict->SetNewFor<CPDF_Name>("Type", "XObject");
- pStreamDict->SetNewFor<CPDF_Name>("Subtype", "Form");
- pStreamDict->SetNewFor<CPDF_Number>("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) ||
@@ -383,18 +346,17 @@
if (eAAT == CPDF_AAction::ButtonUp)
return GetAction();
- return CPDF_Action();
-}
-
-void CPDFSDK_BAAnnot::Annot_OnDraw(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- CPDF_RenderOptions* pOptions) {
- m_pAnnot->GetAPForm(m_pPageView->GetPDFPage(), CPDF_Annot::Normal);
- m_pAnnot->DrawAppearance(m_pPageView->GetPDFPage(), pDevice, pUser2Device,
- CPDF_Annot::Normal, nullptr);
+ return CPDF_Action(nullptr);
}
void CPDFSDK_BAAnnot::SetOpenState(bool bOpenState) {
if (CPDF_Annot* pAnnot = m_pAnnot->GetPopupAnnot())
pAnnot->SetOpenState(bOpenState);
}
+
+int CPDFSDK_BAAnnot::GetLayoutOrder() const {
+ if (m_pAnnot->GetSubtype() == CPDF_Annot::Subtype::POPUP)
+ return 1;
+
+ return CPDFSDK_Annot::GetLayoutOrder();
+}
diff --git a/fpdfsdk/cpdfsdk_baannot.h b/fpdfsdk/cpdfsdk_baannot.h
index 2da5723..ac3c0cb 100644
--- a/fpdfsdk/cpdfsdk_baannot.h
+++ b/fpdfsdk/cpdfsdk_baannot.h
@@ -32,18 +32,17 @@
void SetRect(const CFX_FloatRect& rect) override;
CFX_FloatRect GetRect() const override;
CPDF_Annot* GetPDFAnnot() const override;
- void Annot_OnDraw(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- CPDF_RenderOptions* pOptions) override;
CPDF_Dictionary* GetAnnotDict() const;
CPDF_Annot* GetPDFPopupAnnot() const;
- void SetContents(const CFX_WideString& sContents);
- CFX_WideString GetContents() const;
+ CPDF_Dictionary* GetAPDict() const;
- void SetAnnotName(const CFX_WideString& sName);
- CFX_WideString GetAnnotName() const;
+ void SetContents(const WideString& sContents);
+ WideString GetContents() const;
+
+ void SetAnnotName(const WideString& sName);
+ WideString GetAnnotName() const;
void SetModifiedDate(const FX_SYSTEMTIME& st);
FX_SYSTEMTIME GetModifiedDate() const;
@@ -51,8 +50,8 @@
void SetFlags(uint32_t nFlags);
uint32_t GetFlags() const;
- void SetAppState(const CFX_ByteString& str);
- CFX_ByteString GetAppState() const;
+ void SetAppState(const ByteString& str);
+ ByteString GetAppState() const;
void SetStructParent(int key);
int GetStructParent() const;
@@ -81,7 +80,7 @@
virtual bool IsAppearanceValid();
virtual bool IsAppearanceValid(CPDF_Annot::AppearanceMode mode);
virtual void DrawAppearance(CFX_RenderDevice* pDevice,
- const CFX_Matrix* pUser2Device,
+ const CFX_Matrix& mtUser2Device,
CPDF_Annot::AppearanceMode mode,
const CPDF_RenderOptions* pOptions);
@@ -91,16 +90,12 @@
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);
+ int GetLayoutOrder() const override;
+
protected:
- CPDF_Annot* const m_pAnnot;
+ UnownedPtr<CPDF_Annot> const m_pAnnot;
};
#endif // FPDFSDK_CPDFSDK_BAANNOT_H_
diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp
index fa83932..027527e 100644
--- a/fpdfsdk/cpdfsdk_baannothandler.cpp
+++ b/fpdfsdk/cpdfsdk_baannothandler.cpp
@@ -73,7 +73,7 @@
#endif // PDF_ENABLE_XFA
if (bDrawAnnots && pAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::POPUP) {
static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance(
- pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
+ pDevice, *pUser2Device, CPDF_Annot::Normal, nullptr);
}
}
@@ -193,6 +193,13 @@
return pAnnot->GetRect();
}
+WideString CPDFSDK_BAAnnotHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) {
+ return WideString();
+}
+
+void CPDFSDK_BAAnnotHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot,
+ const WideString& text) {}
+
bool CPDFSDK_BAAnnotHandler::HitTest(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
const CFX_PointF& point) {
diff --git a/fpdfsdk/cpdfsdk_baannothandler.h b/fpdfsdk/cpdfsdk_baannothandler.h
index d5f170f..7bf8034 100644
--- a/fpdfsdk/cpdfsdk_baannothandler.h
+++ b/fpdfsdk/cpdfsdk_baannothandler.h
@@ -7,7 +7,6 @@
#ifndef FPDFSDK_CPDFSDK_BAANNOTHANDLER_H_
#define FPDFSDK_CPDFSDK_BAANNOTHANDLER_H_
-#include "core/fxcrt/fx_basic.h"
#include "core/fxcrt/fx_coordinates.h"
#include "fpdfsdk/ipdfsdk_annothandler.h"
@@ -37,6 +36,8 @@
void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override;
CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot) override;
+ WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override;
+ void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override;
bool HitTest(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
const CFX_PointF& point) override;
diff --git a/fpdfsdk/cpdfsdk_datetime.cpp b/fpdfsdk/cpdfsdk_datetime.cpp
index 72f50a6..332ae8e 100644
--- a/fpdfsdk/cpdfsdk_datetime.cpp
+++ b/fpdfsdk/cpdfsdk_datetime.cpp
@@ -6,7 +6,7 @@
#include "fpdfsdk/cpdfsdk_datetime.h"
-#include "core/fxcrt/fx_ext.h"
+#include "core/fxcrt/fx_extension.h"
namespace {
@@ -63,7 +63,7 @@
ResetDateTime();
}
-CPDFSDK_DateTime::CPDFSDK_DateTime(const CFX_ByteString& dtStr) {
+CPDFSDK_DateTime::CPDFSDK_DateTime(const ByteString& dtStr) {
ResetDateTime();
FromPDFDateTimeString(dtStr);
}
@@ -129,7 +129,7 @@
}
CPDFSDK_DateTime& CPDFSDK_DateTime::FromPDFDateTimeString(
- const CFX_ByteString& dtStr) {
+ const ByteString& dtStr) {
int strLength = dtStr.GetLength();
if (strLength <= 0)
return *this;
@@ -143,10 +143,10 @@
int j = 0;
int k = 0;
- FX_CHAR ch;
+ char ch;
while (i < strLength && j < 4) {
ch = dtStr[i];
- k = k * 10 + FXSYS_toDecimalDigit(ch);
+ k = k * 10 + FXSYS_DecimalCharToInt(ch);
j++;
if (!std::isdigit(ch))
break;
@@ -160,7 +160,7 @@
k = 0;
while (i < strLength && j < 2) {
ch = dtStr[i];
- k = k * 10 + FXSYS_toDecimalDigit(ch);
+ k = k * 10 + FXSYS_DecimalCharToInt(ch);
j++;
if (!std::isdigit(ch))
break;
@@ -174,7 +174,7 @@
k = 0;
while (i < strLength && j < 2) {
ch = dtStr[i];
- k = k * 10 + FXSYS_toDecimalDigit(ch);
+ k = k * 10 + FXSYS_DecimalCharToInt(ch);
j++;
if (!std::isdigit(ch))
break;
@@ -188,7 +188,7 @@
k = 0;
while (i < strLength && j < 2) {
ch = dtStr[i];
- k = k * 10 + FXSYS_toDecimalDigit(ch);
+ k = k * 10 + FXSYS_DecimalCharToInt(ch);
j++;
if (!std::isdigit(ch))
break;
@@ -202,7 +202,7 @@
k = 0;
while (i < strLength && j < 2) {
ch = dtStr[i];
- k = k * 10 + FXSYS_toDecimalDigit(ch);
+ k = k * 10 + FXSYS_DecimalCharToInt(ch);
j++;
if (!std::isdigit(ch))
break;
@@ -216,7 +216,7 @@
k = 0;
while (i < strLength && j < 2) {
ch = dtStr[i];
- k = k * 10 + FXSYS_toDecimalDigit(ch);
+ k = k * 10 + FXSYS_DecimalCharToInt(ch);
j++;
if (!std::isdigit(ch))
break;
@@ -237,7 +237,7 @@
k = 0;
while (i < strLength && j < 2) {
ch = dtStr[i];
- k = k * 10 + FXSYS_toDecimalDigit(ch);
+ k = k * 10 + FXSYS_DecimalCharToInt(ch);
j++;
if (!std::isdigit(ch))
break;
@@ -253,7 +253,7 @@
k = 0;
while (i < strLength && j < 2) {
ch = dtStr[i];
- k = k * 10 + FXSYS_toDecimalDigit(ch);
+ k = k * 10 + FXSYS_DecimalCharToInt(ch);
j++;
if (!std::isdigit(ch))
break;
@@ -263,34 +263,29 @@
return *this;
}
-CFX_ByteString CPDFSDK_DateTime::ToCommonDateTimeString() {
- CFX_ByteString str1;
- str1.Format("%04d-%02u-%02u %02u:%02u:%02u ", m_year, m_month, m_day, m_hour,
- m_minute, m_second);
- if (m_tzHour < 0)
- str1 += "-";
- else
- str1 += "+";
- CFX_ByteString str2;
- str2.Format("%02d:%02u", std::abs(static_cast<int>(m_tzHour)), m_tzMinute);
- return str1 + str2;
+ByteString CPDFSDK_DateTime::ToCommonDateTimeString() {
+ return ByteString::Format("%04d-%02u-%02u %02u:%02u:%02u ", m_year, m_month,
+ m_day, m_hour, m_minute, m_second) +
+ (m_tzHour < 0 ? "-" : "+") +
+ ByteString::Format("%02d:%02u", std::abs(static_cast<int>(m_tzHour)),
+ m_tzMinute);
}
-CFX_ByteString CPDFSDK_DateTime::ToPDFDateTimeString() {
- CFX_ByteString dtStr;
+ByteString CPDFSDK_DateTime::ToPDFDateTimeString() {
+ ByteString dtStr;
char tempStr[32];
memset(tempStr, 0, sizeof(tempStr));
FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "D:%04d%02u%02u%02u%02u%02u",
m_year, m_month, m_day, m_hour, m_minute, m_second);
- dtStr = CFX_ByteString(tempStr);
+ dtStr = ByteString(tempStr);
if (m_tzHour < 0)
- dtStr += CFX_ByteString("-");
+ dtStr += ByteString("-");
else
- dtStr += CFX_ByteString("+");
+ dtStr += ByteString("+");
memset(tempStr, 0, sizeof(tempStr));
FXSYS_snprintf(tempStr, sizeof(tempStr) - 1, "%02d'%02u'",
std::abs(static_cast<int>(m_tzHour)), m_tzMinute);
- dtStr += CFX_ByteString(tempStr);
+ dtStr += ByteString(tempStr);
return dtStr;
}
diff --git a/fpdfsdk/cpdfsdk_datetime.h b/fpdfsdk/cpdfsdk_datetime.h
index 6b612b2..cbd3c36 100644
--- a/fpdfsdk/cpdfsdk_datetime.h
+++ b/fpdfsdk/cpdfsdk_datetime.h
@@ -7,7 +7,7 @@
#ifndef FPDFSDK_CPDFSDK_DATETIME_H_
#define FPDFSDK_CPDFSDK_DATETIME_H_
-#if _FX_OS_ == _FX_ANDROID_
+#if _FX_OS_ == _FX_OS_ANDROID_
#include <time.h>
#else
#include <ctime>
@@ -18,16 +18,16 @@
class CPDFSDK_DateTime {
public:
CPDFSDK_DateTime();
- explicit CPDFSDK_DateTime(const CFX_ByteString& dtStr);
+ explicit CPDFSDK_DateTime(const ByteString& dtStr);
explicit CPDFSDK_DateTime(const FX_SYSTEMTIME& st);
CPDFSDK_DateTime(const CPDFSDK_DateTime& datetime);
bool operator==(const CPDFSDK_DateTime& datetime) const;
bool operator!=(const CPDFSDK_DateTime& datetime) const;
- CPDFSDK_DateTime& FromPDFDateTimeString(const CFX_ByteString& dtStr);
- CFX_ByteString ToCommonDateTimeString();
- CFX_ByteString ToPDFDateTimeString();
+ CPDFSDK_DateTime& FromPDFDateTimeString(const ByteString& dtStr);
+ ByteString ToCommonDateTimeString();
+ ByteString ToPDFDateTimeString();
void ToSystemTime(FX_SYSTEMTIME& st);
time_t ToTime_t() const;
CPDFSDK_DateTime ToGMT() const;
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
index 4ef766d..955c184 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
@@ -7,6 +7,7 @@
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include <memory>
+#include <utility>
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfdoc/cpdf_docjsactions.h"
@@ -16,14 +17,14 @@
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
#include "fpdfsdk/fsdk_actionhandler.h"
-#include "fpdfsdk/javascript/ijs_runtime.h"
+#include "fxjs/ijs_runtime.h"
#include "third_party/base/ptr_util.h"
namespace {
// NOTE: |bsUTF16LE| must outlive the use of the result. Care must be taken
// since modifying the result would impact |bsUTF16LE|.
-FPDF_WIDESTRING AsFPDFWideString(CFX_ByteString* bsUTF16LE) {
+FPDF_WIDESTRING AsFPDFWideString(ByteString* bsUTF16LE) {
return reinterpret_cast<FPDF_WIDESTRING>(
bsUTF16LE->GetBuffer(bsUTF16LE->GetLength()));
}
@@ -35,7 +36,7 @@
FPDF_FORMFILLINFO* pFFinfo)
: m_pInfo(pFFinfo),
m_pUnderlyingDoc(pDoc),
- m_pSysHandler(new CFX_SystemHandler(this)),
+ m_pSysHandler(pdfium::MakeUnique<CFX_SystemHandler>(this)),
m_bChangeMask(false),
m_bBeingDestroyed(false) {}
@@ -60,25 +61,25 @@
m_pInfo->Release(m_pInfo);
}
-int CPDFSDK_FormFillEnvironment::JS_appAlert(const FX_WCHAR* Msg,
- const FX_WCHAR* Title,
+int CPDFSDK_FormFillEnvironment::JS_appAlert(const wchar_t* Msg,
+ const wchar_t* Title,
uint32_t Type,
uint32_t Icon) {
if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
!m_pInfo->m_pJsPlatform->app_alert) {
return -1;
}
- CFX_ByteString bsMsg = CFX_WideString(Msg).UTF16LE_Encode();
- CFX_ByteString bsTitle = CFX_WideString(Title).UTF16LE_Encode();
+ ByteString bsMsg = WideString(Msg).UTF16LE_Encode();
+ ByteString bsTitle = WideString(Title).UTF16LE_Encode();
return m_pInfo->m_pJsPlatform->app_alert(
m_pInfo->m_pJsPlatform, AsFPDFWideString(&bsMsg),
AsFPDFWideString(&bsTitle), Type, Icon);
}
-int CPDFSDK_FormFillEnvironment::JS_appResponse(const FX_WCHAR* Question,
- const FX_WCHAR* Title,
- const FX_WCHAR* Default,
- const FX_WCHAR* cLabel,
+int CPDFSDK_FormFillEnvironment::JS_appResponse(const wchar_t* Question,
+ const wchar_t* Title,
+ const wchar_t* Default,
+ const wchar_t* cLabel,
FPDF_BOOL bPassword,
void* response,
int length) {
@@ -86,10 +87,10 @@
!m_pInfo->m_pJsPlatform->app_response) {
return -1;
}
- CFX_ByteString bsQuestion = CFX_WideString(Question).UTF16LE_Encode();
- CFX_ByteString bsTitle = CFX_WideString(Title).UTF16LE_Encode();
- CFX_ByteString bsDefault = CFX_WideString(Default).UTF16LE_Encode();
- CFX_ByteString bsLabel = CFX_WideString(cLabel).UTF16LE_Encode();
+ ByteString bsQuestion = WideString(Question).UTF16LE_Encode();
+ ByteString bsTitle = WideString(Title).UTF16LE_Encode();
+ ByteString bsDefault = WideString(Default).UTF16LE_Encode();
+ ByteString bsLabel = WideString(cLabel).UTF16LE_Encode();
return m_pInfo->m_pJsPlatform->app_response(
m_pInfo->m_pJsPlatform, AsFPDFWideString(&bsQuestion),
AsFPDFWideString(&bsTitle), AsFPDFWideString(&bsDefault),
@@ -104,54 +105,54 @@
m_pInfo->m_pJsPlatform->app_beep(m_pInfo->m_pJsPlatform, nType);
}
-CFX_WideString CPDFSDK_FormFillEnvironment::JS_fieldBrowse() {
+WideString CPDFSDK_FormFillEnvironment::JS_fieldBrowse() {
if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
!m_pInfo->m_pJsPlatform->Field_browse) {
- return CFX_WideString();
+ return WideString();
}
const int nRequiredLen =
m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, nullptr, 0);
if (nRequiredLen <= 0)
- return CFX_WideString();
+ return WideString();
- std::unique_ptr<char[]> pBuff(new char[nRequiredLen]);
- memset(pBuff.get(), 0, nRequiredLen);
+ std::vector<uint8_t> pBuff(nRequiredLen);
const int nActualLen = m_pInfo->m_pJsPlatform->Field_browse(
- m_pInfo->m_pJsPlatform, pBuff.get(), nRequiredLen);
+ m_pInfo->m_pJsPlatform, pBuff.data(), nRequiredLen);
if (nActualLen <= 0 || nActualLen > nRequiredLen)
- return CFX_WideString();
+ return WideString();
- return CFX_WideString::FromLocal(CFX_ByteStringC(pBuff.get(), nActualLen));
+ pBuff.resize(nActualLen);
+ return WideString::FromLocal(ByteStringView(pBuff));
}
-CFX_WideString CPDFSDK_FormFillEnvironment::JS_docGetFilePath() {
+WideString CPDFSDK_FormFillEnvironment::JS_docGetFilePath() {
if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
!m_pInfo->m_pJsPlatform->Doc_getFilePath) {
- return CFX_WideString();
+ return WideString();
}
const int nRequiredLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(
m_pInfo->m_pJsPlatform, nullptr, 0);
if (nRequiredLen <= 0)
- return CFX_WideString();
+ return WideString();
- std::unique_ptr<char[]> pBuff(new char[nRequiredLen]);
- memset(pBuff.get(), 0, nRequiredLen);
+ std::vector<uint8_t> pBuff(nRequiredLen);
const int nActualLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(
- m_pInfo->m_pJsPlatform, pBuff.get(), nRequiredLen);
+ m_pInfo->m_pJsPlatform, pBuff.data(), nRequiredLen);
if (nActualLen <= 0 || nActualLen > nRequiredLen)
- return CFX_WideString();
+ return WideString();
- return CFX_WideString::FromLocal(CFX_ByteStringC(pBuff.get(), nActualLen));
+ pBuff.resize(nActualLen);
+ return WideString::FromLocal(ByteStringView(pBuff));
}
void CPDFSDK_FormFillEnvironment::JS_docSubmitForm(void* formData,
int length,
- const FX_WCHAR* URL) {
+ const wchar_t* URL) {
if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
!m_pInfo->m_pJsPlatform->Doc_submitForm) {
return;
}
- CFX_ByteString bsDestination = CFX_WideString(URL).UTF16LE_Encode();
+ ByteString bsDestination = WideString(URL).UTF16LE_Encode();
m_pInfo->m_pJsPlatform->Doc_submitForm(m_pInfo->m_pJsPlatform, formData,
length,
AsFPDFWideString(&bsDestination));
@@ -160,20 +161,20 @@
void CPDFSDK_FormFillEnvironment::JS_docmailForm(void* mailData,
int length,
FPDF_BOOL bUI,
- const FX_WCHAR* To,
- const FX_WCHAR* Subject,
- const FX_WCHAR* CC,
- const FX_WCHAR* BCC,
- const FX_WCHAR* Msg) {
+ const wchar_t* To,
+ const wchar_t* Subject,
+ const wchar_t* CC,
+ const wchar_t* BCC,
+ const wchar_t* Msg) {
if (!m_pInfo || !m_pInfo->m_pJsPlatform ||
!m_pInfo->m_pJsPlatform->Doc_mail) {
return;
}
- CFX_ByteString bsTo = CFX_WideString(To).UTF16LE_Encode();
- CFX_ByteString bsSubject = CFX_WideString(Subject).UTF16LE_Encode();
- CFX_ByteString bsCC = CFX_WideString(CC).UTF16LE_Encode();
- CFX_ByteString bsBcc = CFX_WideString(BCC).UTF16LE_Encode();
- CFX_ByteString bsMsg = CFX_WideString(Msg).UTF16LE_Encode();
+ ByteString bsTo = WideString(To).UTF16LE_Encode();
+ ByteString bsSubject = WideString(Subject).UTF16LE_Encode();
+ ByteString bsCC = WideString(CC).UTF16LE_Encode();
+ ByteString bsBcc = WideString(BCC).UTF16LE_Encode();
+ ByteString bsMsg = WideString(Msg).UTF16LE_Encode();
m_pInfo->m_pJsPlatform->Doc_mail(
m_pInfo->m_pJsPlatform, mailData, length, bUI, AsFPDFWideString(&bsTo),
AsFPDFWideString(&bsSubject), AsFPDFWideString(&bsCC),
@@ -219,7 +220,7 @@
return m_pAnnotHandlerMgr.get();
}
-CPDFSDK_ActionHandler* CPDFSDK_FormFillEnvironment::GetActionHander() {
+CPDFSDK_ActionHandler* CPDFSDK_FormFillEnvironment::GetActionHandler() {
if (!m_pActionHandler)
m_pActionHandler = pdfium::MakeUnique<CPDFSDK_ActionHandler>();
return m_pActionHandler.get();
@@ -232,7 +233,7 @@
return m_pFormFiller.get();
}
-void CPDFSDK_FormFillEnvironment::Invalidate(FPDF_PAGE page,
+void CPDFSDK_FormFillEnvironment::Invalidate(UnderlyingPageType* page,
const FX_RECT& rect) {
if (m_pInfo && m_pInfo->FFI_Invalidate) {
m_pInfo->FFI_Invalidate(m_pInfo, page, rect.left, rect.top, rect.right,
@@ -241,7 +242,7 @@
}
void CPDFSDK_FormFillEnvironment::OutputSelectedRect(
- FPDF_PAGE page,
+ UnderlyingPageType* page,
const CFX_FloatRect& rect) {
if (m_pInfo && m_pInfo->FFI_OutputSelectedRect) {
m_pInfo->FFI_OutputSelectedRect(m_pInfo, page, rect.left, rect.top,
@@ -288,33 +289,14 @@
m_pInfo->FFI_OnChange(m_pInfo);
}
-bool CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(uint32_t nFlag) const {
- return (nFlag & FWL_EVENTFLAG_ShiftKey) != 0;
-}
-
-bool CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(uint32_t nFlag) const {
- return (nFlag & FWL_EVENTFLAG_ControlKey) != 0;
-}
-
-bool CPDFSDK_FormFillEnvironment::IsALTKeyDown(uint32_t nFlag) const {
- return (nFlag & FWL_EVENTFLAG_AltKey) != 0;
-}
-
-FPDF_PAGE CPDFSDK_FormFillEnvironment::GetPage(FPDF_DOCUMENT document,
- int nPageIndex) {
- if (m_pInfo && m_pInfo->FFI_GetPage)
- return m_pInfo->FFI_GetPage(m_pInfo, document, nPageIndex);
- return nullptr;
-}
-
-FPDF_PAGE CPDFSDK_FormFillEnvironment::GetCurrentPage(FPDF_DOCUMENT document) {
+FPDF_PAGE CPDFSDK_FormFillEnvironment::GetCurrentPage(
+ UnderlyingDocumentType* document) {
if (m_pInfo && m_pInfo->FFI_GetCurrentPage)
return m_pInfo->FFI_GetCurrentPage(m_pInfo, document);
return nullptr;
}
-void CPDFSDK_FormFillEnvironment::ExecuteNamedAction(
- const FX_CHAR* namedAction) {
+void CPDFSDK_FormFillEnvironment::ExecuteNamedAction(const char* namedAction) {
if (m_pInfo && m_pInfo->FFI_ExecuteNamedAction)
m_pInfo->FFI_ExecuteNamedAction(m_pInfo, namedAction);
}
@@ -327,7 +309,7 @@
m_pInfo->FFI_SetTextFieldFocus(m_pInfo, focusText, nTextLen, bFocus);
}
-void CPDFSDK_FormFillEnvironment::DoURIAction(const FX_CHAR* bsURI) {
+void CPDFSDK_FormFillEnvironment::DoURIAction(const char* bsURI) {
if (m_pInfo && m_pInfo->FFI_DoURIAction)
m_pInfo->FFI_DoURIAction(m_pInfo, bsURI);
}
@@ -343,7 +325,7 @@
}
#ifdef PDF_ENABLE_XFA
-void CPDFSDK_FormFillEnvironment::DisplayCaret(FPDF_PAGE page,
+void CPDFSDK_FormFillEnvironment::DisplayCaret(CPDFXFA_Page* page,
FPDF_BOOL bVisible,
double left,
double top,
@@ -355,53 +337,49 @@
}
}
-int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex(FPDF_DOCUMENT document) {
+int CPDFSDK_FormFillEnvironment::GetCurrentPageIndex(
+ CPDFXFA_Context* document) {
if (!m_pInfo || !m_pInfo->FFI_GetCurrentPageIndex)
return -1;
return m_pInfo->FFI_GetCurrentPageIndex(m_pInfo, document);
}
-void CPDFSDK_FormFillEnvironment::SetCurrentPage(FPDF_DOCUMENT document,
+void CPDFSDK_FormFillEnvironment::SetCurrentPage(CPDFXFA_Context* document,
int iCurPage) {
if (m_pInfo && m_pInfo->FFI_SetCurrentPage)
m_pInfo->FFI_SetCurrentPage(m_pInfo, document, iCurPage);
}
-CFX_WideString CPDFSDK_FormFillEnvironment::GetPlatform() {
+WideString CPDFSDK_FormFillEnvironment::GetPlatform() {
if (!m_pInfo || !m_pInfo->FFI_GetPlatform)
- return L"";
+ return WideString();
int nRequiredLen = m_pInfo->FFI_GetPlatform(m_pInfo, nullptr, 0);
if (nRequiredLen <= 0)
- return L"";
+ return WideString();
- char* pbuff = new char[nRequiredLen];
- memset(pbuff, 0, nRequiredLen);
- int nActualLen = m_pInfo->FFI_GetPlatform(m_pInfo, pbuff, nRequiredLen);
- if (nActualLen <= 0 || nActualLen > nRequiredLen) {
- delete[] pbuff;
- return L"";
- }
- CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen);
- CFX_WideString wsRet = CFX_WideString::FromUTF16LE(
- (unsigned short*)bsRet.GetBuffer(bsRet.GetLength()),
- bsRet.GetLength() / sizeof(unsigned short));
- delete[] pbuff;
- return wsRet;
+ std::vector<uint8_t> pBuff(nRequiredLen);
+ int nActualLen =
+ m_pInfo->FFI_GetPlatform(m_pInfo, pBuff.data(), nRequiredLen);
+ if (nActualLen <= 0 || nActualLen > nRequiredLen)
+ return WideString();
+
+ return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
+ nActualLen / sizeof(uint16_t));
}
-void CPDFSDK_FormFillEnvironment::GotoURL(FPDF_DOCUMENT document,
- const CFX_WideStringC& wsURL) {
+void CPDFSDK_FormFillEnvironment::GotoURL(CPDFXFA_Context* document,
+ const WideStringView& wsURL) {
if (!m_pInfo || !m_pInfo->FFI_GotoURL)
return;
- CFX_ByteString bsTo = CFX_WideString(wsURL).UTF16LE_Encode();
+ ByteString bsTo = WideString(wsURL).UTF16LE_Encode();
FPDF_WIDESTRING pTo = (FPDF_WIDESTRING)bsTo.GetBuffer(wsURL.GetLength());
m_pInfo->FFI_GotoURL(m_pInfo, document, pTo);
- bsTo.ReleaseBuffer();
+ bsTo.ReleaseBuffer(bsTo.GetStringLength());
}
-void CPDFSDK_FormFillEnvironment::GetPageViewRect(FPDF_PAGE page,
+void CPDFSDK_FormFillEnvironment::GetPageViewRect(CPDFXFA_Page* page,
FS_RECTF& dstRect) {
if (!m_pInfo || !m_pInfo->FFI_GetPageViewRect)
return;
@@ -411,14 +389,16 @@
double right;
double bottom;
m_pInfo->FFI_GetPageViewRect(m_pInfo, page, &left, &top, &right, &bottom);
+ if (top < bottom)
+ std::swap(top, bottom);
dstRect.left = static_cast<float>(left);
- dstRect.top = static_cast<float>(top < bottom ? bottom : top);
- dstRect.bottom = static_cast<float>(top < bottom ? top : bottom);
+ dstRect.top = static_cast<float>(top);
+ dstRect.bottom = static_cast<float>(bottom);
dstRect.right = static_cast<float>(right);
}
-bool CPDFSDK_FormFillEnvironment::PopupMenu(FPDF_PAGE page,
+bool CPDFSDK_FormFillEnvironment::PopupMenu(CPDFXFA_Page* page,
FPDF_WIDGET hWidget,
int menuFlag,
CFX_PointF pt) {
@@ -461,12 +441,12 @@
return nullptr;
}
-CFX_RetainPtr<IFX_SeekableReadStream>
-CPDFSDK_FormFillEnvironment::DownloadFromURL(const FX_WCHAR* url) {
+RetainPtr<IFX_SeekableReadStream> CPDFSDK_FormFillEnvironment::DownloadFromURL(
+ const wchar_t* url) {
if (!m_pInfo || !m_pInfo->FFI_DownloadFromURL)
return nullptr;
- CFX_ByteString bstrURL = CFX_WideString(url).UTF16LE_Encode();
+ ByteString bstrURL = WideString(url).UTF16LE_Encode();
FPDF_WIDESTRING wsURL =
(FPDF_WIDESTRING)bstrURL.GetBuffer(bstrURL.GetLength());
@@ -474,30 +454,30 @@
return MakeSeekableStream(fileHandler);
}
-CFX_WideString CPDFSDK_FormFillEnvironment::PostRequestURL(
- const FX_WCHAR* wsURL,
- const FX_WCHAR* wsData,
- const FX_WCHAR* wsContentType,
- const FX_WCHAR* wsEncode,
- const FX_WCHAR* wsHeader) {
+WideString CPDFSDK_FormFillEnvironment::PostRequestURL(
+ const wchar_t* wsURL,
+ const wchar_t* wsData,
+ const wchar_t* wsContentType,
+ const wchar_t* wsEncode,
+ const wchar_t* wsHeader) {
if (!m_pInfo || !m_pInfo->FFI_PostRequestURL)
return L"";
- CFX_ByteString bsURL = CFX_WideString(wsURL).UTF16LE_Encode();
+ ByteString bsURL = WideString(wsURL).UTF16LE_Encode();
FPDF_WIDESTRING URL = (FPDF_WIDESTRING)bsURL.GetBuffer(bsURL.GetLength());
- CFX_ByteString bsData = CFX_WideString(wsData).UTF16LE_Encode();
+ ByteString bsData = WideString(wsData).UTF16LE_Encode();
FPDF_WIDESTRING data = (FPDF_WIDESTRING)bsData.GetBuffer(bsData.GetLength());
- CFX_ByteString bsContentType = CFX_WideString(wsContentType).UTF16LE_Encode();
+ ByteString bsContentType = WideString(wsContentType).UTF16LE_Encode();
FPDF_WIDESTRING contentType =
(FPDF_WIDESTRING)bsContentType.GetBuffer(bsContentType.GetLength());
- CFX_ByteString bsEncode = CFX_WideString(wsEncode).UTF16LE_Encode();
+ ByteString bsEncode = WideString(wsEncode).UTF16LE_Encode();
FPDF_WIDESTRING encode =
(FPDF_WIDESTRING)bsEncode.GetBuffer(bsEncode.GetLength());
- CFX_ByteString bsHeader = CFX_WideString(wsHeader).UTF16LE_Encode();
+ ByteString bsHeader = WideString(wsHeader).UTF16LE_Encode();
FPDF_WIDESTRING header =
(FPDF_WIDESTRING)bsHeader.GetBuffer(bsHeader.GetLength());
@@ -506,53 +486,48 @@
m_pInfo->FFI_PostRequestURL(m_pInfo, URL, data, contentType, encode, header,
&response);
- CFX_WideString wsRet = CFX_WideString::FromUTF16LE(
+ WideString wsRet = WideString::FromUTF16LE(
(FPDF_WIDESTRING)response.str, response.len / sizeof(FPDF_WIDESTRING));
FPDF_BStr_Clear(&response);
return wsRet;
}
-FPDF_BOOL CPDFSDK_FormFillEnvironment::PutRequestURL(const FX_WCHAR* wsURL,
- const FX_WCHAR* wsData,
- const FX_WCHAR* wsEncode) {
+FPDF_BOOL CPDFSDK_FormFillEnvironment::PutRequestURL(const wchar_t* wsURL,
+ const wchar_t* wsData,
+ const wchar_t* wsEncode) {
if (!m_pInfo || !m_pInfo->FFI_PutRequestURL)
return false;
- CFX_ByteString bsURL = CFX_WideString(wsURL).UTF16LE_Encode();
+ ByteString bsURL = WideString(wsURL).UTF16LE_Encode();
FPDF_WIDESTRING URL = (FPDF_WIDESTRING)bsURL.GetBuffer(bsURL.GetLength());
- CFX_ByteString bsData = CFX_WideString(wsData).UTF16LE_Encode();
+ ByteString bsData = WideString(wsData).UTF16LE_Encode();
FPDF_WIDESTRING data = (FPDF_WIDESTRING)bsData.GetBuffer(bsData.GetLength());
- CFX_ByteString bsEncode = CFX_WideString(wsEncode).UTF16LE_Encode();
+ ByteString bsEncode = WideString(wsEncode).UTF16LE_Encode();
FPDF_WIDESTRING encode =
(FPDF_WIDESTRING)bsEncode.GetBuffer(bsEncode.GetLength());
return m_pInfo->FFI_PutRequestURL(m_pInfo, URL, data, encode);
}
-CFX_WideString CPDFSDK_FormFillEnvironment::GetLanguage() {
+WideString CPDFSDK_FormFillEnvironment::GetLanguage() {
if (!m_pInfo || !m_pInfo->FFI_GetLanguage)
- return L"";
+ return WideString();
int nRequiredLen = m_pInfo->FFI_GetLanguage(m_pInfo, nullptr, 0);
if (nRequiredLen <= 0)
- return L"";
+ return WideString();
- char* pbuff = new char[nRequiredLen];
- memset(pbuff, 0, nRequiredLen);
- int nActualLen = m_pInfo->FFI_GetLanguage(m_pInfo, pbuff, nRequiredLen);
- if (nActualLen <= 0 || nActualLen > nRequiredLen) {
- delete[] pbuff;
- return L"";
- }
- CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen);
- CFX_WideString wsRet = CFX_WideString::FromUTF16LE(
- (FPDF_WIDESTRING)bsRet.GetBuffer(bsRet.GetLength()),
- bsRet.GetLength() / sizeof(FPDF_WIDESTRING));
- delete[] pbuff;
- return wsRet;
+ std::vector<uint8_t> pBuff(nRequiredLen);
+ int nActualLen =
+ m_pInfo->FFI_GetLanguage(m_pInfo, pBuff.data(), nRequiredLen);
+ if (nActualLen <= 0 || nActualLen > nRequiredLen)
+ return WideString();
+
+ return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
+ nActualLen / sizeof(uint16_t));
}
void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount,
@@ -579,8 +554,10 @@
if (!renew)
return nullptr;
- CPDFSDK_PageView* pPageView = new CPDFSDK_PageView(this, pUnderlyingPage);
- m_PageMap[pUnderlyingPage].reset(pPageView);
+ auto pNew = pdfium::MakeUnique<CPDFSDK_PageView>(this, pUnderlyingPage);
+ CPDFSDK_PageView* pPageView = pNew.get();
+ m_PageMap[pUnderlyingPage] = std::move(pNew);
+
// Delay to load all the annotations, to avoid endless loop.
pPageView->LoadFXAnnots();
return pPageView;
@@ -588,13 +565,12 @@
CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() {
UnderlyingPageType* pPage =
- UnderlyingFromFPDFPage(GetCurrentPage(m_pUnderlyingDoc));
+ UnderlyingFromFPDFPage(GetCurrentPage(m_pUnderlyingDoc.Get()));
return pPage ? GetPageView(pPage, true) : nullptr;
}
CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(int nIndex) {
- UnderlyingPageType* pTempPage =
- UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex));
+ UnderlyingPageType* pTempPage = GetPage(nIndex);
if (!pTempPage)
return nullptr;
@@ -606,15 +582,10 @@
CPDF_Document* pPDFDoc = GetPDFDocument();
CPDF_DocJSActions docJS(pPDFDoc);
int iCount = docJS.CountJSActions();
- if (iCount < 1)
- return;
for (int i = 0; i < iCount; i++) {
- CFX_ByteString csJSName;
- CPDF_Action jsAction = docJS.GetJSAction(i, csJSName);
- if (GetActionHander()) {
- GetActionHander()->DoAction_JavaScript(
- jsAction, CFX_WideString::FromLocal(csJSName.AsStringC()), this);
- }
+ WideString csJSName;
+ CPDF_Action jsAction = docJS.GetJSActionAndName(i, &csJSName);
+ GetActionHandler()->DoAction_JavaScript(jsAction, csJSName, this);
}
}
@@ -622,27 +593,26 @@
if (!m_pUnderlyingDoc)
return false;
- CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot();
+ const CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot();
if (!pRoot)
return false;
CPDF_Object* pOpenAction = pRoot->GetDictFor("OpenAction");
if (!pOpenAction)
pOpenAction = pRoot->GetArrayFor("OpenAction");
-
if (!pOpenAction)
return false;
if (pOpenAction->IsArray())
return true;
- if (CPDF_Dictionary* pDict = pOpenAction->AsDictionary()) {
- CPDF_Action action(pDict);
- if (GetActionHander())
- GetActionHander()->DoAction_DocOpen(action, this);
- return true;
- }
- return false;
+ CPDF_Dictionary* pDict = pOpenAction->AsDictionary();
+ if (!pDict)
+ return false;
+
+ CPDF_Action action(pDict);
+ GetActionHandler()->DoAction_DocOpen(action, this);
+ return true;
}
void CPDFSDK_FormFillEnvironment::RemovePageView(
@@ -673,7 +643,10 @@
}
UnderlyingPageType* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) {
- return UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex));
+ if (!m_pInfo || !m_pInfo->FFI_GetPage)
+ return nullptr;
+ return UnderlyingFromFPDFPage(
+ m_pInfo->FFI_GetPage(m_pInfo, m_pUnderlyingDoc.Get(), nIndex));
}
CPDFSDK_InterForm* CPDFSDK_FormFillEnvironment::GetInterForm() {
@@ -702,59 +675,58 @@
if (!*pAnnot)
return false;
+ CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView();
+ if (!pPageView || !pPageView->IsValid())
+ return false;
+
+ CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr();
+ if (m_pFocusAnnot)
+ return false;
+
#ifdef PDF_ENABLE_XFA
CPDFSDK_Annot::ObservedPtr pLastFocusAnnot(m_pFocusAnnot.Get());
+ if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot))
+ return false;
#endif // PDF_ENABLE_XFA
- CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView();
- if (pPageView && pPageView->IsValid()) {
- CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr();
- if (!m_pFocusAnnot) {
-#ifdef PDF_ENABLE_XFA
- if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot))
- return false;
-#endif // PDF_ENABLE_XFA
- if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0))
- return false;
- if (!m_pFocusAnnot) {
- m_pFocusAnnot.Reset(pAnnot->Get());
- return true;
- }
- }
- }
- return false;
+ if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0))
+ return false;
+ if (m_pFocusAnnot)
+ return false;
+
+ m_pFocusAnnot.Reset(pAnnot->Get());
+ return true;
}
bool CPDFSDK_FormFillEnvironment::KillFocusAnnot(uint32_t nFlag) {
- if (m_pFocusAnnot) {
- CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr();
- CPDFSDK_Annot::ObservedPtr pFocusAnnot(m_pFocusAnnot.Get());
- m_pFocusAnnot.Reset();
+ if (!m_pFocusAnnot)
+ return false;
+
+ CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr();
+ CPDFSDK_Annot::ObservedPtr pFocusAnnot(m_pFocusAnnot.Get());
+ m_pFocusAnnot.Reset();
#ifdef PDF_ENABLE_XFA
- CPDFSDK_Annot::ObservedPtr pNull;
- if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot))
- return false;
+ CPDFSDK_Annot::ObservedPtr pNull;
+ if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot))
+ return false;
#endif // PDF_ENABLE_XFA
- if (pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) {
- if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) {
- CPDFSDK_Widget* pWidget =
- static_cast<CPDFSDK_Widget*>(pFocusAnnot.Get());
- int nFieldType = pWidget->GetFieldType();
- if (FIELDTYPE_TEXTFIELD == nFieldType ||
- FIELDTYPE_COMBOBOX == nFieldType) {
- OnSetFieldInputFocus(nullptr, 0, false);
- }
- }
- if (!m_pFocusAnnot)
- return true;
- } else {
- m_pFocusAnnot.Reset(pFocusAnnot.Get());
+ if (!pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) {
+ m_pFocusAnnot.Reset(pFocusAnnot.Get());
+ return false;
+ }
+
+ if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) {
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pFocusAnnot.Get());
+ FormFieldType fieldType = pWidget->GetFieldType();
+ if (fieldType == FormFieldType::kTextField ||
+ fieldType == FormFieldType::kComboBox) {
+ OnSetFieldInputFocus(nullptr, 0, false);
}
}
- return false;
+ return !m_pFocusAnnot;
}
-bool CPDFSDK_FormFillEnvironment::GetPermissions(int nFlag) {
+bool CPDFSDK_FormFillEnvironment::GetPermissions(int nFlag) const {
return !!(GetPDFDocument()->GetUserPermissions() & nFlag);
}
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.h b/fpdfsdk/cpdfsdk_formfillenvironment.h
index eead873..31a1c51 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.h
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.h
@@ -14,7 +14,7 @@
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfdoc/cpdf_occontext.h"
-#include "core/fxcrt/cfx_observable.h"
+#include "core/fxcrt/observable.h"
#include "fpdfsdk/cfx_systemhandler.h"
#include "fpdfsdk/cpdfsdk_annot.h"
#include "fpdfsdk/fsdk_define.h"
@@ -29,13 +29,34 @@
class CPDFSDK_PageView;
class IJS_Runtime;
+// The CPDFSDK_FormFillEnvironment is "owned" by the embedder across the
+// C API as a FPDF_FormHandle, and may pop out of existence at any time,
+// so long as the associated embedder-owned FPDF_Document outlives it.
+// Pointers from objects in the FPDF_Document ownership hierarchy should
+// be ObservedPtr<> so as to clear themselves when the embedder "exits"
+// the form fill environment. Pointers from objects in this ownership
+// heirarcy to objects in the FPDF_Document ownership hierarcy should be
+// UnownedPtr<>, as should pointers from objects in this ownership
+// hierarcy back to the form fill environment itself, so as to flag any
+// lingering lifetime issues via the memory tools.
+
class CPDFSDK_FormFillEnvironment
- : public CFX_Observable<CPDFSDK_FormFillEnvironment> {
+ : public Observable<CPDFSDK_FormFillEnvironment> {
public:
CPDFSDK_FormFillEnvironment(UnderlyingDocumentType* pDoc,
FPDF_FORMFILLINFO* pFFinfo);
~CPDFSDK_FormFillEnvironment();
+ static bool IsSHIFTKeyDown(uint32_t nFlag) {
+ return !!(nFlag & FWL_EVENTFLAG_ShiftKey);
+ }
+ static bool IsCTRLKeyDown(uint32_t nFlag) {
+ return !!(nFlag & FWL_EVENTFLAG_ControlKey);
+ }
+ static bool IsALTKeyDown(uint32_t nFlag) {
+ return !!(nFlag & FWL_EVENTFLAG_AltKey);
+ }
+
CPDFSDK_PageView* GetPageView(UnderlyingPageType* pPage, bool renew);
CPDFSDK_PageView* GetPageView(int nIndex);
CPDFSDK_PageView* GetCurrentView();
@@ -56,20 +77,18 @@
const CPDF_Document* pSrcDoc,
const std::vector<uint16_t>& arrSrcPages);
- int GetPageCount() { return m_pUnderlyingDoc->GetPageCount(); }
- bool GetPermissions(int nFlag);
+ int GetPageCount() const { return m_pUnderlyingDoc->GetPageCount(); }
+ bool GetPermissions(int nFlag) const;
bool GetChangeMark() const { return m_bChangeMask; }
void SetChangeMark() { m_bChangeMask = true; }
void ClearChangeMark() { m_bChangeMask = false; }
- UnderlyingPageType* GetPage(int nIndex);
-
void ProcJavascriptFun();
bool ProcOpenAction();
- void Invalidate(FPDF_PAGE page, const FX_RECT& rect);
- void OutputSelectedRect(FPDF_PAGE page, const CFX_FloatRect& rect);
+ void Invalidate(UnderlyingPageType* page, const FX_RECT& rect);
+ void OutputSelectedRect(UnderlyingPageType* page, const CFX_FloatRect& rect);
void SetCursor(int nCursorType);
int SetTimer(int uElapse, TimerCallback lpTimerFunc);
@@ -77,25 +96,21 @@
FX_SYSTEMTIME GetLocalTime() const;
void OnChange();
- bool IsSHIFTKeyDown(uint32_t nFlag) const;
- bool IsCTRLKeyDown(uint32_t nFlag) const;
- bool IsALTKeyDown(uint32_t nFlag) const;
- FPDF_PAGE GetPage(FPDF_DOCUMENT document, int nPageIndex);
- FPDF_PAGE GetCurrentPage(FPDF_DOCUMENT document);
+ FPDF_PAGE GetCurrentPage(UnderlyingDocumentType* document);
- void ExecuteNamedAction(const FX_CHAR* namedAction);
+ void ExecuteNamedAction(const char* namedAction);
void OnSetFieldInputFocus(FPDF_WIDESTRING focusText,
FPDF_DWORD nTextLen,
bool bFocus);
- void DoURIAction(const FX_CHAR* bsURI);
+ void DoURIAction(const char* bsURI);
void DoGoToAction(int nPageIndex,
int zoomMode,
float* fPosArray,
int sizeOfArray);
UnderlyingDocumentType* GetUnderlyingDocument() const {
- return m_pUnderlyingDoc;
+ return m_pUnderlyingDoc.Get();
}
#ifdef PDF_ENABLE_XFA
@@ -103,27 +118,27 @@
return m_pUnderlyingDoc ? m_pUnderlyingDoc->GetPDFDoc() : nullptr;
}
- CPDFXFA_Context* GetXFAContext() const { return m_pUnderlyingDoc; }
+ CPDFXFA_Context* GetXFAContext() const { return m_pUnderlyingDoc.Get(); }
void ResetXFADocument() { m_pUnderlyingDoc = nullptr; }
int GetPageViewCount() const { return m_PageMap.size(); }
- void DisplayCaret(FPDF_PAGE page,
+ void DisplayCaret(CPDFXFA_Page* page,
FPDF_BOOL bVisible,
double left,
double top,
double right,
double bottom);
- int GetCurrentPageIndex(FPDF_DOCUMENT document);
- void SetCurrentPage(FPDF_DOCUMENT document, int iCurPage);
+ int GetCurrentPageIndex(CPDFXFA_Context* document);
+ void SetCurrentPage(CPDFXFA_Context* document, int iCurPage);
// TODO(dsinclair): This should probably change to PDFium?
- CFX_WideString FFI_GetAppName() const { return CFX_WideString(L"Acrobat"); }
+ WideString FFI_GetAppName() const { return WideString(L"Acrobat"); }
- CFX_WideString GetPlatform();
- void GotoURL(FPDF_DOCUMENT document, const CFX_WideStringC& wsURL);
- void GetPageViewRect(FPDF_PAGE page, FS_RECTF& dstRect);
- bool PopupMenu(FPDF_PAGE page,
+ WideString GetPlatform();
+ void GotoURL(CPDFXFA_Context* document, const WideStringView& wsURL);
+ void GetPageViewRect(CPDFXFA_Page* page, FS_RECTF& dstRect);
+ bool PopupMenu(CPDFXFA_Page* page,
FPDF_WIDGET hWidget,
int menuFlag,
CFX_PointF pt);
@@ -141,45 +156,45 @@
FPDF_FILEHANDLER* OpenFile(int fileType,
FPDF_WIDESTRING wsURL,
const char* mode);
- CFX_RetainPtr<IFX_SeekableReadStream> DownloadFromURL(const FX_WCHAR* url);
- CFX_WideString PostRequestURL(const FX_WCHAR* wsURL,
- const FX_WCHAR* wsData,
- const FX_WCHAR* wsContentType,
- const FX_WCHAR* wsEncode,
- const FX_WCHAR* wsHeader);
- FPDF_BOOL PutRequestURL(const FX_WCHAR* wsURL,
- const FX_WCHAR* wsData,
- const FX_WCHAR* wsEncode);
- CFX_WideString GetLanguage();
+ RetainPtr<IFX_SeekableReadStream> DownloadFromURL(const wchar_t* url);
+ WideString PostRequestURL(const wchar_t* wsURL,
+ const wchar_t* wsData,
+ const wchar_t* wsContentType,
+ const wchar_t* wsEncode,
+ const wchar_t* wsHeader);
+ FPDF_BOOL PutRequestURL(const wchar_t* wsURL,
+ const wchar_t* wsData,
+ const wchar_t* wsEncode);
+ WideString GetLanguage();
void PageEvent(int iPageCount, uint32_t dwEventType) const;
#else // PDF_ENABLE_XFA
- CPDF_Document* GetPDFDocument() const { return m_pUnderlyingDoc; }
+ CPDF_Document* GetPDFDocument() const { return m_pUnderlyingDoc.Get(); }
#endif // PDF_ENABLE_XFA
- int JS_appAlert(const FX_WCHAR* Msg,
- const FX_WCHAR* Title,
+ int JS_appAlert(const wchar_t* Msg,
+ const wchar_t* Title,
uint32_t Type,
uint32_t Icon);
- int JS_appResponse(const FX_WCHAR* Question,
- const FX_WCHAR* Title,
- const FX_WCHAR* Default,
- const FX_WCHAR* cLabel,
+ int JS_appResponse(const wchar_t* Question,
+ const wchar_t* Title,
+ const wchar_t* Default,
+ const wchar_t* cLabel,
FPDF_BOOL bPassword,
void* response,
int length);
void JS_appBeep(int nType);
- CFX_WideString JS_fieldBrowse();
- CFX_WideString JS_docGetFilePath();
- void JS_docSubmitForm(void* formData, int length, const FX_WCHAR* URL);
+ WideString JS_fieldBrowse();
+ WideString JS_docGetFilePath();
+ void JS_docSubmitForm(void* formData, int length, const wchar_t* URL);
void JS_docmailForm(void* mailData,
int length,
FPDF_BOOL bUI,
- const FX_WCHAR* To,
- const FX_WCHAR* Subject,
- const FX_WCHAR* CC,
- const FX_WCHAR* BCC,
- const FX_WCHAR* Msg);
+ const wchar_t* To,
+ const wchar_t* Subject,
+ const wchar_t* CC,
+ const wchar_t* BCC,
+ const wchar_t* Msg);
void JS_docprint(FPDF_BOOL bUI,
int nStart,
int nEnd,
@@ -191,7 +206,7 @@
void JS_docgotoPage(int nPageNum);
bool IsJSInitiated() const { return m_pInfo && m_pInfo->m_pJsPlatform; }
- CFX_ByteString GetAppName() const { return ""; }
+ ByteString GetAppName() const { return ""; }
CFX_SystemHandler* GetSysHandler() const { return m_pSysHandler.get(); }
FPDF_FORMFILLINFO* GetFormFillInfo() const { return m_pInfo; }
@@ -199,18 +214,20 @@
CFFL_InteractiveFormFiller* GetInteractiveFormFiller();
CPDFSDK_AnnotHandlerMgr* GetAnnotHandlerMgr(); // Creates if not present.
IJS_Runtime* GetJSRuntime(); // Creates if not present.
- CPDFSDK_ActionHandler* GetActionHander(); // Creates if not present.
+ CPDFSDK_ActionHandler* GetActionHandler(); // Creates if not present.
CPDFSDK_InterForm* GetInterForm(); // Creates if not present.
private:
+ UnderlyingPageType* GetPage(int nIndex);
+
+ FPDF_FORMFILLINFO* const m_pInfo;
std::unique_ptr<CPDFSDK_AnnotHandlerMgr> m_pAnnotHandlerMgr;
std::unique_ptr<CPDFSDK_ActionHandler> m_pActionHandler;
std::unique_ptr<IJS_Runtime> m_pJSRuntime;
- FPDF_FORMFILLINFO* const m_pInfo;
std::map<UnderlyingPageType*, std::unique_ptr<CPDFSDK_PageView>> m_PageMap;
std::unique_ptr<CPDFSDK_InterForm> m_pInterForm;
CPDFSDK_Annot::ObservedPtr m_pFocusAnnot;
- UnderlyingDocumentType* m_pUnderlyingDoc;
+ UnownedPtr<UnderlyingDocumentType> m_pUnderlyingDoc;
std::unique_ptr<CFFL_InteractiveFormFiller> m_pFormFiller;
std::unique_ptr<CFX_SystemHandler> m_pSysHandler;
bool m_bChangeMask;
diff --git a/fpdfsdk/cpdfsdk_interform.cpp b/fpdfsdk/cpdfsdk_interform.cpp
index 4ebcf8a..e19d47b 100644
--- a/fpdfsdk/cpdfsdk_interform.cpp
+++ b/fpdfsdk/cpdfsdk_interform.cpp
@@ -8,6 +8,8 @@
#include <algorithm>
#include <memory>
+#include <sstream>
+#include <string>
#include <vector>
#include "core/fpdfapi/page/cpdf_page.h"
@@ -19,7 +21,6 @@
#include "core/fpdfdoc/cpdf_interform.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_pathdata.h"
-#include "core/fxge/cfx_renderdevice.h"
#include "fpdfsdk/cba_annotiterator.h"
#include "fpdfsdk/cpdfsdk_annot.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
@@ -28,11 +29,9 @@
#include "fpdfsdk/formfiller/cffl_formfiller.h"
#include "fpdfsdk/fsdk_actionhandler.h"
#include "fpdfsdk/fsdk_define.h"
-#include "fpdfsdk/fxedit/fxet_edit.h"
#include "fpdfsdk/ipdfsdk_annothandler.h"
-#include "fpdfsdk/javascript/ijs_event_context.h"
-#include "fpdfsdk/javascript/ijs_runtime.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
+#include "fxjs/ijs_event_context.h"
+#include "fxjs/ijs_runtime.h"
#include "third_party/base/stl_util.h"
#ifdef PDF_ENABLE_XFA
@@ -40,24 +39,56 @@
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
#include "xfa/fxfa/cxfa_eventparam.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffwidget.h"
-#include "xfa/fxfa/xfa_ffwidgethandler.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
+#include "xfa/fxfa/cxfa_ffwidgethandler.h"
#endif // PDF_ENABLE_XFA
+namespace {
+
+bool IsFormFieldTypeComboOrText(FormFieldType fieldType) {
+ switch (fieldType) {
+ case FormFieldType::kComboBox:
+ case FormFieldType::kTextField:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#ifdef PDF_ENABLE_XFA
+bool IsFormFieldTypeXFA(FormFieldType fieldType) {
+ switch (fieldType) {
+ case FormFieldType::kXFA:
+ case FormFieldType::kXFA_CheckBox:
+ case FormFieldType::kXFA_ComboBox:
+ case FormFieldType::kXFA_ImageField:
+ case FormFieldType::kXFA_ListBox:
+ case FormFieldType::kXFA_PushButton:
+ case FormFieldType::kXFA_Signature:
+ case FormFieldType::kXFA_TextField:
+ return true;
+ default:
+ return false;
+ }
+}
+#endif // PDF_ENABLE_XFA
+
+} // namespace
+
CPDFSDK_InterForm::CPDFSDK_InterForm(CPDFSDK_FormFillEnvironment* pFormFillEnv)
: m_pFormFillEnv(pFormFillEnv),
- m_pInterForm(new CPDF_InterForm(m_pFormFillEnv->GetPDFDocument())),
+ m_pInterForm(
+ pdfium::MakeUnique<CPDF_InterForm>(m_pFormFillEnv->GetPDFDocument())),
#ifdef PDF_ENABLE_XFA
m_bXfaCalculate(true),
m_bXfaValidationsEnabled(true),
#endif // PDF_ENABLE_XFA
m_bCalculate(true),
m_bBusy(false),
- m_iHighlightAlpha(0) {
+ m_HighlightAlpha(0) {
m_pInterForm->SetFormNotify(this);
- for (int i = 0; i < kNumFieldTypes; ++i)
- m_bNeedHightlight[i] = false;
+ RemoveAllHighLights();
}
CPDFSDK_InterForm::~CPDFSDK_InterForm() {
@@ -73,8 +104,8 @@
CPDFSDK_Widget* CPDFSDK_InterForm::GetSibling(CPDFSDK_Widget* pWidget,
bool bNext) const {
- std::unique_ptr<CBA_AnnotIterator> pIterator(new CBA_AnnotIterator(
- pWidget->GetPageView(), CPDF_Annot::Subtype::WIDGET));
+ auto pIterator = pdfium::MakeUnique<CBA_AnnotIterator>(
+ pWidget->GetPageView(), CPDF_Annot::Subtype::WIDGET);
if (bNext)
return static_cast<CPDFSDK_Widget*>(pIterator->GetNextAnnot(pWidget));
@@ -116,7 +147,7 @@
}
void CPDFSDK_InterForm::GetWidgets(
- const CFX_WideString& sFieldName,
+ const WideString& sFieldName,
std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const {
for (int i = 0, sz = m_pInterForm->CountFields(sFieldName); i < sz; ++i) {
CPDF_FormField* pFormField = m_pInterForm->GetField(i, sFieldName);
@@ -237,8 +268,8 @@
if (!pField)
continue;
- int nType = pField->GetFieldType();
- if (nType != FIELDTYPE_COMBOBOX && nType != FIELDTYPE_TEXTFIELD)
+ FormFieldType fieldType = pField->GetFieldType();
+ if (!IsFormFieldTypeComboOrText(fieldType))
continue;
CPDF_AAction aAction = pField->GetAdditionalAction();
@@ -249,17 +280,17 @@
if (!action.GetDict())
continue;
- CFX_WideString csJS = action.GetJavaScript();
+ WideString csJS = action.GetJavaScript();
if (csJS.IsEmpty())
continue;
IJS_EventContext* pContext = pRuntime->NewEventContext();
- CFX_WideString sOldValue = pField->GetValue();
- CFX_WideString sValue = sOldValue;
+ WideString sOldValue = pField->GetValue();
+ WideString sValue = sOldValue;
bool bRC = true;
pContext->OnField_Calculate(pFormField, pField, sValue, bRC);
- CFX_WideString sInfo;
+ WideString sInfo;
bool bRet = pContext->RunScript(csJS, &sInfo);
pRuntime->ReleaseEventContext(pContext);
if (bRet && bRC && sValue.Compare(sOldValue) != 0)
@@ -268,16 +299,16 @@
m_bBusy = false;
}
-CFX_WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField,
- bool& bFormatted) {
- CFX_WideString sValue = pFormField->GetValue();
+WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField,
+ bool& bFormatted) {
+ WideString sValue = pFormField->GetValue();
if (!m_pFormFillEnv->IsJSInitiated()) {
bFormatted = false;
return sValue;
}
IJS_Runtime* pRuntime = m_pFormFillEnv->GetJSRuntime();
- if (pFormField->GetFieldType() == FIELDTYPE_COMBOBOX &&
+ if (pFormField->GetFieldType() == FormFieldType::kComboBox &&
pFormField->CountSelectedItems() > 0) {
int index = pFormField->GetSelectedIndex(0);
if (index >= 0)
@@ -290,13 +321,13 @@
if (aAction.GetDict() && aAction.ActionExist(CPDF_AAction::Format)) {
CPDF_Action action = aAction.GetAction(CPDF_AAction::Format);
if (action.GetDict()) {
- CFX_WideString script = action.GetJavaScript();
+ WideString script = action.GetJavaScript();
if (!script.IsEmpty()) {
- CFX_WideString Value = sValue;
+ WideString Value = sValue;
IJS_EventContext* pContext = pRuntime->NewEventContext();
pContext->OnField_Format(pFormField, Value, true);
- CFX_WideString sInfo;
+ WideString sInfo;
bool bRet = pContext->RunScript(script, &sInfo);
pRuntime->ReleaseEventContext(pContext);
if (bRet) {
@@ -310,7 +341,7 @@
}
void CPDFSDK_InterForm::ResetFieldAppearance(CPDF_FormField* pFormField,
- const CFX_WideString* sValue,
+ const WideString* sValue,
bool bValueChanged) {
for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
@@ -321,22 +352,24 @@
}
void CPDFSDK_InterForm::UpdateField(CPDF_FormField* pFormField) {
- auto formfiller = m_pFormFillEnv->GetInteractiveFormFiller();
+ auto* formfiller = m_pFormFillEnv->GetInteractiveFormFiller();
for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
ASSERT(pFormCtrl);
- if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) {
- UnderlyingPageType* pPage = pWidget->GetUnderlyingPage();
- m_pFormFillEnv->Invalidate(
- pPage, formfiller->GetViewBBox(
- m_pFormFillEnv->GetPageView(pPage, false), pWidget));
- }
+ CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
+ if (!pWidget)
+ continue;
+
+ UnderlyingPageType* pPage = pWidget->GetUnderlyingPage();
+ FX_RECT rect = formfiller->GetViewBBox(
+ m_pFormFillEnv->GetPageView(pPage, false), pWidget);
+ m_pFormFillEnv->Invalidate(pPage, rect);
}
}
bool CPDFSDK_InterForm::OnKeyStrokeCommit(CPDF_FormField* pFormField,
- const CFX_WideString& csValue) {
+ const WideString& csValue) {
CPDF_AAction aAction = pFormField->GetAdditionalAction();
if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::KeyStroke))
return true;
@@ -345,18 +378,18 @@
if (!action.GetDict())
return true;
- CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHander();
+ CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler();
PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(0);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(0);
+ fa.bModifier = false;
+ fa.bShift = false;
fa.sValue = csValue;
- pActionHandler->DoAction_FieldJavaScript(action, CPDF_AAction::KeyStroke,
- m_pFormFillEnv, pFormField, fa);
+ pActionHandler->DoAction_FieldJavaScript(
+ action, CPDF_AAction::KeyStroke, m_pFormFillEnv.Get(), pFormField, fa);
return fa.bRC;
}
bool CPDFSDK_InterForm::OnValidate(CPDF_FormField* pFormField,
- const CFX_WideString& csValue) {
+ const WideString& csValue) {
CPDF_AAction aAction = pFormField->GetAdditionalAction();
if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::Validate))
return true;
@@ -365,13 +398,13 @@
if (!action.GetDict())
return true;
- CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHander();
+ CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler();
PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(0);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(0);
+ fa.bModifier = false;
+ fa.bShift = false;
fa.sValue = csValue;
- pActionHandler->DoAction_FieldJavaScript(action, CPDF_AAction::Validate,
- m_pFormFillEnv, pFormField, fa);
+ pActionHandler->DoAction_FieldJavaScript(
+ action, CPDF_AAction::Validate, m_pFormFillEnv.Get(), pFormField, fa);
return fa.bRC;
}
@@ -409,7 +442,7 @@
}
bool CPDFSDK_InterForm::DoAction_SubmitForm(const CPDF_Action& action) {
- CFX_WideString sDestination = action.GetFilePath();
+ WideString sDestination = action.GetFilePath();
if (sDestination.IsEmpty())
return false;
@@ -433,30 +466,36 @@
return SubmitForm(sDestination, false);
}
-bool CPDFSDK_InterForm::SubmitFields(const CFX_WideString& csDestination,
+bool CPDFSDK_InterForm::SubmitFields(const WideString& csDestination,
const std::vector<CPDF_FormField*>& fields,
bool bIncludeOrExclude,
bool bUrlEncoded) {
- CFX_ByteTextBuf textBuf;
- ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude, textBuf);
+ ByteString textBuf = ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude);
- uint8_t* pBuffer = textBuf.GetBuffer();
- FX_STRSIZE nBufSize = textBuf.GetLength();
-
- if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize))
+ size_t nBufSize = textBuf.GetLength();
+ if (nBufSize == 0)
return false;
+ uint8_t* pLocalBuffer = FX_Alloc(uint8_t, nBufSize);
+ memcpy(pLocalBuffer, textBuf.c_str(), nBufSize);
+ uint8_t* pBuffer = pLocalBuffer;
+
+ if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) {
+ FX_Free(pLocalBuffer);
+ return false;
+ }
+
m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, csDestination.c_str());
+
+ if (pBuffer != pLocalBuffer)
+ FX_Free(pBuffer);
+
+ FX_Free(pLocalBuffer);
+
return true;
}
-bool CPDFSDK_InterForm::FDFToURLEncodedData(CFX_WideString csFDFFile,
- CFX_WideString csTxtFile) {
- return true;
-}
-
-bool CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf,
- FX_STRSIZE& nBufSize) {
+bool CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf, size_t& nBufSize) {
std::unique_ptr<CFDF_Document> pFDF =
CFDF_Document::ParseMemory(pBuf, nBufSize);
if (!pFDF)
@@ -470,49 +509,46 @@
if (!pFields)
return false;
- CFX_ByteTextBuf fdfEncodedData;
+ std::ostringstream fdfEncodedData;
for (uint32_t i = 0; i < pFields->GetCount(); i++) {
CPDF_Dictionary* pField = pFields->GetDictAt(i);
if (!pField)
continue;
- CFX_WideString name;
+ WideString name;
name = pField->GetUnicodeTextFor("T");
- CFX_ByteString name_b = CFX_ByteString::FromUnicode(name);
- CFX_ByteString csBValue = pField->GetStringFor("V");
- CFX_WideString csWValue = PDF_DecodeText(csBValue);
- CFX_ByteString csValue_b = CFX_ByteString::FromUnicode(csWValue);
+ ByteString name_b = ByteString::FromUnicode(name);
+ ByteString csBValue = pField->GetStringFor("V");
+ WideString csWValue = PDF_DecodeText(csBValue);
+ ByteString csValue_b = ByteString::FromUnicode(csWValue);
fdfEncodedData << name_b.GetBuffer(name_b.GetLength());
- name_b.ReleaseBuffer();
+ name_b.ReleaseBuffer(name_b.GetStringLength());
fdfEncodedData << "=";
fdfEncodedData << csValue_b.GetBuffer(csValue_b.GetLength());
- csValue_b.ReleaseBuffer();
+ csValue_b.ReleaseBuffer(csValue_b.GetStringLength());
if (i != pFields->GetCount() - 1)
fdfEncodedData << "&";
}
- nBufSize = fdfEncodedData.GetLength();
+ nBufSize = fdfEncodedData.tellp();
+ if (nBufSize == 0)
+ return false;
+
pBuf = FX_Alloc(uint8_t, nBufSize);
- FXSYS_memcpy(pBuf, fdfEncodedData.GetBuffer(), nBufSize);
+ memcpy(pBuf, fdfEncodedData.str().c_str(), nBufSize);
return true;
}
-bool CPDFSDK_InterForm::ExportFieldsToFDFTextBuf(
+ByteString CPDFSDK_InterForm::ExportFieldsToFDFTextBuf(
const std::vector<CPDF_FormField*>& fields,
- bool bIncludeOrExclude,
- CFX_ByteTextBuf& textBuf) {
- std::unique_ptr<CFDF_Document> pFDF =
- m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath().AsStringC(),
- fields, bIncludeOrExclude, false);
- return pFDF ? pFDF->WriteBuf(textBuf) : false;
+ bool bIncludeOrExclude) {
+ std::unique_ptr<CFDF_Document> pFDF = m_pInterForm->ExportToFDF(
+ m_pFormFillEnv->JS_docGetFilePath(), fields, bIncludeOrExclude, false);
+
+ return pFDF ? pFDF->WriteToString() : ByteString();
}
-CFX_WideString CPDFSDK_InterForm::GetTemporaryFileName(
- const CFX_WideString& sFileExt) {
- return L"";
-}
-
-bool CPDFSDK_InterForm::SubmitForm(const CFX_WideString& sDestination,
+bool CPDFSDK_InterForm::SubmitForm(const WideString& sDestination,
bool bUrlEncoded) {
if (sDestination.IsEmpty())
return false;
@@ -520,31 +556,41 @@
if (!m_pFormFillEnv || !m_pInterForm)
return false;
- std::unique_ptr<CFDF_Document> pFDFDoc = m_pInterForm->ExportToFDF(
- m_pFormFillEnv->JS_docGetFilePath().AsStringC(), false);
+ std::unique_ptr<CFDF_Document> pFDFDoc =
+ m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false);
if (!pFDFDoc)
return false;
- CFX_ByteTextBuf FdfBuffer;
- if (!pFDFDoc->WriteBuf(FdfBuffer))
+ ByteString fdfBuffer = pFDFDoc->WriteToString();
+
+ if (fdfBuffer.IsEmpty())
return false;
- uint8_t* pBuffer = FdfBuffer.GetBuffer();
- FX_STRSIZE nBufSize = FdfBuffer.GetLength();
- if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize))
+ uint8_t* pLocalBuffer = FX_Alloc(uint8_t, fdfBuffer.GetLength());
+ memcpy(pLocalBuffer, fdfBuffer.c_str(), fdfBuffer.GetLength());
+ uint8_t* pBuffer = pLocalBuffer;
+
+ size_t nBufSize = fdfBuffer.GetLength();
+ if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) {
+ FX_Free(pLocalBuffer);
return false;
+ }
m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, sDestination.c_str());
- if (bUrlEncoded)
+
+ if (pBuffer != pLocalBuffer)
FX_Free(pBuffer);
+ FX_Free(pLocalBuffer);
+
return true;
}
-bool CPDFSDK_InterForm::ExportFormToFDFTextBuf(CFX_ByteTextBuf& textBuf) {
- std::unique_ptr<CFDF_Document> pFDF = m_pInterForm->ExportToFDF(
- m_pFormFillEnv->JS_docGetFilePath().AsStringC(), false);
- return pFDF && pFDF->WriteBuf(textBuf);
+ByteString CPDFSDK_InterForm::ExportFormToFDFTextBuf() {
+ std::unique_ptr<CFDF_Document> pFDF =
+ m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false);
+
+ return pFDF ? pFDF->WriteToString() : ByteString();
}
bool CPDFSDK_InterForm::DoAction_ResetForm(const CPDF_Action& action) {
@@ -571,7 +617,7 @@
std::vector<CPDF_FormField*> fields;
for (CPDF_Object* pObject : objects) {
if (pObject && pObject->IsString()) {
- CFX_WideString csName = pObject->GetUnicodeText();
+ WideString csName = pObject->GetUnicodeText();
CPDF_FormField* pField = m_pInterForm->GetField(0, csName);
if (pField)
fields.push_back(pField);
@@ -581,9 +627,9 @@
}
int CPDFSDK_InterForm::BeforeValueChange(CPDF_FormField* pField,
- const CFX_WideString& csValue) {
- int nType = pField->GetFieldType();
- if (nType != FIELDTYPE_COMBOBOX && nType != FIELDTYPE_TEXTFIELD)
+ const WideString& csValue) {
+ FormFieldType fieldType = pField->GetFieldType();
+ if (!IsFormFieldTypeComboOrText(fieldType))
return 0;
if (!OnKeyStrokeCommit(pField, csValue))
@@ -599,19 +645,19 @@
#ifdef PDF_ENABLE_XFA
SynchronizeField(pField, false);
#endif // PDF_ENABLE_XFA
- int nType = pField->GetFieldType();
- if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
+ FormFieldType fieldType = pField->GetFieldType();
+ if (IsFormFieldTypeComboOrText(fieldType)) {
OnCalculate(pField);
bool bFormatted = false;
- CFX_WideString sValue = OnFormat(pField, bFormatted);
+ WideString sValue = OnFormat(pField, bFormatted);
ResetFieldAppearance(pField, bFormatted ? &sValue : nullptr, true);
UpdateField(pField);
}
}
int CPDFSDK_InterForm::BeforeSelectionChange(CPDF_FormField* pField,
- const CFX_WideString& csValue) {
- if (pField->GetFieldType() != FIELDTYPE_LISTBOX)
+ const WideString& csValue) {
+ if (pField->GetFieldType() != FormFieldType::kListBox)
return 0;
if (!OnKeyStrokeCommit(pField, csValue))
@@ -624,7 +670,7 @@
}
void CPDFSDK_InterForm::AfterSelectionChange(CPDF_FormField* pField) {
- if (pField->GetFieldType() != FIELDTYPE_LISTBOX)
+ if (pField->GetFieldType() != FormFieldType::kListBox)
return;
OnCalculate(pField);
@@ -633,8 +679,9 @@
}
void CPDFSDK_InterForm::AfterCheckedStatusChange(CPDF_FormField* pField) {
- int nType = pField->GetFieldType();
- if (nType != FIELDTYPE_CHECKBOX && nType != FIELDTYPE_RADIOBUTTON)
+ FormFieldType fieldType = pField->GetFieldType();
+ if (fieldType != FormFieldType::kCheckBox &&
+ fieldType != FormFieldType::kRadioButton)
return;
OnCalculate(pField);
@@ -657,40 +704,56 @@
OnCalculate(nullptr);
}
-bool CPDFSDK_InterForm::IsNeedHighLight(int nFieldType) {
- if (nFieldType < 1 || nFieldType > kNumFieldTypes)
+bool CPDFSDK_InterForm::IsNeedHighLight(FormFieldType fieldType) {
+ if (fieldType == FormFieldType::kUnknown)
return false;
- return m_bNeedHightlight[nFieldType - 1];
+
+#ifdef PDF_ENABLE_XFA
+ // For the XFA fields, we need to return if the specific field type has
+ // highlight enabled or if the general XFA field type has it enabled.
+ if (IsFormFieldTypeXFA(fieldType)) {
+ if (!m_NeedsHighlight[static_cast<size_t>(fieldType)])
+ return m_NeedsHighlight[static_cast<size_t>(FormFieldType::kXFA)];
+ }
+#endif // PDF_ENABLE_XFA
+ return m_NeedsHighlight[static_cast<size_t>(fieldType)];
}
-void CPDFSDK_InterForm::RemoveAllHighLight() {
- for (int i = 0; i < kNumFieldTypes; ++i)
- m_bNeedHightlight[i] = false;
+void CPDFSDK_InterForm::RemoveAllHighLights() {
+ std::fill(m_HighlightColor, m_HighlightColor + kFormFieldTypeCount,
+ FXSYS_RGB(255, 255, 255));
+ std::fill(m_NeedsHighlight, m_NeedsHighlight + kFormFieldTypeCount, false);
}
-void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr, int nFieldType) {
- if (nFieldType < 0 || nFieldType > kNumFieldTypes)
+void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr,
+ FormFieldType fieldType) {
+ if (fieldType == FormFieldType::kUnknown)
return;
- switch (nFieldType) {
- case 0: {
- for (int i = 0; i < kNumFieldTypes; ++i) {
- m_aHighlightColor[i] = clr;
- m_bNeedHightlight[i] = true;
- }
- break;
- }
- default: {
- m_aHighlightColor[nFieldType - 1] = clr;
- m_bNeedHightlight[nFieldType - 1] = true;
- break;
- }
+
+ m_HighlightColor[static_cast<size_t>(fieldType)] = clr;
+ m_NeedsHighlight[static_cast<size_t>(fieldType)] = true;
+}
+
+void CPDFSDK_InterForm::SetAllHighlightColors(FX_COLORREF clr) {
+ for (auto type : kFormFieldTypes) {
+ m_HighlightColor[static_cast<size_t>(type)] = clr;
+ m_NeedsHighlight[static_cast<size_t>(type)] = true;
}
}
-FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(int nFieldType) {
- if (nFieldType < 0 || nFieldType > kNumFieldTypes)
+FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(FormFieldType fieldType) {
+ if (fieldType == FormFieldType::kUnknown)
return FXSYS_RGB(255, 255, 255);
- if (nFieldType == 0)
- return m_aHighlightColor[0];
- return m_aHighlightColor[nFieldType - 1];
+
+#ifdef PDF_ENABLE_XFA
+ // For the XFA fields, we need to return the specific field type highlight
+ // colour or the general XFA field type colour if present.
+ if (IsFormFieldTypeXFA(fieldType)) {
+ if (!m_NeedsHighlight[static_cast<size_t>(fieldType)] &&
+ m_NeedsHighlight[static_cast<size_t>(FormFieldType::kXFA)]) {
+ return m_HighlightColor[static_cast<size_t>(FormFieldType::kXFA)];
+ }
+ }
+#endif // PDF_ENABLE_XFA
+ return m_HighlightColor[static_cast<size_t>(fieldType)];
}
diff --git a/fpdfsdk/cpdfsdk_interform.h b/fpdfsdk/cpdfsdk_interform.h
index 032399c..ee960ff 100644
--- a/fpdfsdk/cpdfsdk_interform.h
+++ b/fpdfsdk/cpdfsdk_interform.h
@@ -13,7 +13,7 @@
#include "core/fpdfdoc/cpdf_action.h"
#include "core/fpdfdoc/ipdf_formnotify.h"
-#include "core/fxcrt/fx_basic.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/fx_dib.h"
#include "fpdfsdk/cpdfsdk_widget.h"
@@ -35,13 +35,15 @@
~CPDFSDK_InterForm() override;
CPDF_InterForm* GetInterForm() const { return m_pInterForm.get(); }
- CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; }
+ CPDFSDK_FormFillEnvironment* GetFormFillEnv() const {
+ return m_pFormFillEnv.Get();
+ }
bool HighlightWidgets();
CPDFSDK_Widget* GetSibling(CPDFSDK_Widget* pWidget, bool bNext) const;
CPDFSDK_Widget* GetWidget(CPDF_FormControl* pControl) const;
- void GetWidgets(const CFX_WideString& sFieldName,
+ void GetWidgets(const WideString& sFieldName,
std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const;
void GetWidgets(CPDF_FormField* pField,
std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const;
@@ -63,14 +65,13 @@
void SynchronizeField(CPDF_FormField* pFormField, bool bSynchronizeElse);
#endif // PDF_ENABLE_XFA
- bool OnKeyStrokeCommit(CPDF_FormField* pFormField,
- const CFX_WideString& csValue);
- bool OnValidate(CPDF_FormField* pFormField, const CFX_WideString& csValue);
+ bool OnKeyStrokeCommit(CPDF_FormField* pFormField, const WideString& csValue);
+ bool OnValidate(CPDF_FormField* pFormField, const WideString& csValue);
void OnCalculate(CPDF_FormField* pFormField = nullptr);
- CFX_WideString OnFormat(CPDF_FormField* pFormField, bool& bFormatted);
+ WideString OnFormat(CPDF_FormField* pFormField, bool& bFormatted);
void ResetFieldAppearance(CPDF_FormField* pFormField,
- const CFX_WideString* sValue,
+ const WideString* sValue,
bool bValueChanged);
void UpdateField(CPDF_FormField* pFormField);
@@ -82,31 +83,31 @@
std::vector<CPDF_FormField*> GetFieldFromObjects(
const std::vector<CPDF_Object*>& objects) const;
bool IsValidField(CPDF_Dictionary* pFieldDict);
- bool SubmitFields(const CFX_WideString& csDestination,
+ bool SubmitFields(const WideString& csDestination,
const std::vector<CPDF_FormField*>& fields,
bool bIncludeOrExclude,
bool bUrlEncoded);
- bool SubmitForm(const CFX_WideString& sDestination, bool bUrlEncoded);
- bool ExportFormToFDFTextBuf(CFX_ByteTextBuf& textBuf);
- bool ExportFieldsToFDFTextBuf(const std::vector<CPDF_FormField*>& fields,
- bool bIncludeOrExclude,
- CFX_ByteTextBuf& textBuf);
- CFX_WideString GetTemporaryFileName(const CFX_WideString& sFileExt);
+ bool SubmitForm(const WideString& sDestination, bool bUrlEncoded);
+ ByteString ExportFormToFDFTextBuf();
+ ByteString ExportFieldsToFDFTextBuf(
+ const std::vector<CPDF_FormField*>& fields,
+ bool bIncludeOrExclude);
- bool IsNeedHighLight(int nFieldType);
- void RemoveAllHighLight();
- void SetHighlightAlpha(uint8_t alpha) { m_iHighlightAlpha = alpha; }
- uint8_t GetHighlightAlpha() { return m_iHighlightAlpha; }
- void SetHighlightColor(FX_COLORREF clr, int nFieldType);
- FX_COLORREF GetHighlightColor(int nFieldType);
+ bool IsNeedHighLight(FormFieldType fieldType);
+ void RemoveAllHighLights();
+ void SetHighlightAlpha(uint8_t alpha) { m_HighlightAlpha = alpha; }
+ uint8_t GetHighlightAlpha() { return m_HighlightAlpha; }
+ void SetHighlightColor(FX_COLORREF clr, FormFieldType fieldType);
+ void SetAllHighlightColors(FX_COLORREF clr);
+ FX_COLORREF GetHighlightColor(FormFieldType fieldType);
private:
// IPDF_FormNotify:
int BeforeValueChange(CPDF_FormField* pField,
- const CFX_WideString& csValue) override;
+ const WideString& csValue) override;
void AfterValueChange(CPDF_FormField* pField) override;
int BeforeSelectionChange(CPDF_FormField* pField,
- const CFX_WideString& csValue) override;
+ const WideString& csValue) override;
void AfterSelectionChange(CPDF_FormField* pField) override;
void AfterCheckedStatusChange(CPDF_FormField* pField) override;
int BeforeFormReset(CPDF_InterForm* pForm) override;
@@ -114,30 +115,26 @@
int BeforeFormImportData(CPDF_InterForm* pForm) override;
void AfterFormImportData(CPDF_InterForm* pForm) override;
- bool FDFToURLEncodedData(CFX_WideString csFDFFile, CFX_WideString csTxtFile);
- bool FDFToURLEncodedData(uint8_t*& pBuf, FX_STRSIZE& nBufSize);
+ bool FDFToURLEncodedData(uint8_t*& pBuf, size_t& nBufSize);
int GetPageIndexByAnnotDict(CPDF_Document* pDocument,
CPDF_Dictionary* pAnnotDict) const;
using CPDFSDK_WidgetMap = std::map<CPDF_FormControl*, CPDFSDK_Widget*>;
- CPDFSDK_FormFillEnvironment* m_pFormFillEnv; // Not owned.
+ UnownedPtr<CPDFSDK_FormFillEnvironment> m_pFormFillEnv;
std::unique_ptr<CPDF_InterForm> m_pInterForm;
CPDFSDK_WidgetMap m_Map;
#ifdef PDF_ENABLE_XFA
std::map<CXFA_FFWidget*, CPDFSDK_XFAWidget*> m_XFAMap;
bool m_bXfaCalculate;
bool m_bXfaValidationsEnabled;
- static const int kNumFieldTypes = 7;
-#else // PDF_ENABLE_XFA
- static const int kNumFieldTypes = 6;
#endif // PDF_ENABLE_XFA
bool m_bCalculate;
bool m_bBusy;
- FX_COLORREF m_aHighlightColor[kNumFieldTypes];
- uint8_t m_iHighlightAlpha;
- bool m_bNeedHightlight[kNumFieldTypes];
+ uint8_t m_HighlightAlpha;
+ FX_COLORREF m_HighlightColor[kFormFieldTypeCount];
+ bool m_NeedsHighlight[kFormFieldTypeCount];
};
#endif // FPDFSDK_CPDFSDK_INTERFORM_H_
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index c67948d..c1b5221 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -13,8 +13,8 @@
#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fpdfdoc/cpdf_annotlist.h"
#include "core/fpdfdoc/cpdf_interform.h"
+#include "core/fxcrt/autorestorer.h"
#include "fpdfsdk/cpdfsdk_annot.h"
-#include "fpdfsdk/cpdfsdk_annothandlermgr.h"
#include "fpdfsdk/cpdfsdk_annotiteration.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_interform.h"
@@ -22,11 +22,11 @@
#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffpageview.h"
-#include "xfa/fxfa/xfa_ffwidgethandler.h"
-#include "xfa/fxfa/xfa_rendercontext.h"
-#include "xfa/fxgraphics/cfx_graphics.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffpageview.h"
+#include "xfa/fxfa/cxfa_ffwidgethandler.h"
+#include "xfa/fxfa/cxfa_rendercontext.h"
+#include "xfa/fxgraphics/cxfa_graphics.h"
#endif // PDF_ENABLE_XFA
CPDFSDK_PageView::CPDFSDK_PageView(CPDFSDK_FormFillEnvironment* pFormFillEnv,
@@ -36,23 +36,17 @@
#ifndef PDF_ENABLE_XFA
m_bOwnsPage(false),
#endif // PDF_ENABLE_XFA
- m_bEnterWidget(false),
- m_bExitWidget(false),
m_bOnWidget(false),
m_bValid(false),
m_bLocked(false),
m_bBeingDestroyed(false) {
CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
- if (pInterForm) {
- CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
+ CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
#ifdef PDF_ENABLE_XFA
- if (page->GetPDFPage())
- pPDFInterForm->FixPageFields(page->GetPDFPage());
+ if (page->GetPDFPage())
+ pPDFInterForm->FixPageFields(page->GetPDFPage());
#else // PDF_ENABLE_XFA
- pPDFInterForm->FixPageFields(page);
-#endif // PDF_ENABLE_XFA
- }
-#ifndef PDF_ENABLE_XFA
+ pPDFInterForm->FixPageFields(page);
m_page->SetView(this);
#endif // PDF_ENABLE_XFA
}
@@ -94,20 +88,18 @@
if (!pPage)
return;
- if (pPage->GetContext()->GetDocType() == DOCTYPE_DYNAMIC_XFA) {
- CFX_Graphics gs(pDevice);
- CFX_RectF rectClip(static_cast<FX_FLOAT>(pClip.left),
- static_cast<FX_FLOAT>(pClip.top),
- static_cast<FX_FLOAT>(pClip.Width()),
- static_cast<FX_FLOAT>(pClip.Height()));
+ if (pPage->GetContext()->GetFormType() == FormType::kXFAFull) {
+ CFX_RectF rectClip(
+ static_cast<float>(pClip.left), static_cast<float>(pClip.top),
+ static_cast<float>(pClip.Width()), static_cast<float>(pClip.Height()));
+
+ CXFA_Graphics gs(pDevice);
gs.SetClipRect(rectClip);
- std::unique_ptr<CXFA_RenderContext> pRenderContext(new CXFA_RenderContext);
- CXFA_RenderOptions renderOptions;
- renderOptions.m_bHighlight = true;
+
CXFA_FFPageView* xfaView = pPage->GetXFAPageView();
- pRenderContext->StartRender(xfaView, &gs, *pUser2Device, renderOptions);
- pRenderContext->DoRender();
- pRenderContext->StopRender();
+ CXFA_RenderContext renderContext(xfaView, rectClip, *pUser2Device);
+ renderContext.DoRender(&gs);
+
CXFA_FFDocView* docView = xfaView->GetDocView();
if (!docView)
return;
@@ -116,7 +108,7 @@
return;
// Render the focus widget
docView->GetWidgetHandler()->RenderWidget(annot->GetXFAWidget(), &gs,
- pUser2Device, false);
+ *pUser2Device, false);
return;
}
#endif // PDF_ENABLE_XFA
@@ -125,7 +117,8 @@
CPDFSDK_AnnotIteration annotIteration(this, true);
for (const auto& pSDKAnnot : annotIteration) {
m_pFormFillEnv->GetAnnotHandlerMgr()->Annot_OnDraw(
- this, pSDKAnnot.Get(), pDevice, pUser2Device, pOptions->m_bDrawAnnots);
+ this, pSDKAnnot.Get(), pDevice, pUser2Device,
+ pOptions->GetDrawAnnots());
}
}
@@ -181,16 +174,21 @@
bool CPDFSDK_PageView::DeleteAnnot(CPDFSDK_Annot* pAnnot) {
if (!pAnnot)
return false;
+
CPDFXFA_Page* pPage = pAnnot->GetPDFXFAPage();
- if (!pPage || (pPage->GetContext()->GetDocType() != DOCTYPE_STATIC_XFA &&
- pPage->GetContext()->GetDocType() != DOCTYPE_DYNAMIC_XFA))
+ if (!pPage || !pPage->GetContext()->ContainsXFAForm())
return false;
+ CPDFSDK_Annot::ObservedPtr pObserved(pAnnot);
if (GetFocusAnnot() == pAnnot)
- m_pFormFillEnv->KillFocusAnnot(0);
- CPDFSDK_AnnotHandlerMgr* pAnnotHandler = m_pFormFillEnv->GetAnnotHandlerMgr();
- if (pAnnotHandler)
- pAnnotHandler->ReleaseAnnot(pAnnot);
+ m_pFormFillEnv->KillFocusAnnot(0); // May invoke JS, invalidating pAnnot.
+
+ if (pObserved) {
+ CPDFSDK_AnnotHandlerMgr* pAnnotHandler =
+ m_pFormFillEnv->GetAnnotHandlerMgr();
+ if (pAnnotHandler)
+ pAnnotHandler->ReleaseAnnot(pObserved.Get());
+ }
auto it = std::find(m_SDKAnnotArray.begin(), m_SDKAnnotArray.end(), pAnnot);
if (it != m_SDKAnnotArray.end())
@@ -207,7 +205,7 @@
#ifdef PDF_ENABLE_XFA
return m_page->GetContext()->GetPDFDoc();
#else // PDF_ENABLE_XFA
- return m_page->m_pDocument;
+ return m_page->m_pDocument.Get();
#endif // PDF_ENABLE_XFA
}
return nullptr;
@@ -242,6 +240,35 @@
}
#endif // PDF_ENABLE_XFA
+WideString CPDFSDK_PageView::GetSelectedText() {
+ if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) {
+ CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
+ m_pFormFillEnv->GetAnnotHandlerMgr();
+ return pAnnotHandlerMgr->Annot_GetSelectedText(pAnnot);
+ }
+
+ return WideString();
+}
+
+void CPDFSDK_PageView::ReplaceSelection(const WideString& text) {
+ if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) {
+ CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
+ m_pFormFillEnv->GetAnnotHandlerMgr();
+ pAnnotHandlerMgr->Annot_ReplaceSelection(pAnnot, text);
+ }
+}
+
+bool CPDFSDK_PageView::OnFocus(const CFX_PointF& point, uint32_t nFlag) {
+ CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point));
+ if (!pAnnot) {
+ m_pFormFillEnv->KillFocusAnnot(nFlag);
+ return false;
+ }
+
+ m_pFormFillEnv->SetFocusAnnot(&pAnnot);
+ return true;
+}
+
bool CPDFSDK_PageView::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point));
if (!pAnnot) {
@@ -311,34 +338,48 @@
CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
m_pFormFillEnv->GetAnnotHandlerMgr();
CPDFSDK_Annot::ObservedPtr pFXAnnot(GetFXAnnotAtPoint(point));
+
+ if (m_bOnWidget && m_pCaptureWidget != pFXAnnot)
+ ExitWidget(pAnnotHandlerMgr, true, nFlag);
+
if (pFXAnnot) {
- if (m_pCaptureWidget && m_pCaptureWidget != pFXAnnot) {
- m_bExitWidget = true;
- m_bEnterWidget = false;
- pAnnotHandlerMgr->Annot_OnMouseExit(this, &m_pCaptureWidget, nFlag);
+ if (!m_bOnWidget) {
+ EnterWidget(pAnnotHandlerMgr, &pFXAnnot, nFlag);
+
+ // Annot_OnMouseEnter may have invalidated pFXAnnot.
+ if (!pFXAnnot) {
+ ExitWidget(pAnnotHandlerMgr, false, nFlag);
+ return true;
+ }
}
- m_pCaptureWidget.Reset(pFXAnnot.Get());
- m_bOnWidget = true;
- if (!m_bEnterWidget) {
- m_bEnterWidget = true;
- m_bExitWidget = false;
- pAnnotHandlerMgr->Annot_OnMouseEnter(this, &pFXAnnot, nFlag);
- }
+
pAnnotHandlerMgr->Annot_OnMouseMove(this, &pFXAnnot, nFlag, point);
return true;
}
- if (m_bOnWidget) {
- m_bOnWidget = false;
- m_bExitWidget = true;
- m_bEnterWidget = false;
- if (m_pCaptureWidget) {
- pAnnotHandlerMgr->Annot_OnMouseExit(this, &m_pCaptureWidget, nFlag);
- m_pCaptureWidget.Reset();
- }
- }
+
return false;
}
+void CPDFSDK_PageView::EnterWidget(CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr,
+ CPDFSDK_Annot::ObservedPtr* pAnnot,
+ uint32_t nFlag) {
+ m_bOnWidget = true;
+ m_pCaptureWidget.Reset(pAnnot->Get());
+ pAnnotHandlerMgr->Annot_OnMouseEnter(this, pAnnot, nFlag);
+}
+
+void CPDFSDK_PageView::ExitWidget(CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr,
+ bool callExitCallback,
+ uint32_t nFlag) {
+ m_bOnWidget = false;
+ if (m_pCaptureWidget) {
+ if (callExitCallback)
+ pAnnotHandlerMgr->Annot_OnMouseExit(this, &m_pCaptureWidget, nFlag);
+
+ m_pCaptureWidget.Reset();
+ }
+}
+
bool CPDFSDK_PageView::OnMouseWheel(double deltaX,
double deltaY,
const CFX_PointF& point,
@@ -349,8 +390,8 @@
CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
m_pFormFillEnv->GetAnnotHandlerMgr();
- return pAnnotHandlerMgr->Annot_OnMouseWheel(this, &pAnnot, nFlag, (int)deltaY,
- point);
+ return pAnnotHandlerMgr->Annot_OnMouseWheel(this, &pAnnot, nFlag,
+ static_cast<int>(deltaY), point);
}
bool CPDFSDK_PageView::OnChar(int nChar, uint32_t nFlag) {
@@ -380,22 +421,22 @@
CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
m_pFormFillEnv->GetAnnotHandlerMgr();
- SetLock(true);
+ AutoRestorer<bool> lock(&m_bLocked);
+ m_bLocked = true;
#ifdef PDF_ENABLE_XFA
- CFX_RetainPtr<CPDFXFA_Page> protector(m_page);
- if (m_pFormFillEnv->GetXFAContext()->GetDocType() == DOCTYPE_DYNAMIC_XFA) {
+ RetainPtr<CPDFXFA_Page> protector(m_page);
+ if (m_pFormFillEnv->GetXFAContext()->GetFormType() == FormType::kXFAFull) {
CXFA_FFPageView* pageView = m_page->GetXFAPageView();
- std::unique_ptr<IXFA_WidgetIterator> pWidgetHander(
+ std::unique_ptr<IXFA_WidgetIterator> pWidgetHandler(
pageView->CreateWidgetIterator(
XFA_TRAVERSEWAY_Form,
XFA_WidgetStatus_Visible | XFA_WidgetStatus_Viewable));
- if (!pWidgetHander) {
- SetLock(false);
+ if (!pWidgetHandler) {
return;
}
- while (CXFA_FFWidget* pXFAAnnot = pWidgetHander->MoveToNext()) {
+ while (CXFA_FFWidget* pXFAAnnot = pWidgetHandler->MoveToNext()) {
CPDFSDK_Annot* pAnnot = pAnnotHandlerMgr->NewAnnot(pXFAAnnot, this);
if (!pAnnot)
continue;
@@ -403,7 +444,6 @@
pAnnotHandlerMgr->Annot_OnLoad(pAnnot);
}
- SetLock(false);
return;
}
#endif // PDF_ENABLE_XFA
@@ -426,18 +466,16 @@
m_SDKAnnotArray.push_back(pAnnot);
pAnnotHandlerMgr->Annot_OnLoad(pAnnot);
}
-
- SetLock(false);
}
void CPDFSDK_PageView::UpdateRects(const std::vector<CFX_FloatRect>& rects) {
for (const auto& rc : rects)
- m_pFormFillEnv->Invalidate(m_page, rc.ToFxRect());
+ m_pFormFillEnv->Invalidate(m_page, rc.GetOuterRect());
}
void CPDFSDK_PageView::UpdateView(CPDFSDK_Annot* pAnnot) {
CFX_FloatRect rcWindow = pAnnot->GetRect();
- m_pFormFillEnv->Invalidate(m_page, rcWindow.ToFxRect());
+ m_pFormFillEnv->Invalidate(m_page, rcWindow.GetOuterRect());
}
int CPDFSDK_PageView::GetPageIndex() const {
@@ -445,21 +483,18 @@
return -1;
#ifdef PDF_ENABLE_XFA
- int nDocType = m_page->GetContext()->GetDocType();
- switch (nDocType) {
- case DOCTYPE_DYNAMIC_XFA: {
+ switch (m_page->GetContext()->GetFormType()) {
+ case FormType::kXFAFull: {
CXFA_FFPageView* pPageView = m_page->GetXFAPageView();
return pPageView ? pPageView->GetPageIndex() : -1;
}
- case DOCTYPE_STATIC_XFA:
- case DOCTYPE_PDF:
- return GetPageIndexForStaticPDF();
- default:
- return -1;
+ case FormType::kNone:
+ case FormType::kAcroForm:
+ case FormType::kXFAForeground:
+ break;
}
-#else // PDF_ENABLE_XFA
- return GetPageIndexForStaticPDF();
#endif // PDF_ENABLE_XFA
+ return GetPageIndexForStaticPDF();
}
bool CPDFSDK_PageView::IsValidAnnot(const CPDF_Annot* p) const {
@@ -486,7 +521,7 @@
}
int CPDFSDK_PageView::GetPageIndexForStaticPDF() const {
- CPDF_Dictionary* pDict = GetPDFPage()->m_pFormDict;
+ CPDF_Dictionary* pDict = GetPDFPage()->m_pFormDict.Get();
CPDF_Document* pDoc = m_pFormFillEnv->GetPDFDocument();
return (pDoc && pDict) ? pDoc->GetPageIndex(pDict->GetObjNum()) : -1;
}
diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h
index bcd5177..03f3ab6 100644
--- a/fpdfsdk/cpdfsdk_pageview.h
+++ b/fpdfsdk/cpdfsdk_pageview.h
@@ -12,7 +12,9 @@
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/cpdfsdk_annot.h"
+#include "fpdfsdk/cpdfsdk_annothandlermgr.h"
class CFX_RenderDevice;
class CPDF_AnnotList;
@@ -55,7 +57,14 @@
CPDF_Page* GetPDFPage() const;
CPDF_Document* GetPDFDocument();
- CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; }
+ CPDFSDK_FormFillEnvironment* GetFormFillEnv() const {
+ return m_pFormFillEnv.Get();
+ }
+
+ WideString GetSelectedText();
+ void ReplaceSelection(const WideString& text);
+
+ bool OnFocus(const CFX_PointF& point, uint32_t nFlag);
bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag);
bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag);
#ifdef PDF_ENABLE_XFA
@@ -81,7 +90,6 @@
void SetValid(bool bValid) { m_bValid = bValid; }
bool IsValid() { return m_bValid; }
- void SetLock(bool bLocked) { m_bLocked = bLocked; }
bool IsLocked() { return m_bLocked; }
void SetBeingDestroyed() { m_bBeingDestroyed = true; }
@@ -98,17 +106,22 @@
int GetPageIndexForStaticPDF() const;
+ void EnterWidget(CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr,
+ CPDFSDK_Annot::ObservedPtr* pAnnot,
+ uint32_t nFlag);
+ void ExitWidget(CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr,
+ bool callExitCallback,
+ uint32_t nFlag);
+
CFX_Matrix m_curMatrix;
UnderlyingPageType* const m_page;
std::unique_ptr<CPDF_AnnotList> m_pAnnotList;
std::vector<CPDFSDK_Annot*> m_SDKAnnotArray;
- CPDFSDK_FormFillEnvironment* const m_pFormFillEnv; // Not owned.
+ UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
CPDFSDK_Annot::ObservedPtr m_pCaptureWidget;
#ifndef PDF_ENABLE_XFA
bool m_bOwnsPage;
#endif // PDF_ENABLE_XFA
- bool m_bEnterWidget;
- bool m_bExitWidget;
bool m_bOnWidget;
bool m_bValid;
bool m_bLocked;
diff --git a/fpdfsdk/cpdfsdk_widget.cpp b/fpdfsdk/cpdfsdk_widget.cpp
index cd86f7a..2adc46f 100644
--- a/fpdfsdk/cpdfsdk_widget.cpp
+++ b/fpdfsdk/cpdfsdk_widget.cpp
@@ -7,6 +7,7 @@
#include "fpdfsdk/cpdfsdk_widget.h"
#include <memory>
+#include <sstream>
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
@@ -28,17 +29,17 @@
#include "fpdfsdk/formfiller/cba_fontmap.h"
#include "fpdfsdk/fsdk_actionhandler.h"
#include "fpdfsdk/fsdk_define.h"
-#include "fpdfsdk/fxedit/fxet_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_Edit.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
+#include "fpdfsdk/pwl/cpwl_appstream.h"
+#include "fpdfsdk/pwl/cpwl_edit.h"
#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "xfa/fxfa/cxfa_eventparam.h"
-#include "xfa/fxfa/fxfa_widget.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffwidget.h"
-#include "xfa/fxfa/xfa_ffwidgethandler.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
+#include "xfa/fxfa/cxfa_ffwidgethandler.h"
+#include "xfa/fxfa/cxfa_widgetacc.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
#endif // PDF_ENABLE_XFA
namespace {
@@ -57,7 +58,7 @@
CPDFSDK_InterForm* pInterForm)
: CPDFSDK_BAAnnot(pAnnot, pPageView),
m_pInterForm(pInterForm),
- m_nAppAge(0),
+ m_nAppearanceAge(0),
m_nValueAge(0)
#ifdef PDF_ENABLE_XFA
,
@@ -72,11 +73,11 @@
#ifdef PDF_ENABLE_XFA
CXFA_FFWidget* CPDFSDK_Widget::GetMixXFAWidget() const {
CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
- if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) {
+ if (pContext->GetFormType() == FormType::kXFAForeground) {
if (!m_hMixXFAWidget) {
if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) {
- CFX_WideString sName;
- if (GetFieldType() == FIELDTYPE_RADIOBUTTON) {
+ WideString sName;
+ if (GetFieldType() == FormFieldType::kRadioButton) {
sName = GetAnnotName();
if (sName.IsEmpty())
sName = GetName();
@@ -88,36 +89,35 @@
m_hMixXFAWidget = pDocView->GetWidgetByName(sName, nullptr);
}
}
- return m_hMixXFAWidget;
+ return m_hMixXFAWidget.Get();
}
-
return nullptr;
}
CXFA_FFWidget* CPDFSDK_Widget::GetGroupMixXFAWidget() {
CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
- if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) {
- if (CXFA_FFDocView* pDocView = pContext->GetXFADocView()) {
- CFX_WideString sName = GetName();
- if (!sName.IsEmpty())
- return pDocView->GetWidgetByName(sName, nullptr);
- }
- }
+ if (pContext->GetFormType() != FormType::kXFAForeground)
+ return nullptr;
- return nullptr;
+ CXFA_FFDocView* pDocView = pContext->GetXFADocView();
+ if (!pDocView)
+ return nullptr;
+
+ WideString sName = GetName();
+ return !sName.IsEmpty() ? pDocView->GetWidgetByName(sName, nullptr) : nullptr;
}
CXFA_FFWidgetHandler* CPDFSDK_Widget::GetXFAWidgetHandler() const {
CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
- if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) {
- if (!m_pWidgetHandler) {
- if (CXFA_FFDocView* pDocView = pContext->GetXFADocView())
- m_pWidgetHandler = pDocView->GetWidgetHandler();
- }
- return m_pWidgetHandler;
- }
+ if (pContext->GetFormType() != FormType::kXFAForeground)
+ return nullptr;
- return nullptr;
+ if (!m_pWidgetHandler) {
+ CXFA_FFDocView* pDocView = pContext->GetXFADocView();
+ if (pDocView)
+ m_pWidgetHandler = pDocView->GetWidgetHandler();
+ }
+ return m_pWidgetHandler.Get();
}
static XFA_EVENTTYPE GetXFAEventType(PDFSDK_XFAAActionType eXFAAAT) {
@@ -165,11 +165,8 @@
eEventType = XFA_EVENT_Exit;
break;
case CPDF_AAction::PageOpen:
- break;
case CPDF_AAction::PageClose:
- break;
case CPDF_AAction::PageVisible:
- break;
case CPDF_AAction::PageInvisible:
break;
case CPDF_AAction::KeyStroke:
@@ -189,6 +186,9 @@
case CPDF_AAction::PrintDocument:
case CPDF_AAction::DocumentPrinted:
break;
+ case CPDF_AAction::NumberOfActions:
+ NOTREACHED();
+ break;
}
return eEventType;
@@ -205,18 +205,18 @@
XFA_EVENTTYPE eEventType = GetXFAEventType(eXFAAAT);
- CXFA_WidgetAcc* pAcc;
if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
- GetFieldType() == FIELDTYPE_RADIOBUTTON) {
+ GetFieldType() == FormFieldType::kRadioButton) {
if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
- pAcc = hGroupWidget->GetDataAcc();
- if (pXFAWidgetHandler->HasEvent(pAcc, eEventType))
+ if (pXFAWidgetHandler->HasEvent(hGroupWidget->GetNode()->GetWidgetAcc(),
+ eEventType)) {
return true;
+ }
}
}
- pAcc = hWidget->GetDataAcc();
- return pXFAWidgetHandler->HasEvent(pAcc, eEventType);
+ return pXFAWidgetHandler->HasEvent(hWidget->GetNode()->GetWidgetAcc(),
+ eEventType);
}
bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
@@ -250,14 +250,14 @@
if (data.nSelEnd > data.nSelStart)
param.m_wsNewText.Delete(data.nSelStart, data.nSelEnd - data.nSelStart);
- for (int i = 0; i < data.sChange.GetLength(); i++)
- param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
- param.m_wsPrevText = data.sValue;
+ for (const auto& c : data.sChange)
+ param.m_wsNewText.Insert(data.nSelStart, c);
+ param.m_wsPrevText = data.sValue;
if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
- GetFieldType() == FIELDTYPE_RADIOBUTTON) {
+ GetFieldType() == FormFieldType::kRadioButton) {
if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
- CXFA_WidgetAcc* pAcc = hGroupWidget->GetDataAcc();
+ CXFA_WidgetAcc* pAcc = hGroupWidget->GetNode()->GetWidgetAcc();
param.m_pTarget = pAcc;
if (pXFAWidgetHandler->ProcessEvent(pAcc, ¶m) !=
XFA_EVENTERROR_Success) {
@@ -265,7 +265,7 @@
}
}
}
- CXFA_WidgetAcc* pAcc = hWidget->GetDataAcc();
+ CXFA_WidgetAcc* pAcc = hWidget->GetNode()->GetWidgetAcc();
param.m_pTarget = pAcc;
int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m);
@@ -280,48 +280,52 @@
if (!hWidget)
return;
- CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc();
+ CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc();
if (!pWidgetAcc)
return;
CPDF_FormField* pFormField = GetFormField();
switch (GetFieldType()) {
- case FIELDTYPE_CHECKBOX:
- case FIELDTYPE_RADIOBUTTON: {
+ case FormFieldType::kCheckBox:
+ case FormFieldType::kRadioButton: {
CPDF_FormControl* pFormCtrl = GetFormControl();
XFA_CHECKSTATE eCheckState =
pFormCtrl->IsChecked() ? XFA_CHECKSTATE_On : XFA_CHECKSTATE_Off;
pWidgetAcc->SetCheckState(eCheckState, true);
break;
}
- case FIELDTYPE_TEXTFIELD:
- pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit);
+ case FormFieldType::kTextField:
+ pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
break;
- case FIELDTYPE_LISTBOX: {
+ case FormFieldType::kListBox: {
pWidgetAcc->ClearAllSelections();
for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
int nIndex = pFormField->GetSelectedIndex(i);
- if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems())
+ if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
pWidgetAcc->SetItemState(nIndex, true, false, false, true);
}
break;
}
- case FIELDTYPE_COMBOBOX: {
+ case FormFieldType::kComboBox: {
pWidgetAcc->ClearAllSelections();
for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
int nIndex = pFormField->GetSelectedIndex(i);
- if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems())
+ if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
pWidgetAcc->SetItemState(nIndex, true, false, false, true);
}
- pWidgetAcc->SetValue(pFormField->GetValue(), XFA_VALUEPICTURE_Edit);
+ pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pFormField->GetValue());
break;
}
+ default:
+ break;
}
- if (bSynchronizeElse)
- pWidgetAcc->ProcessValueChanged();
+ if (bSynchronizeElse) {
+ CPDFXFA_Context* context = m_pPageView->GetFormFillEnv()->GetXFAContext();
+ context->GetXFADocView()->ProcessValueChanged(pWidgetAcc);
+ }
}
void CPDFSDK_Widget::SynchronizeXFAValue() {
@@ -358,36 +362,35 @@
ASSERT(pFormControl);
switch (pFormField->GetFieldType()) {
- case FIELDTYPE_CHECKBOX: {
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
+ case FormFieldType::kCheckBox: {
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
pFormField->CheckControl(
pFormField->GetControlIndex(pFormControl),
pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true);
}
break;
}
- case FIELDTYPE_RADIOBUTTON: {
+ case FormFieldType::kRadioButton: {
// TODO(weili): Check whether we need to handle checkbox and radio
// button differently, otherwise, merge these two cases.
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
pFormField->CheckControl(
pFormField->GetControlIndex(pFormControl),
pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On, true);
}
break;
}
- case FIELDTYPE_TEXTFIELD: {
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
- CFX_WideString sValue;
- pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display);
- pFormField->SetValue(sValue, true);
+ case FormFieldType::kTextField: {
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
+ pFormField->SetValue(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display),
+ true);
}
break;
}
- case FIELDTYPE_LISTBOX: {
+ case FormFieldType::kListBox: {
pFormField->ClearSelection(false);
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
int nIndex = pWidgetAcc->GetSelectedItem(i);
@@ -398,10 +401,10 @@
}
break;
}
- case FIELDTYPE_COMBOBOX: {
+ case FormFieldType::kComboBox: {
pFormField->ClearSelection(false);
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
for (int i = 0, sz = pWidgetAcc->CountSelectedItems(); i < sz; i++) {
int nIndex = pWidgetAcc->GetSelectedItem(i);
@@ -409,13 +412,13 @@
pFormField->SetItemSelection(nIndex, true, true);
}
}
-
- CFX_WideString sValue;
- pWidgetAcc->GetValue(sValue, XFA_VALUEPICTURE_Display);
- pFormField->SetValue(sValue, true);
+ pFormField->SetValue(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display),
+ true);
}
break;
}
+ default:
+ break;
}
}
@@ -426,36 +429,36 @@
ASSERT(hWidget);
switch (pFormField->GetFieldType()) {
- case FIELDTYPE_LISTBOX: {
+ case FormFieldType::kListBox: {
pFormField->ClearSelection(false);
pFormField->ClearOptions(true);
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
- for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz; i++) {
- CFX_WideString swText;
- pWidgetAcc->GetChoiceListItem(swText, i);
-
- pFormField->InsertOption(swText, i, true);
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
+ for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz;
+ i++) {
+ pFormField->InsertOption(
+ pWidgetAcc->GetChoiceListItem(i, false).value_or(L""), i, true);
}
}
break;
}
- case FIELDTYPE_COMBOBOX: {
+ case FormFieldType::kComboBox: {
pFormField->ClearSelection(false);
pFormField->ClearOptions(false);
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
- for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(); i < sz; i++) {
- CFX_WideString swText;
- pWidgetAcc->GetChoiceListItem(swText, i);
-
- pFormField->InsertOption(swText, i, false);
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
+ for (int i = 0, sz = pWidgetAcc->CountChoiceListItems(false); i < sz;
+ i++) {
+ pFormField->InsertOption(
+ pWidgetAcc->GetChoiceListItem(i, false).value_or(L""), i, false);
}
}
pFormField->SetValue(L"", true);
break;
}
+ default:
+ break;
}
}
#endif // PDF_ENABLE_XFA
@@ -466,7 +469,7 @@
return false;
// Choose the right sub-ap
- const FX_CHAR* ap_entry = "N";
+ const char* ap_entry = "N";
if (mode == CPDF_Annot::Down)
ap_entry = "D";
else if (mode == CPDF_Annot::Rollover)
@@ -479,34 +482,35 @@
if (!psub)
return false;
- int nFieldType = GetFieldType();
- switch (nFieldType) {
- case FIELDTYPE_PUSHBUTTON:
- case FIELDTYPE_COMBOBOX:
- case FIELDTYPE_LISTBOX:
- case FIELDTYPE_TEXTFIELD:
- case FIELDTYPE_SIGNATURE:
+ FormFieldType fieldType = GetFieldType();
+ switch (fieldType) {
+ case FormFieldType::kPushButton:
+ case FormFieldType::kComboBox:
+ case FormFieldType::kListBox:
+ case FormFieldType::kTextField:
+ case FormFieldType::kSignature:
return psub->IsStream();
- case FIELDTYPE_CHECKBOX:
- case FIELDTYPE_RADIOBUTTON:
+ case FormFieldType::kCheckBox:
+ case FormFieldType::kRadioButton:
if (CPDF_Dictionary* pSubDict = psub->AsDictionary()) {
return !!pSubDict->GetStreamFor(GetAppState());
}
return false;
+ default:
+ return true;
}
- return true;
}
-int CPDFSDK_Widget::GetFieldType() const {
+FormFieldType CPDFSDK_Widget::GetFieldType() const {
CPDF_FormField* pField = GetFormField();
- return pField ? pField->GetFieldType() : FIELDTYPE_UNKNOWN;
+ return pField ? pField->GetFieldType() : FormFieldType::kUnknown;
}
bool CPDFSDK_Widget::IsAppearanceValid() {
#ifdef PDF_ENABLE_XFA
CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
- int nDocType = pContext->GetDocType();
- if (nDocType != DOCTYPE_PDF && nDocType != DOCTYPE_STATIC_XFA)
+ FormType formType = pContext->GetFormType();
+ if (formType == FormType::kXFAFull)
return true;
#endif // PDF_ENABLE_XFA
return CPDFSDK_BAAnnot::IsAppearanceValid();
@@ -525,7 +529,7 @@
}
bool CPDFSDK_Widget::IsSignatureWidget() const {
- return GetFieldType() == FIELDTYPE_SIGNATURE;
+ return GetFieldType() == FormFieldType::kSignature;
}
CPDF_FormField* CPDFSDK_Widget::GetFormField() const {
@@ -551,7 +555,7 @@
}
#ifdef PDF_ENABLE_XFA
-CFX_WideString CPDFSDK_Widget::GetName() const {
+WideString CPDFSDK_Widget::GetName() const {
CPDF_FormField* pFormField = GetFormField();
return pFormField->GetFullName();
}
@@ -561,14 +565,14 @@
CPDF_FormControl* pFormCtrl = GetFormControl();
int iColorType = 0;
color = ARGBToColorRef(pFormCtrl->GetBackgroundColor(iColorType));
- return iColorType != COLORTYPE_TRANSPARENT;
+ return iColorType != CFX_Color::kTransparent;
}
bool CPDFSDK_Widget::GetBorderColor(FX_COLORREF& color) const {
CPDF_FormControl* pFormCtrl = GetFormControl();
int iColorType = 0;
color = ARGBToColorRef(pFormCtrl->GetBorderColor(iColorType));
- return iColorType != COLORTYPE_TRANSPARENT;
+ return iColorType != CFX_Color::kTransparent;
}
bool CPDFSDK_Widget::GetTextColor(FX_COLORREF& color) const {
@@ -578,26 +582,24 @@
return false;
FX_ARGB argb;
- int iColorType = COLORTYPE_TRANSPARENT;
+ int iColorType = CFX_Color::kTransparent;
da.GetColor(argb, iColorType);
color = ARGBToColorRef(argb);
- return iColorType != COLORTYPE_TRANSPARENT;
+ return iColorType != CFX_Color::kTransparent;
}
-FX_FLOAT CPDFSDK_Widget::GetFontSize() const {
+float CPDFSDK_Widget::GetFontSize() const {
CPDF_FormControl* pFormCtrl = GetFormControl();
CPDF_DefaultAppearance pDa = pFormCtrl->GetDefaultAppearance();
- CFX_ByteString csFont = "";
- FX_FLOAT fFontSize = 0.0f;
- pDa.GetFont(csFont, fFontSize);
-
+ float fFontSize;
+ pDa.GetFont(&fFontSize);
return fFontSize;
}
int CPDFSDK_Widget::GetSelectedIndex(int nIndex) const {
#ifdef PDF_ENABLE_XFA
if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
if (nIndex < pWidgetAcc->CountSelectedItems())
return pWidgetAcc->GetSelectedItem(nIndex);
}
@@ -608,28 +610,26 @@
}
#ifdef PDF_ENABLE_XFA
-CFX_WideString CPDFSDK_Widget::GetValue(bool bDisplay) const {
+WideString CPDFSDK_Widget::GetValue(bool bDisplay) const {
if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
- CFX_WideString sValue;
- pWidgetAcc->GetValue(
- sValue, bDisplay ? XFA_VALUEPICTURE_Display : XFA_VALUEPICTURE_Edit);
- return sValue;
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
+ return pWidgetAcc->GetValue(bDisplay ? XFA_VALUEPICTURE_Display
+ : XFA_VALUEPICTURE_Edit);
}
}
#else
-CFX_WideString CPDFSDK_Widget::GetValue() const {
+WideString CPDFSDK_Widget::GetValue() const {
#endif // PDF_ENABLE_XFA
CPDF_FormField* pFormField = GetFormField();
return pFormField->GetValue();
}
-CFX_WideString CPDFSDK_Widget::GetDefaultValue() const {
+WideString CPDFSDK_Widget::GetDefaultValue() const {
CPDF_FormField* pFormField = GetFormField();
return pFormField->GetDefaultValue();
}
-CFX_WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
+WideString CPDFSDK_Widget::GetOptionLabel(int nIndex) const {
CPDF_FormField* pFormField = GetFormField();
return pFormField->GetOptionLabel(nIndex);
}
@@ -642,8 +642,8 @@
bool CPDFSDK_Widget::IsOptionSelected(int nIndex) const {
#ifdef PDF_ENABLE_XFA
if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc()) {
- if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems())
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc()) {
+ if (nIndex > -1 && nIndex < pWidgetAcc->CountChoiceListItems(false))
return pWidgetAcc->GetItemState(nIndex);
return false;
@@ -662,7 +662,7 @@
bool CPDFSDK_Widget::IsChecked() const {
#ifdef PDF_ENABLE_XFA
if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
- if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc())
+ if (CXFA_WidgetAcc* pWidgetAcc = hWidget->GetNode()->GetWidgetAcc())
return pWidgetAcc->GetCheckState() == XFA_CHECKSTATE_On;
}
#endif // PDF_ENABLE_XFA
@@ -693,7 +693,7 @@
#endif // PDF_ENABLE_XFA
}
-void CPDFSDK_Widget::SetValue(const CFX_WideString& sValue, bool bNotify) {
+void CPDFSDK_Widget::SetValue(const WideString& sValue, bool bNotify) {
CPDF_FormField* pFormField = GetFormField();
pFormField->SetValue(sValue, bNotify);
#ifdef PDF_ENABLE_XFA
@@ -702,7 +702,7 @@
#endif // PDF_ENABLE_XFA
}
-void CPDFSDK_Widget::SetDefaultValue(const CFX_WideString& sValue) {}
+void CPDFSDK_Widget::SetDefaultValue(const WideString& sValue) {}
void CPDFSDK_Widget::SetOptionSelection(int index,
bool bSelected,
bool bNotify) {
@@ -740,10 +740,10 @@
#ifdef PDF_ENABLE_XFA
void CPDFSDK_Widget::ResetAppearance(bool bValueChanged) {
switch (GetFieldType()) {
- case FIELDTYPE_TEXTFIELD:
- case FIELDTYPE_COMBOBOX: {
+ case FormFieldType::kTextField:
+ case FormFieldType::kComboBox: {
bool bFormatted = false;
- CFX_WideString sValue = OnFormat(bFormatted);
+ WideString sValue = OnFormat(bFormatted);
ResetAppearance(bFormatted ? &sValue : nullptr, true);
break;
}
@@ -754,43 +754,42 @@
}
#endif // PDF_ENABLE_XFA
-void CPDFSDK_Widget::ResetAppearance(const CFX_WideString* sValue,
+void CPDFSDK_Widget::ResetAppearance(const WideString* sValue,
bool bValueChanged) {
SetAppModified();
- m_nAppAge++;
- if (m_nAppAge > 999999)
- m_nAppAge = 0;
+ m_nAppearanceAge++;
if (bValueChanged)
m_nValueAge++;
- int nFieldType = GetFieldType();
-
- switch (nFieldType) {
- case FIELDTYPE_PUSHBUTTON:
- ResetAppearance_PushButton();
+ CPWL_AppStream appStream(this, GetAPDict());
+ switch (GetFieldType()) {
+ case FormFieldType::kPushButton:
+ appStream.SetAsPushButton();
break;
- case FIELDTYPE_CHECKBOX:
- ResetAppearance_CheckBox();
+ case FormFieldType::kCheckBox:
+ appStream.SetAsCheckBox();
break;
- case FIELDTYPE_RADIOBUTTON:
- ResetAppearance_RadioButton();
+ case FormFieldType::kRadioButton:
+ appStream.SetAsRadioButton();
break;
- case FIELDTYPE_COMBOBOX:
- ResetAppearance_ComboBox(sValue);
+ case FormFieldType::kComboBox:
+ appStream.SetAsComboBox(sValue);
break;
- case FIELDTYPE_LISTBOX:
- ResetAppearance_ListBox();
+ case FormFieldType::kListBox:
+ appStream.SetAsListBox();
break;
- case FIELDTYPE_TEXTFIELD:
- ResetAppearance_TextField(sValue);
+ case FormFieldType::kTextField:
+ appStream.SetAsTextField(sValue);
+ break;
+ default:
break;
}
m_pAnnot->ClearCachedAP();
}
-CFX_WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) {
+WideString CPDFSDK_Widget::OnFormat(bool& bFormatted) {
CPDF_FormField* pFormField = GetFormField();
ASSERT(pFormField);
return m_pInterForm->OnFormat(pFormField, bFormatted);
@@ -803,13 +802,13 @@
}
void CPDFSDK_Widget::DrawAppearance(CFX_RenderDevice* pDevice,
- const CFX_Matrix* pUser2Device,
+ const CFX_Matrix& mtUser2Device,
CPDF_Annot::AppearanceMode mode,
const CPDF_RenderOptions* pOptions) {
- int nFieldType = GetFieldType();
+ FormFieldType fieldType = GetFieldType();
- if ((nFieldType == FIELDTYPE_CHECKBOX ||
- nFieldType == FIELDTYPE_RADIOBUTTON) &&
+ if ((fieldType == FormFieldType::kCheckBox ||
+ fieldType == FormFieldType::kRadioButton) &&
mode == CPDF_Annot::Normal &&
!IsWidgetAppearanceValid(CPDF_Annot::Normal)) {
CFX_PathData pathData;
@@ -822,10 +821,10 @@
CFX_GraphStateData gsd;
gsd.m_LineWidth = 0.0f;
- pDevice->DrawPath(&pathData, pUser2Device, &gsd, 0, 0xFFAAAAAA,
+ pDevice->DrawPath(&pathData, &mtUser2Device, &gsd, 0, 0xFFAAAAAA,
FXFILL_ALTERNATE);
} else {
- CPDFSDK_BAAnnot::DrawAppearance(pDevice, pUser2Device, mode, pOptions);
+ CPDFSDK_BAAnnot::DrawAppearance(pDevice, mtUser2Device, mode, pOptions);
}
}
@@ -837,8 +836,8 @@
void CPDFSDK_Widget::DrawShadow(CFX_RenderDevice* pDevice,
CPDFSDK_PageView* pPageView) {
- int nFieldType = GetFieldType();
- if (!m_pInterForm->IsNeedHighLight(nFieldType))
+ FormFieldType fieldType = GetFieldType();
+ if (!m_pInterForm->IsNeedHighLight(fieldType))
return;
CFX_Matrix page2device;
@@ -858,791 +857,12 @@
FX_RECT rcDev = rcDevice.ToFxRect();
pDevice->FillRect(
&rcDev, ArgbEncode(static_cast<int>(m_pInterForm->GetHighlightAlpha()),
- 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;
- }
-
- CPWL_Color crBackground;
- CPWL_Color crBorder;
- int iColorType;
- FX_FLOAT fc[4];
- pControl->GetOriginalBackgroundColor(iColorType, fc);
- if (iColorType > 0)
- crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
-
- pControl->GetOriginalBorderColor(iColorType, fc);
- if (iColorType > 0)
- crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
-
- FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
- CPWL_Dash dsBorder(3, 0, 0);
- CPWL_Color crLeftTop;
- CPWL_Color crRightBottom;
-
- BorderStyle nBorderStyle = GetBorderStyle();
- switch (nBorderStyle) {
- case BorderStyle::DASH:
- dsBorder = CPWL_Dash(3, 3, 0);
- break;
- case BorderStyle::BEVELED:
- fBorderWidth *= 2;
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
- crRightBottom = crBackground / 2.0f;
- break;
- case BorderStyle::INSET:
- fBorderWidth *= 2;
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
- crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
- break;
- default:
- break;
- }
-
- CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
-
- CPWL_Color crText(COLORTYPE_GRAY, 0);
-
- FX_FLOAT fFontSize = 12.0f;
- CFX_ByteString csNameTag;
-
- CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
- if (da.HasColor()) {
- da.GetColor(iColorType, fc);
- crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
- }
-
- if (da.HasFont())
- da.GetFont(csNameTag, fFontSize);
-
- CFX_WideString csWCaption;
- CFX_WideString csNormalCaption, csRolloverCaption, 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<CPDF_String>("Name", "ImgA", false);
- }
- }
-
- if (pRolloverIcon) {
- if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) {
- if (pImageDict->GetStringFor("Name").IsEmpty())
- pImageDict->SetNewFor<CPDF_String>("Name", "ImgB", false);
- }
- }
-
- if (pDownIcon) {
- if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) {
- if (pImageDict->GetStringFor("Name").IsEmpty())
- pImageDict->SetNewFor<CPDF_String>("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: {
- CPWL_Color crTemp = crLeftTop;
- crLeftTop = crRightBottom;
- crRightBottom = crTemp;
- break;
- }
- case BorderStyle::INSET: {
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
- crRightBottom = CPWL_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();
- CPWL_Color crBackground, crBorder, crText;
- int iColorType;
- FX_FLOAT fc[4];
-
- pControl->GetOriginalBackgroundColor(iColorType, fc);
- if (iColorType > 0)
- crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
-
- pControl->GetOriginalBorderColor(iColorType, fc);
- if (iColorType > 0)
- crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
-
- FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
- CPWL_Dash dsBorder(3, 0, 0);
- CPWL_Color crLeftTop, crRightBottom;
-
- BorderStyle nBorderStyle = GetBorderStyle();
- switch (nBorderStyle) {
- case BorderStyle::DASH:
- dsBorder = CPWL_Dash(3, 3, 0);
- break;
- case BorderStyle::BEVELED:
- fBorderWidth *= 2;
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
- crRightBottom = crBackground / 2.0f;
- break;
- case BorderStyle::INSET:
- fBorderWidth *= 2;
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
- crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
- break;
- default:
- break;
- }
-
- CFX_FloatRect rcWindow = GetRotatedRect();
- CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
- CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
- if (da.HasColor()) {
- da.GetColor(iColorType, fc);
- crText = CPWL_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: {
- CPWL_Color crTemp = crLeftTop;
- crLeftTop = crRightBottom;
- crRightBottom = crTemp;
- break;
- }
- case BorderStyle::INSET: {
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
- crRightBottom = CPWL_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();
- CPWL_Color crBackground, crBorder, crText;
- int iColorType;
- FX_FLOAT fc[4];
-
- pControl->GetOriginalBackgroundColor(iColorType, fc);
- if (iColorType > 0)
- crBackground = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
-
- pControl->GetOriginalBorderColor(iColorType, fc);
- if (iColorType > 0)
- crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
-
- FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
- CPWL_Dash dsBorder(3, 0, 0);
- CPWL_Color crLeftTop;
- CPWL_Color crRightBottom;
- BorderStyle nBorderStyle = GetBorderStyle();
- switch (nBorderStyle) {
- case BorderStyle::DASH:
- dsBorder = CPWL_Dash(3, 3, 0);
- break;
- case BorderStyle::BEVELED:
- fBorderWidth *= 2;
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
- crRightBottom = crBackground / 2.0f;
- break;
- case BorderStyle::INSET:
- fBorderWidth *= 2;
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
- crRightBottom = CPWL_Color(COLORTYPE_GRAY, 0.75);
- break;
- default:
- break;
- }
-
- CFX_FloatRect rcWindow = GetRotatedRect();
- CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
-
- CPDF_DefaultAppearance da = pControl->GetDefaultAppearance();
- if (da.HasColor()) {
- da.GetColor(iColorType, fc);
- crText = CPWL_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 =
- CPWL_Utils::DeflateRect(CPWL_Utils::GetCenterSquare(rcWindow), 1.0f);
-
- if (nStyle == PCS_CIRCLE) {
- if (nBorderStyle == BorderStyle::BEVELED) {
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 1);
- crRightBottom = crBackground - 0.25f;
- } else if (nBorderStyle == BorderStyle::INSET) {
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5f);
- crRightBottom = CPWL_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: {
- CPWL_Color crTemp = crLeftTop;
- crLeftTop = crRightBottom;
- crRightBottom = crTemp;
- break;
- }
- case BorderStyle::INSET: {
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
- crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
- break;
- }
- default:
- break;
- }
-
- CFX_ByteString csAP_D_ON;
-
- if (nStyle == PCS_CIRCLE) {
- CPWL_Color crBK = crBackground - 0.25f;
- if (nBorderStyle == BorderStyle::BEVELED) {
- crLeftTop = crBackground - 0.25f;
- crRightBottom = CPWL_Color(COLORTYPE_GRAY, 1);
- crBK = crBackground;
- } else if (nBorderStyle == BorderStyle::INSET) {
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0);
- crRightBottom = CPWL_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();
- CFX_ByteTextBuf sBody, sLines;
-
- CFX_FloatRect rcClient = GetClientRect();
- CFX_FloatRect rcButton = rcClient;
- rcButton.left = rcButton.right - 13;
- rcButton.Normalize();
-
- std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
- 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);
-
- FX_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";
- }
-
- CPWL_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() +
- sLines.AsStringC() + sBody.AsStringC();
-
- WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
-}
-
-void CPDFSDK_Widget::ResetAppearance_ListBox() {
- CPDF_FormControl* pControl = GetFormControl();
- CPDF_FormField* pField = pControl->GetField();
- CFX_FloatRect rcClient = GetClientRect();
- CFX_ByteTextBuf sBody, sLines;
-
- std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
- 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));
-
- FX_FLOAT fFontSize = GetFontSize();
-
- pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize);
-
- pEdit->Initialize();
-
- CFX_ByteTextBuf sList;
- FX_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();
- FX_FLOAT fItemHeight = rcContent.Height();
-
- if (bSelected) {
- CFX_FloatRect rcItem =
- CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy);
- sList << "q\n"
- << CPWL_Utils::GetColorAppStream(
- CPWL_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(CPWL_Color(COLORTYPE_GRAY, 1),
- true)
- << CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy))
- << "ET\n";
- } else {
- CPWL_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.GetSize() > 0) {
- sBody << "/Tx BMC\n"
- << "q\n"
- << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width()
- << " " << rcClient.Height() << " re\nW\nn\n";
- sBody << sList << "Q\nEMC\n";
- }
-
- CFX_ByteString sAP = GetBackgroundAppStream() + GetBorderAppStream() +
- sLines.AsStringC() + sBody.AsStringC();
-
- WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
-}
-
-void CPDFSDK_Widget::ResetAppearance_TextField(const CFX_WideString* sValue) {
- CPDF_FormControl* pControl = GetFormControl();
- CPDF_FormField* pField = pControl->GetField();
- CFX_ByteTextBuf sBody, sLines;
-
- std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
- 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;
- FX_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";
- }
- CPWL_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() +
- sLines.AsStringC() + sBody.AsStringC();
- WriteAppearance("N", GetRotatedRect(), GetMatrix(), sAP);
+ m_pInterForm->GetHighlightColor(fieldType)));
}
CFX_FloatRect CPDFSDK_Widget::GetClientRect() const {
CFX_FloatRect rcWindow = GetRotatedRect();
- FX_FLOAT fBorderWidth = (FX_FLOAT)GetBorderWidth();
+ float fBorderWidth = (float)GetBorderWidth();
switch (GetBorderStyle()) {
case BorderStyle::BEVELED:
case BorderStyle::INSET:
@@ -1651,14 +871,13 @@
default:
break;
}
-
- return CPWL_Utils::DeflateRect(rcWindow, fBorderWidth);
+ return rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
}
CFX_FloatRect CPDFSDK_Widget::GetRotatedRect() const {
CFX_FloatRect rectAnnot = GetRect();
- FX_FLOAT fWidth = rectAnnot.right - rectAnnot.left;
- FX_FLOAT fHeight = rectAnnot.top - rectAnnot.bottom;
+ float fWidth = rectAnnot.right - rectAnnot.left;
+ float fHeight = rectAnnot.top - rectAnnot.bottom;
CPDF_FormControl* pControl = GetFormControl();
CFX_FloatRect rcPDFWindow;
@@ -1677,58 +896,16 @@
return rcPDFWindow;
}
-CFX_ByteString CPDFSDK_Widget::GetBackgroundAppStream() const {
- CPWL_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();
- CPWL_Color crBorder = GetBorderPWLColor();
- CPWL_Color crBackground = GetFillPWLColor();
- CPWL_Color crLeftTop, crRightBottom;
-
- FX_FLOAT fBorderWidth = (FX_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 = CPWL_Color(COLORTYPE_GRAY, 1);
- crRightBottom = crBackground / 2.0f;
- break;
- case BorderStyle::INSET:
- fBorderWidth *= 2;
- crLeftTop = CPWL_Color(COLORTYPE_GRAY, 0.5);
- crRightBottom = CPWL_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();
CFX_FloatRect rcAnnot = GetRect();
- FX_FLOAT fWidth = rcAnnot.right - rcAnnot.left;
- FX_FLOAT fHeight = rcAnnot.top - rcAnnot.bottom;
+ float fWidth = rcAnnot.right - rcAnnot.left;
+ float fHeight = rcAnnot.top - rcAnnot.bottom;
switch (abs(pControl->GetRotation() % 360)) {
- case 0:
default:
- mt = CFX_Matrix(1, 0, 0, 1, 0, 0);
+ case 0:
break;
case 90:
mt = CFX_Matrix(0, 1, -1, 0, fWidth, 0);
@@ -1744,75 +921,47 @@
return mt;
}
-CPWL_Color CPDFSDK_Widget::GetTextPWLColor() const {
- CPWL_Color crText = CPWL_Color(COLORTYPE_GRAY, 0);
+CFX_Color CPDFSDK_Widget::GetTextPWLColor() const {
+ CFX_Color crText = CFX_Color(CFX_Color::kGray, 0);
CPDF_FormControl* pFormCtrl = GetFormControl();
CPDF_DefaultAppearance da = pFormCtrl->GetDefaultAppearance();
if (da.HasColor()) {
int32_t iColorType;
- FX_FLOAT fc[4];
+ float fc[4];
da.GetColor(iColorType, fc);
- crText = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
+ crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
}
return crText;
}
-CPWL_Color CPDFSDK_Widget::GetBorderPWLColor() const {
- CPWL_Color crBorder;
+CFX_Color CPDFSDK_Widget::GetBorderPWLColor() const {
+ CFX_Color crBorder;
CPDF_FormControl* pFormCtrl = GetFormControl();
int32_t iColorType;
- FX_FLOAT fc[4];
+ float fc[4];
pFormCtrl->GetOriginalBorderColor(iColorType, fc);
if (iColorType > 0)
- crBorder = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
+ crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
return crBorder;
}
-CPWL_Color CPDFSDK_Widget::GetFillPWLColor() const {
- CPWL_Color crFill;
+CFX_Color CPDFSDK_Widget::GetFillPWLColor() const {
+ CFX_Color crFill;
CPDF_FormControl* pFormCtrl = GetFormControl();
int32_t iColorType;
- FX_FLOAT fc[4];
+ float fc[4];
pFormCtrl->GetOriginalBackgroundColor(iColorType, fc);
if (iColorType > 0)
- crFill = CPWL_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
+ crFill = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]);
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<CPDF_Dictionary>("Resources");
-
- CPDF_Dictionary* pXObject =
- pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
- pXObject->SetNewFor<CPDF_Reference>(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) {
@@ -1843,7 +992,7 @@
param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
param.m_wsPrevText = data.sValue;
- CXFA_WidgetAcc* pAcc = hWidget->GetDataAcc();
+ CXFA_WidgetAcc* pAcc = hWidget->GetNode()->GetWidgetAcc();
param.m_pTarget = pAcc;
int32_t nRet = pXFAWidgetHandler->ProcessEvent(pAcc, ¶m);
@@ -1859,7 +1008,7 @@
CPDF_Action action = GetAAction(type);
if (action.GetDict() && action.GetType() != CPDF_Action::Unknown) {
- CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHander();
+ CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler();
return pActionHandler->DoAction_Field(action, type, pFormFillEnv,
GetFormField(), data);
}
@@ -1893,18 +1042,10 @@
break;
}
- return CPDF_Action();
+ return CPDF_Action(nullptr);
}
-CFX_WideString CPDFSDK_Widget::GetAlternateName() const {
+WideString CPDFSDK_Widget::GetAlternateName() const {
CPDF_FormField* pFormField = GetFormField();
return pFormField->GetAlternateName();
}
-
-int32_t CPDFSDK_Widget::GetAppearanceAge() const {
- return m_nAppAge;
-}
-
-int32_t CPDFSDK_Widget::GetValueAge() const {
- return m_nValueAge;
-}
diff --git a/fpdfsdk/cpdfsdk_widget.h b/fpdfsdk/cpdfsdk_widget.h
index 21e5169..4b11150 100644
--- a/fpdfsdk/cpdfsdk_widget.h
+++ b/fpdfsdk/cpdfsdk_widget.h
@@ -14,9 +14,10 @@
#include "core/fpdfdoc/cpdf_annot.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxge/cfx_color.h"
#include "fpdfsdk/cpdfsdk_baannot.h"
#include "fpdfsdk/pdfsdk_fieldaction.h"
-#include "fpdfsdk/pdfwindow/cpwl_color.h"
class CFX_RenderDevice;
class CPDF_Annot;
@@ -70,23 +71,23 @@
int GetLayoutOrder() const override;
- int GetFieldType() const;
+ FormFieldType GetFieldType() const;
int GetFieldFlags() const;
int GetRotate() const;
bool GetFillColor(FX_COLORREF& color) const;
bool GetBorderColor(FX_COLORREF& color) const;
bool GetTextColor(FX_COLORREF& color) const;
- FX_FLOAT GetFontSize() const;
+ float GetFontSize() const;
int GetSelectedIndex(int nIndex) const;
#ifndef PDF_ENABLE_XFA
- CFX_WideString GetValue() const;
+ WideString GetValue() const;
#else
- CFX_WideString GetValue(bool bDisplay = true) const;
+ WideString GetValue(bool bDisplay = true) const;
#endif // PDF_ENABLE_XFA
- CFX_WideString GetDefaultValue() const;
- CFX_WideString GetOptionLabel(int nIndex) const;
+ WideString GetDefaultValue() const;
+ WideString GetOptionLabel(int nIndex) const;
int CountOptions() const;
bool IsOptionSelected(int nIndex) const;
int GetTopVisibleIndex() const;
@@ -94,13 +95,13 @@
int GetAlignment() const;
int GetMaxLen() const;
#ifdef PDF_ENABLE_XFA
- CFX_WideString GetName() const;
+ WideString GetName() const;
#endif // PDF_ENABLE_XFA
- CFX_WideString GetAlternateName() const;
+ WideString GetAlternateName() const;
void SetCheck(bool bChecked, bool bNotify);
- void SetValue(const CFX_WideString& sValue, bool bNotify);
- void SetDefaultValue(const CFX_WideString& sValue);
+ void SetValue(const WideString& sValue, bool bNotify);
+ void SetDefaultValue(const WideString& sValue);
void SetOptionSelection(int index, bool bSelected, bool bNotify);
void ClearSelection(bool bNotify);
void SetTopVisibleIndex(int index);
@@ -108,16 +109,16 @@
#ifdef PDF_ENABLE_XFA
void ResetAppearance(bool bValueChanged);
#endif // PDF_ENABLE_XFA
- void ResetAppearance(const CFX_WideString* sValue, bool bValueChanged);
+ void ResetAppearance(const WideString* sValue, bool bValueChanged);
void ResetFieldAppearance(bool bValueChanged);
void UpdateField();
- CFX_WideString OnFormat(bool& bFormatted);
+ WideString OnFormat(bool& bFormatted);
bool OnAAction(CPDF_AAction::AActionType type,
PDFSDK_FieldAction& data,
CPDFSDK_PageView* pPageView);
- CPDFSDK_InterForm* GetInterForm() const { return m_pInterForm; }
+ CPDFSDK_InterForm* GetInterForm() const { return m_pInterForm.Get(); }
CPDF_FormField* GetFormField() const;
CPDF_FormControl* GetFormControl() const;
static CPDF_FormControl* GetFormControl(CPDF_InterForm* pInterForm,
@@ -129,45 +130,31 @@
void ClearAppModified();
bool IsAppModified() const;
- int32_t GetAppearanceAge() const;
- int32_t GetValueAge() const;
+ uint32_t GetAppearanceAge() const { return m_nAppearanceAge; }
+ uint32_t GetValueAge() const { return m_nValueAge; }
bool IsWidgetAppearanceValid(CPDF_Annot::AppearanceMode mode);
void DrawAppearance(CFX_RenderDevice* pDevice,
- const CFX_Matrix* pUser2Device,
+ const CFX_Matrix& mtUser2Device,
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_Color GetTextPWLColor() const;
+ CFX_Color GetBorderPWLColor() const;
+ CFX_Color GetFillPWLColor() const;
- CFX_ByteString GetBackgroundAppStream() const;
- CFX_ByteString GetBorderAppStream() const;
- CFX_Matrix GetMatrix() const;
-
- CPWL_Color GetTextPWLColor() const;
- CPWL_Color GetBorderPWLColor() const;
- CPWL_Color GetFillPWLColor() const;
-
- void AddImageToAppearance(const CFX_ByteString& sAPType, CPDF_Stream* pImage);
- void RemoveAppearance(const CFX_ByteString& sAPType);
-
- CPDFSDK_InterForm* const m_pInterForm;
+ private:
+ UnownedPtr<CPDFSDK_InterForm> const m_pInterForm;
bool m_bAppModified;
- int32_t m_nAppAge;
- int32_t m_nValueAge;
+ uint32_t m_nAppearanceAge;
+ uint32_t m_nValueAge;
#ifdef PDF_ENABLE_XFA
- mutable CXFA_FFWidget* m_hMixXFAWidget;
- mutable CXFA_FFWidgetHandler* m_pWidgetHandler;
+ mutable UnownedPtr<CXFA_FFWidget> m_hMixXFAWidget;
+ mutable UnownedPtr<CXFA_FFWidgetHandler> m_pWidgetHandler;
#endif // PDF_ENABLE_XFA
};
diff --git a/fpdfsdk/cpdfsdk_widgethandler.cpp b/fpdfsdk/cpdfsdk_widgethandler.cpp
index e85d24c..dcce7b6 100644
--- a/fpdfsdk/cpdfsdk_widgethandler.cpp
+++ b/fpdfsdk/cpdfsdk_widgethandler.cpp
@@ -25,7 +25,8 @@
CPDFSDK_WidgetHandler::CPDFSDK_WidgetHandler(
CPDFSDK_FormFillEnvironment* pFormFillEnv)
- : m_pFormFillEnv(pFormFillEnv), m_pFormFiller(nullptr) {}
+ : m_pFormFillEnv(pFormFillEnv),
+ m_pFormFiller(pFormFillEnv->GetInteractiveFormFiller()) {}
CPDFSDK_WidgetHandler::~CPDFSDK_WidgetHandler() {}
@@ -42,12 +43,11 @@
if ((nFieldFlags & FIELDFLAG_READONLY) == FIELDFLAG_READONLY)
return false;
- if (pWidget->GetFieldType() == FIELDTYPE_PUSHBUTTON)
+ if (pWidget->GetFieldType() == FormFieldType::kPushButton)
return true;
CPDF_Page* pPage = pWidget->GetPDFPage();
- CPDF_Document* pDocument = pPage->m_pDocument;
- uint32_t dwPermissions = pDocument->GetUserPermissions();
+ uint32_t dwPermissions = pPage->m_pDocument->GetUserPermissions();
return (dwPermissions & FPDFPERM_FILL_FORM) ||
(dwPermissions & FPDFPERM_ANNOT_FORM);
}
@@ -95,7 +95,7 @@
bool bDrawAnnots) {
if (pAnnot->IsSignatureWidget()) {
static_cast<CPDFSDK_BAAnnot*>(pAnnot)->DrawAppearance(
- pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
+ pDevice, *pUser2Device, CPDF_Annot::Normal, nullptr);
} else {
if (m_pFormFiller)
m_pFormFiller->OnDraw(pPageView, pAnnot, pDevice, pUser2Device);
@@ -227,18 +227,23 @@
if (!pWidget->IsAppearanceValid())
pWidget->ResetAppearance(nullptr, false);
- int nFieldType = pWidget->GetFieldType();
- if (nFieldType == FIELDTYPE_TEXTFIELD || nFieldType == FIELDTYPE_COMBOBOX) {
+ FormFieldType fieldType = pWidget->GetFieldType();
+ if (fieldType == FormFieldType::kTextField ||
+ fieldType == FormFieldType::kComboBox) {
bool bFormatted = false;
- CFX_WideString sValue = pWidget->OnFormat(bFormatted);
- if (bFormatted && nFieldType == FIELDTYPE_COMBOBOX)
+ CPDFSDK_Annot::ObservedPtr pObserved(pWidget);
+ WideString sValue = pWidget->OnFormat(bFormatted);
+ if (!pObserved)
+ return;
+
+ if (bFormatted && fieldType == FormFieldType::kComboBox)
pWidget->ResetAppearance(&sValue, false);
}
#ifdef PDF_ENABLE_XFA
CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
CPDFXFA_Context* pContext = pPageView->GetFormFillEnv()->GetXFAContext();
- if (pContext->GetDocType() == DOCTYPE_STATIC_XFA) {
+ if (pContext->GetFormType() == FormType::kXFAForeground) {
if (!pWidget->IsAppearanceValid() && !pWidget->GetValue().IsEmpty())
pWidget->ResetAppearance(false);
}
@@ -273,8 +278,20 @@
CPDFSDK_Annot* pAnnot) {
if (!pAnnot->IsSignatureWidget() && m_pFormFiller)
return CFX_FloatRect(m_pFormFiller->GetViewBBox(pPageView, pAnnot));
+ return CFX_FloatRect();
+}
- return CFX_FloatRect(0, 0, 0, 0);
+WideString CPDFSDK_WidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) {
+ if (!pAnnot->IsSignatureWidget() && m_pFormFiller)
+ return m_pFormFiller->GetSelectedText(pAnnot);
+
+ return WideString();
+}
+
+void CPDFSDK_WidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot,
+ const WideString& text) {
+ if (!pAnnot->IsSignatureWidget() && m_pFormFiller)
+ m_pFormFiller->ReplaceSelection(pAnnot, text);
}
bool CPDFSDK_WidgetHandler::HitTest(CPDFSDK_PageView* pPageView,
diff --git a/fpdfsdk/cpdfsdk_widgethandler.h b/fpdfsdk/cpdfsdk_widgethandler.h
index 6e4d50b..f8aa7de 100644
--- a/fpdfsdk/cpdfsdk_widgethandler.h
+++ b/fpdfsdk/cpdfsdk_widgethandler.h
@@ -7,8 +7,8 @@
#ifndef FPDFSDK_CPDFSDK_WIDGETHANDLER_H_
#define FPDFSDK_CPDFSDK_WIDGETHANDLER_H_
-#include "core/fxcrt/fx_basic.h"
#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/ipdfsdk_annothandler.h"
class CFFL_InteractiveFormFiller;
@@ -37,6 +37,8 @@
void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override;
CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot) override;
+ WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override;
+ void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override;
bool HitTest(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
const CFX_PointF& point) override;
@@ -96,14 +98,13 @@
CPDFSDK_Annot::ObservedPtr* pNewAnnot) override;
#endif // PDF_ENABLE_XFA
- void SetFormFiller(CFFL_InteractiveFormFiller* pFiller) {
- m_pFormFiller = pFiller;
+ CFFL_InteractiveFormFiller* GetFormFiller() const {
+ return m_pFormFiller.Get();
}
- CFFL_InteractiveFormFiller* GetFormFiller() { return m_pFormFiller; }
private:
- CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
- CFFL_InteractiveFormFiller* m_pFormFiller;
+ UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
+ UnownedPtr<CFFL_InteractiveFormFiller> const m_pFormFiller;
};
#endif // FPDFSDK_CPDFSDK_WIDGETHANDLER_H_
diff --git a/fpdfsdk/cpdfsdk_xfawidget.cpp b/fpdfsdk/cpdfsdk_xfawidget.cpp
index b30e5f3..af08023 100644
--- a/fpdfsdk/cpdfsdk_xfawidget.cpp
+++ b/fpdfsdk/cpdfsdk_xfawidget.cpp
@@ -7,7 +7,7 @@
#include "fpdfsdk/cpdfsdk_xfawidget.h"
#include "fpdfsdk/ipdfsdk_annothandler.h"
-#include "xfa/fxfa/xfa_ffwidget.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
CPDFSDK_XFAWidget::CPDFSDK_XFAWidget(CXFA_FFWidget* pAnnot,
CPDFSDK_PageView* pPageView,
@@ -16,12 +16,14 @@
m_pInterForm(pInterForm),
m_hXFAWidget(pAnnot) {}
+CPDFSDK_XFAWidget::~CPDFSDK_XFAWidget() {}
+
bool CPDFSDK_XFAWidget::IsXFAField() {
return true;
}
CXFA_FFWidget* CPDFSDK_XFAWidget::GetXFAWidget() const {
- return m_hXFAWidget;
+ return m_hXFAWidget.Get();
}
CPDF_Annot::Subtype CPDFSDK_XFAWidget::GetAnnotSubtype() const {
diff --git a/fpdfsdk/cpdfsdk_xfawidget.h b/fpdfsdk/cpdfsdk_xfawidget.h
index 9d0be75..d2635eb 100644
--- a/fpdfsdk/cpdfsdk_xfawidget.h
+++ b/fpdfsdk/cpdfsdk_xfawidget.h
@@ -9,6 +9,7 @@
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/cpdfsdk_annot.h"
class CPDFSDK_InterForm;
@@ -20,18 +21,19 @@
CPDFSDK_XFAWidget(CXFA_FFWidget* pAnnot,
CPDFSDK_PageView* pPageView,
CPDFSDK_InterForm* pInterForm);
- ~CPDFSDK_XFAWidget() override {}
+ ~CPDFSDK_XFAWidget() override;
+ // CPDFSDK_Annot:
bool IsXFAField() override;
CXFA_FFWidget* GetXFAWidget() const override;
CPDF_Annot::Subtype GetAnnotSubtype() const override;
CFX_FloatRect GetRect() const override;
- CPDFSDK_InterForm* GetInterForm() { return m_pInterForm; }
+ CPDFSDK_InterForm* GetInterForm() const { return m_pInterForm.Get(); }
private:
- CPDFSDK_InterForm* m_pInterForm;
- CXFA_FFWidget* m_hXFAWidget;
+ UnownedPtr<CPDFSDK_InterForm> m_pInterForm;
+ UnownedPtr<CXFA_FFWidget> m_hXFAWidget;
};
#endif // FPDFSDK_CPDFSDK_XFAWIDGET_H_
diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
index 653eb8a..897e16d 100644
--- a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
+++ b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
@@ -15,12 +15,13 @@
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "xfa/fwl/cfwl_app.h"
#include "xfa/fwl/fwl_widgethit.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffpageview.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
+#include "xfa/fxfa/cxfa_ffwidgethandler.h"
#include "xfa/fxfa/fxfa_basic.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffpageview.h"
-#include "xfa/fxfa/xfa_ffwidget.h"
-#include "xfa/fxfa/xfa_ffwidgethandler.h"
-#include "xfa/fxgraphics/cfx_graphics.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
+#include "xfa/fxgraphics/cxfa_graphics.h"
CPDFSDK_XFAWidgetHandler::CPDFSDK_XFAWidgetHandler(
CPDFSDK_FormFillEnvironment* pFormFillEnv)
@@ -53,14 +54,14 @@
ASSERT(pPageView);
ASSERT(pAnnot);
- CFX_Graphics gs(pDevice);
+ CXFA_Graphics gs(pDevice);
CFX_Matrix mt = *pUser2Device;
bool bIsHighlight = false;
if (pPageView->GetFormFillEnv()->GetFocusAnnot() != pAnnot)
bIsHighlight = true;
- GetXFAWidgetHandler(pAnnot)->RenderWidget(pAnnot->GetXFAWidget(), &gs, &mt,
+ GetXFAWidgetHandler(pAnnot)->RenderWidget(pAnnot->GetXFAWidget(), &gs, mt,
bIsHighlight);
// to do highlight and shadow
@@ -81,7 +82,8 @@
ASSERT(pAnnot);
CFX_RectF rcBBox;
- XFA_Element eType = pAnnot->GetXFAWidget()->GetDataAcc()->GetUIType();
+ XFA_Element eType =
+ pAnnot->GetXFAWidget()->GetNode()->GetWidgetAcc()->GetUIType();
if (eType == XFA_Element::Signature)
rcBBox = pAnnot->GetXFAWidget()->GetBBox(XFA_WidgetStatus_Visible, true);
else
@@ -97,6 +99,23 @@
return rcWidget;
}
+WideString CPDFSDK_XFAWidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) {
+ if (!pAnnot)
+ return WideString();
+
+ CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot);
+ return pWidgetHandler->GetSelectedText(pAnnot->GetXFAWidget());
+}
+
+void CPDFSDK_XFAWidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot,
+ const WideString& text) {
+ if (!pAnnot)
+ return;
+
+ CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot);
+ return pWidgetHandler->PasteText(pAnnot->GetXFAWidget(), text);
+}
+
bool CPDFSDK_XFAWidgetHandler::HitTest(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
const CFX_PointF& point) {
diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.h b/fpdfsdk/cpdfsdk_xfawidgethandler.h
index 3903103..e0dccbe 100644
--- a/fpdfsdk/cpdfsdk_xfawidgethandler.h
+++ b/fpdfsdk/cpdfsdk_xfawidgethandler.h
@@ -7,8 +7,8 @@
#ifndef FPDFSDK_CPDFSDK_XFAWIDGETHANDLER_H_
#define FPDFSDK_CPDFSDK_XFAWIDGETHANDLER_H_
-#include "core/fxcrt/fx_basic.h"
#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/ipdfsdk_annothandler.h"
class CFX_Matrix;
@@ -32,6 +32,8 @@
void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override;
CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot) override;
+ WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override;
+ void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override;
bool HitTest(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
const CFX_PointF& point) override;
@@ -92,7 +94,7 @@
CXFA_FFWidgetHandler* GetXFAWidgetHandler(CPDFSDK_Annot* pAnnot);
uint32_t GetFWLFlags(uint32_t dwFlag);
- CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
+ UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
};
#endif // FPDFSDK_CPDFSDK_XFAWIDGETHANDLER_H_
diff --git a/fpdfsdk/formfiller/cba_fontmap.cpp b/fpdfsdk/formfiller/cba_fontmap.cpp
index 750b416..d675676 100644
--- a/fpdfsdk/formfiller/cba_fontmap.cpp
+++ b/fpdfsdk/formfiller/cba_fontmap.cpp
@@ -28,7 +28,7 @@
m_sAPType("N") {
CPDF_Page* pPage = pAnnot->GetPDFPage();
- m_pDocument = pPage->m_pDocument;
+ m_pDocument = pPage->m_pDocument.Get();
m_pAnnotDict = pAnnot->GetPDFAnnot()->GetAnnotDict();
Initialize();
}
@@ -38,14 +38,14 @@
void CBA_FontMap::Reset() {
Empty();
m_pDefaultFont = nullptr;
- m_sDefaultFontName = "";
+ m_sDefaultFontName.clear();
}
void CBA_FontMap::Initialize() {
- int32_t nCharset = FXFONT_DEFAULT_CHARSET;
+ int32_t nCharset = FX_CHARSET_Default;
if (!m_pDefaultFont) {
- m_pDefaultFont = GetAnnotDefaultFont(m_sDefaultFontName);
+ m_pDefaultFont = GetAnnotDefaultFont(&m_sDefaultFontName);
if (m_pDefaultFont) {
if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont()) {
nCharset = pSubstFont->m_Charset;
@@ -54,21 +54,21 @@
m_sDefaultFontName == "Wingdings2" ||
m_sDefaultFontName == "Wingdings3" ||
m_sDefaultFontName == "Webdings")
- nCharset = FXFONT_SYMBOL_CHARSET;
+ nCharset = FX_CHARSET_Symbol;
else
- nCharset = FXFONT_ANSI_CHARSET;
+ nCharset = FX_CHARSET_ANSI;
}
- AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset);
- AddFontToAnnotDict(m_pDefaultFont, m_sDefaultFontName);
+ AddFontData(m_pDefaultFont.Get(), m_sDefaultFontName, nCharset);
+ AddFontToAnnotDict(m_pDefaultFont.Get(), m_sDefaultFontName);
}
}
- if (nCharset != FXFONT_ANSI_CHARSET)
+ if (nCharset != FX_CHARSET_ANSI)
CPWL_FontMap::Initialize();
}
void CBA_FontMap::SetDefaultFont(CPDF_Font* pFont,
- const CFX_ByteString& sFontName) {
+ const ByteString& sFontName) {
ASSERT(pFont);
if (m_pDefaultFont)
@@ -77,19 +77,19 @@
m_pDefaultFont = pFont;
m_sDefaultFontName = sFontName;
- int32_t nCharset = FXFONT_DEFAULT_CHARSET;
+ int32_t nCharset = FX_CHARSET_Default;
if (const CFX_SubstFont* pSubstFont = m_pDefaultFont->GetSubstFont())
nCharset = pSubstFont->m_Charset;
- AddFontData(m_pDefaultFont, m_sDefaultFontName, nCharset);
+ AddFontData(m_pDefaultFont.Get(), m_sDefaultFontName, nCharset);
}
-CPDF_Font* CBA_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias,
+CPDF_Font* CBA_FontMap::FindFontSameCharset(ByteString* sFontAlias,
int32_t nCharset) {
if (m_pAnnotDict->GetStringFor("Subtype") != "Widget")
return nullptr;
CPDF_Document* pDocument = GetDocument();
- CPDF_Dictionary* pRootDict = pDocument->GetRoot();
+ const CPDF_Dictionary* pRootDict = pDocument->GetRoot();
if (!pRootDict)
return nullptr;
@@ -105,11 +105,11 @@
}
CPDF_Document* CBA_FontMap::GetDocument() {
- return m_pDocument;
+ return m_pDocument.Get();
}
CPDF_Font* CBA_FontMap::FindResFontSameCharset(CPDF_Dictionary* pResDict,
- CFX_ByteString& sFontAlias,
+ ByteString* sFontAlias,
int32_t nCharset) {
if (!pResDict)
return nullptr;
@@ -121,7 +121,7 @@
CPDF_Document* pDocument = GetDocument();
CPDF_Font* pFind = nullptr;
for (const auto& it : *pFonts) {
- const CFX_ByteString& csKey = it.first;
+ const ByteString& csKey = it.first;
if (!it.second)
continue;
@@ -138,20 +138,19 @@
if (!pSubst)
continue;
if (pSubst->m_Charset == nCharset) {
- sFontAlias = csKey;
+ *sFontAlias = csKey;
pFind = pFont;
}
}
return pFind;
}
-void CBA_FontMap::AddedFont(CPDF_Font* pFont,
- const CFX_ByteString& sFontAlias) {
+void CBA_FontMap::AddedFont(CPDF_Font* pFont, const ByteString& sFontAlias) {
AddFontToAnnotDict(pFont, sFontAlias);
}
void CBA_FontMap::AddFontToAnnotDict(CPDF_Font* pFont,
- const CFX_ByteString& sAlias) {
+ const ByteString& sAlias) {
if (!pFont)
return;
@@ -167,7 +166,7 @@
CPDF_Stream* pStream = pAPDict->GetStreamFor(m_sAPType);
if (!pStream) {
pStream = m_pDocument->NewIndirect<CPDF_Stream>();
- pAPDict->SetNewFor<CPDF_Reference>(m_sAPType, m_pDocument,
+ pAPDict->SetNewFor<CPDF_Reference>(m_sAPType, m_pDocument.Get(),
pStream->GetObjNum());
}
@@ -185,64 +184,65 @@
CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictFor("Font");
if (!pStreamResFontList) {
pStreamResFontList = m_pDocument->NewIndirect<CPDF_Dictionary>();
- pStreamResList->SetNewFor<CPDF_Reference>("Font", m_pDocument,
+ pStreamResList->SetNewFor<CPDF_Reference>("Font", m_pDocument.Get(),
pStreamResFontList->GetObjNum());
}
if (!pStreamResFontList->KeyExist(sAlias)) {
pStreamResFontList->SetNewFor<CPDF_Reference>(
- sAlias, m_pDocument, pFont->GetFontDict()->GetObjNum());
+ sAlias, m_pDocument.Get(), pFont->GetFontDict()->GetObjNum());
}
}
-CPDF_Font* CBA_FontMap::GetAnnotDefaultFont(CFX_ByteString& sAlias) {
+CPDF_Font* CBA_FontMap::GetAnnotDefaultFont(ByteString* sAlias) {
CPDF_Dictionary* pAcroFormDict = nullptr;
const bool bWidget = (m_pAnnotDict->GetStringFor("Subtype") == "Widget");
if (bWidget) {
- if (CPDF_Dictionary* pRootDict = m_pDocument->GetRoot())
+ const CPDF_Dictionary* pRootDict = m_pDocument->GetRoot();
+ if (pRootDict)
pAcroFormDict = pRootDict->GetDictFor("AcroForm");
}
- CFX_ByteString sDA;
- CPDF_Object* pObj = FPDF_GetFieldAttr(m_pAnnotDict, "DA");
+ ByteString sDA;
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pAnnotDict.Get(), "DA");
if (pObj)
sDA = pObj->GetString();
if (bWidget) {
if (sDA.IsEmpty()) {
pObj = FPDF_GetFieldAttr(pAcroFormDict, "DA");
- sDA = pObj ? pObj->GetString() : CFX_ByteString();
+ sDA = pObj ? pObj->GetString() : ByteString();
}
}
if (sDA.IsEmpty())
return nullptr;
- CPDF_SimpleParser syntax(sDA.AsStringC());
+ CPDF_SimpleParser syntax(sDA.AsStringView());
syntax.FindTagParamFromStart("Tf", 2);
- CFX_ByteString sFontName(syntax.GetWord());
- sAlias = PDF_NameDecode(sFontName).Mid(1);
- CPDF_Dictionary* pFontDict = nullptr;
+ ByteString sFontName(syntax.GetWord());
+ ByteString sDecodedFontName = PDF_NameDecode(sFontName);
+ *sAlias = sDecodedFontName.Right(sDecodedFontName.GetLength() - 1);
+
+ CPDF_Dictionary* pFontDict = nullptr;
if (CPDF_Dictionary* pAPDict = m_pAnnotDict->GetDictFor("AP")) {
if (CPDF_Dictionary* pNormalDict = pAPDict->GetDictFor("N")) {
if (CPDF_Dictionary* pNormalResDict =
pNormalDict->GetDictFor("Resources")) {
if (CPDF_Dictionary* pResFontDict = pNormalResDict->GetDictFor("Font"))
- pFontDict = pResFontDict->GetDictFor(sAlias);
+ pFontDict = pResFontDict->GetDictFor(*sAlias);
}
}
}
-
if (bWidget && !pFontDict && pAcroFormDict) {
if (CPDF_Dictionary* pDRDict = pAcroFormDict->GetDictFor("DR")) {
if (CPDF_Dictionary* pDRFontDict = pDRDict->GetDictFor("Font"))
- pFontDict = pDRFontDict->GetDictFor(sAlias);
+ pFontDict = pDRFontDict->GetDictFor(*sAlias);
}
}
-
return pFontDict ? m_pDocument->LoadFont(pFontDict) : nullptr;
}
-void CBA_FontMap::SetAPType(const CFX_ByteString& sAPType) {
+void CBA_FontMap::SetAPType(const ByteString& sAPType) {
m_sAPType = sAPType;
Reset();
diff --git a/fpdfsdk/formfiller/cba_fontmap.h b/fpdfsdk/formfiller/cba_fontmap.h
index c0e569a..45df8c8 100644
--- a/fpdfsdk/formfiller/cba_fontmap.h
+++ b/fpdfsdk/formfiller/cba_fontmap.h
@@ -7,7 +7,8 @@
#ifndef FPDFSDK_FORMFILLER_CBA_FONTMAP_H_
#define FPDFSDK_FORMFILLER_CBA_FONTMAP_H_
-#include "fpdfsdk/pdfwindow/PWL_FontMap.h"
+#include "core/fxcrt/unowned_ptr.h"
+#include "fpdfsdk/pwl/cpwl_font_map.h"
class CPDF_Dictionary;
class CPDFSDK_Annot;
@@ -17,30 +18,29 @@
CBA_FontMap(CPDFSDK_Annot* pAnnot, CFX_SystemHandler* pSystemHandler);
~CBA_FontMap() override;
- void SetDefaultFont(CPDF_Font* pFont, const CFX_ByteString& sFontName);
-
void Reset();
- void SetAPType(const CFX_ByteString& sAPType);
+ void SetDefaultFont(CPDF_Font* pFont, const ByteString& sFontName);
+ void SetAPType(const ByteString& sAPType);
private:
// CPWL_FontMap:
void Initialize() override;
CPDF_Document* GetDocument() override;
- CPDF_Font* FindFontSameCharset(CFX_ByteString& sFontAlias,
+ CPDF_Font* FindFontSameCharset(ByteString* sFontAlias,
int32_t nCharset) override;
- void AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias) override;
+ void AddedFont(CPDF_Font* pFont, const ByteString& sFontAlias) override;
CPDF_Font* FindResFontSameCharset(CPDF_Dictionary* pResDict,
- CFX_ByteString& sFontAlias,
+ ByteString* sFontAlias,
int32_t nCharset);
- CPDF_Font* GetAnnotDefaultFont(CFX_ByteString& csNameTag);
- void AddFontToAnnotDict(CPDF_Font* pFont, const CFX_ByteString& sAlias);
+ CPDF_Font* GetAnnotDefaultFont(ByteString* csNameTag);
+ void AddFontToAnnotDict(CPDF_Font* pFont, const ByteString& sAlias);
- CPDF_Document* m_pDocument;
- CPDF_Dictionary* m_pAnnotDict;
- CPDF_Font* m_pDefaultFont;
- CFX_ByteString m_sDefaultFontName;
- CFX_ByteString m_sAPType;
+ UnownedPtr<CPDF_Document> m_pDocument;
+ UnownedPtr<CPDF_Dictionary> m_pAnnotDict;
+ UnownedPtr<CPDF_Font> m_pDefaultFont;
+ ByteString m_sDefaultFontName;
+ ByteString m_sAPType;
};
#endif // FPDFSDK_FORMFILLER_CBA_FONTMAP_H_
diff --git a/fpdfsdk/formfiller/cffl_button.cpp b/fpdfsdk/formfiller/cffl_button.cpp
new file mode 100644
index 0000000..dab0045
--- /dev/null
+++ b/fpdfsdk/formfiller/cffl_button.cpp
@@ -0,0 +1,103 @@
+// 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/formfiller/cffl_button.h"
+
+CFFL_Button::CFFL_Button(CPDFSDK_FormFillEnvironment* pApp,
+ CPDFSDK_Widget* pWidget)
+ : CFFL_FormFiller(pApp, pWidget), m_bMouseIn(false), m_bMouseDown(false) {}
+
+CFFL_Button::~CFFL_Button() {}
+
+void CFFL_Button::OnMouseEnter(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot) {
+ m_bMouseIn = true;
+ InvalidateRect(GetViewBBox(pPageView, pAnnot));
+}
+
+void CFFL_Button::OnMouseExit(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot) {
+ m_bMouseIn = false;
+ InvalidateRect(GetViewBBox(pPageView, pAnnot));
+ EndTimer();
+ ASSERT(m_pWidget);
+}
+
+bool CFFL_Button::OnLButtonDown(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ uint32_t nFlags,
+ const CFX_PointF& point) {
+ if (!pAnnot->GetRect().Contains(point))
+ return false;
+
+ m_bMouseDown = true;
+ m_bValid = true;
+ InvalidateRect(GetViewBBox(pPageView, pAnnot));
+ return true;
+}
+
+bool CFFL_Button::OnLButtonUp(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ uint32_t nFlags,
+ const CFX_PointF& point) {
+ if (!pAnnot->GetRect().Contains(point))
+ return false;
+
+ m_bMouseDown = false;
+ m_pWidget->GetPDFPage();
+ InvalidateRect(GetViewBBox(pPageView, pAnnot));
+ return true;
+}
+
+bool CFFL_Button::OnMouseMove(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ uint32_t nFlags,
+ const CFX_PointF& point) {
+ return true;
+}
+
+void CFFL_Button::OnDraw(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ ASSERT(pPageView);
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot);
+ CPDF_FormControl* pCtrl = pWidget->GetFormControl();
+ if (pCtrl->GetHighlightingMode() != CPDF_FormControl::Push) {
+ pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal,
+ nullptr);
+ return;
+ }
+ if (m_bMouseDown) {
+ if (pWidget->IsWidgetAppearanceValid(CPDF_Annot::Down)) {
+ pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Down,
+ nullptr);
+ } else {
+ pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal,
+ nullptr);
+ }
+ return;
+ }
+ if (m_bMouseIn) {
+ if (pWidget->IsWidgetAppearanceValid(CPDF_Annot::Rollover)) {
+ pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Rollover,
+ nullptr);
+ } else {
+ pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal,
+ nullptr);
+ }
+ return;
+ }
+
+ pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, nullptr);
+}
+
+void CFFL_Button::OnDrawDeactive(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ OnDraw(pPageView, pAnnot, pDevice, mtUser2Device);
+}
diff --git a/fpdfsdk/formfiller/cffl_button.h b/fpdfsdk/formfiller/cffl_button.h
new file mode 100644
index 0000000..ad2eb5b
--- /dev/null
+++ b/fpdfsdk/formfiller/cffl_button.h
@@ -0,0 +1,56 @@
+// 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_FORMFILLER_CFFL_BUTTON_H_
+#define FPDFSDK_FORMFILLER_CFFL_BUTTON_H_
+
+#include "core/fxcrt/fx_coordinates.h"
+#include "fpdfsdk/formfiller/cffl_formfiller.h"
+
+class CFX_RenderDevice;
+class CFX_Matrix;
+class CPDFSDK_Annot;
+class CPDFSDK_FormFillEnvironment;
+class CPDFSDK_PageView;
+class CPDFSDK_Widget;
+
+class CFFL_Button : public CFFL_FormFiller {
+ public:
+ CFFL_Button(CPDFSDK_FormFillEnvironment* pFormFillEnv,
+ CPDFSDK_Widget* pWidget);
+ ~CFFL_Button() override;
+
+ // CFFL_FormFiller
+ void OnMouseEnter(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot) override;
+ void OnMouseExit(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override;
+ bool OnLButtonDown(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ uint32_t nFlags,
+ const CFX_PointF& point) override;
+ bool OnLButtonUp(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ uint32_t nFlags,
+ const CFX_PointF& point) override;
+ bool OnMouseMove(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ uint32_t nFlags,
+ const CFX_PointF& point) override;
+ void OnDraw(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) override;
+ void OnDrawDeactive(CPDFSDK_PageView* pPageView,
+ CPDFSDK_Annot* pAnnot,
+ CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) override;
+
+ private:
+ bool m_bMouseIn;
+ bool m_bMouseDown;
+};
+
+#endif // FPDFSDK_FORMFILLER_CFFL_BUTTON_H_
diff --git a/fpdfsdk/formfiller/cffl_checkbox.cpp b/fpdfsdk/formfiller/cffl_checkbox.cpp
index c233c13..e9c72ef 100644
--- a/fpdfsdk/formfiller/cffl_checkbox.cpp
+++ b/fpdfsdk/formfiller/cffl_checkbox.cpp
@@ -9,7 +9,7 @@
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cffl_formfiller.h"
-#include "fpdfsdk/pdfwindow/PWL_SpecialButton.h"
+#include "fpdfsdk/pwl/cpwl_special_button.h"
#include "public/fpdf_fwlevent.h"
CFFL_CheckBox::CFFL_CheckBox(CPDFSDK_FormFillEnvironment* pApp,
@@ -18,9 +18,8 @@
CFFL_CheckBox::~CFFL_CheckBox() {}
-CPWL_Wnd* CFFL_CheckBox::NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) {
- CPWL_CheckBox* pWnd = new CPWL_CheckBox();
+CPWL_Wnd* CFFL_CheckBox::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) {
+ auto* pWnd = new CPWL_CheckBox();
pWnd->Create(cp);
pWnd->SetCheck(m_pWidget->IsChecked());
return pWnd;
@@ -46,24 +45,27 @@
CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
ASSERT(pPageView);
- bool bReset = false;
- bool bExit = false;
- CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget);
- m_pFormFillEnv->GetInteractiveFormFiller()->OnButtonUp(
- &pObserved, pPageView, bReset, bExit, nFlags);
+ CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget.Get());
+ if (m_pFormFillEnv->GetInteractiveFormFiller()->OnButtonUp(
+ &pObserved, pPageView, nFlags)) {
+ if (!pObserved)
+ m_pWidget = nullptr;
+ return true;
+ }
if (!pObserved) {
m_pWidget = nullptr;
return true;
}
- if (bReset || bExit)
- return true;
CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
- if (CPWL_CheckBox* pWnd = (CPWL_CheckBox*)GetPDFWindow(pPageView, true))
- pWnd->SetCheck(!pWnd->IsChecked());
- CommitData(pPageView, nFlags);
- return true;
+ CPWL_CheckBox* pWnd = GetCheckBox(pPageView, true);
+ if (pWnd) {
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot);
+ pWnd->SetCheck(!pWidget->IsChecked());
+ }
+
+ return CommitData(pPageView, nFlags);
}
default:
return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
@@ -76,41 +78,52 @@
const CFX_PointF& point) {
CFFL_Button::OnLButtonUp(pPageView, pAnnot, nFlags, point);
- if (IsValid()) {
- if (CPWL_CheckBox* pWnd = (CPWL_CheckBox*)GetPDFWindow(pPageView, true)) {
- CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
- pWnd->SetCheck(!pWidget->IsChecked());
- }
+ if (!IsValid())
+ return true;
- if (!CommitData(pPageView, nFlags))
- return false;
+ CPWL_CheckBox* pWnd = GetCheckBox(pPageView, true);
+ if (pWnd) {
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot);
+ pWnd->SetCheck(!pWidget->IsChecked());
}
- return true;
+ return CommitData(pPageView, nFlags);
}
bool CFFL_CheckBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
- CPWL_CheckBox* pWnd = (CPWL_CheckBox*)GetPDFWindow(pPageView, false);
+ CPWL_CheckBox* pWnd = GetCheckBox(pPageView, false);
return pWnd && pWnd->IsChecked() != m_pWidget->IsChecked();
}
void CFFL_CheckBox::SaveData(CPDFSDK_PageView* pPageView) {
- if (CPWL_CheckBox* pWnd = (CPWL_CheckBox*)GetPDFWindow(pPageView, false)) {
- bool bNewChecked = pWnd->IsChecked();
+ CPWL_CheckBox* pWnd = GetCheckBox(pPageView, false);
+ if (!pWnd)
+ return;
- if (bNewChecked) {
- CPDF_FormField* pField = m_pWidget->GetFormField();
- for (int32_t i = 0, sz = pField->CountControls(); i < sz; i++) {
- if (CPDF_FormControl* pCtrl = pField->GetControl(i)) {
- if (pCtrl->IsChecked()) {
- break;
- }
+ bool bNewChecked = pWnd->IsChecked();
+ if (bNewChecked) {
+ CPDF_FormField* pField = m_pWidget->GetFormField();
+ for (int32_t i = 0, sz = pField->CountControls(); i < sz; i++) {
+ if (CPDF_FormControl* pCtrl = pField->GetControl(i)) {
+ if (pCtrl->IsChecked()) {
+ break;
}
}
}
-
- m_pWidget->SetCheck(bNewChecked, false);
- m_pWidget->UpdateField();
- SetChangeMark();
}
+ CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get());
+ CFFL_CheckBox::ObservedPtr observed_this(this);
+
+ m_pWidget->SetCheck(bNewChecked, false);
+ if (!observed_widget)
+ return;
+ m_pWidget->UpdateField();
+ if (!observed_widget || !observed_this)
+ return;
+ SetChangeMark();
+}
+
+CPWL_CheckBox* CFFL_CheckBox::GetCheckBox(CPDFSDK_PageView* pPageView,
+ bool bNew) {
+ return static_cast<CPWL_CheckBox*>(GetPDFWindow(pPageView, bNew));
}
diff --git a/fpdfsdk/formfiller/cffl_checkbox.h b/fpdfsdk/formfiller/cffl_checkbox.h
index 79ddc84..8ef3de6 100644
--- a/fpdfsdk/formfiller/cffl_checkbox.h
+++ b/fpdfsdk/formfiller/cffl_checkbox.h
@@ -7,16 +7,17 @@
#ifndef FPDFSDK_FORMFILLER_CFFL_CHECKBOX_H_
#define FPDFSDK_FORMFILLER_CFFL_CHECKBOX_H_
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_button.h"
+
+class CPWL_CheckBox;
class CFFL_CheckBox : public CFFL_Button {
public:
CFFL_CheckBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
~CFFL_CheckBox() override;
- // CFFL_Button
- CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) override;
+ // CFFL_Button:
+ CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override;
bool OnKeyDown(CPDFSDK_Annot* pAnnot,
uint32_t nKeyCode,
uint32_t nFlags) override;
@@ -27,6 +28,9 @@
const CFX_PointF& point) override;
bool IsDataChanged(CPDFSDK_PageView* pPageView) override;
void SaveData(CPDFSDK_PageView* pPageView) override;
+
+ private:
+ CPWL_CheckBox* GetCheckBox(CPDFSDK_PageView* pPageView, bool bNew);
};
#endif // FPDFSDK_FORMFILLER_CFFL_CHECKBOX_H_
diff --git a/fpdfsdk/formfiller/cffl_combobox.cpp b/fpdfsdk/formfiller/cffl_combobox.cpp
index c8438a3..d9b12f5 100644
--- a/fpdfsdk/formfiller/cffl_combobox.cpp
+++ b/fpdfsdk/formfiller/cffl_combobox.cpp
@@ -9,14 +9,14 @@
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cba_fontmap.h"
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
#include "fpdfsdk/fsdk_common.h"
-#include "fpdfsdk/pdfwindow/PWL_ComboBox.h"
+#include "fpdfsdk/pwl/cpwl_combo_box.h"
+#include "third_party/base/ptr_util.h"
CFFL_ComboBox::CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp,
- CPDFSDK_Annot* pAnnot)
- : CFFL_FormFiller(pApp, pAnnot), m_pFontMap(nullptr) {
+ CPDFSDK_Widget* pWidget)
+ : CFFL_TextObject(pApp, pWidget) {
m_State.nIndex = 0;
m_State.nStart = 0;
m_State.nEnd = 0;
@@ -30,28 +30,20 @@
// The font map should be stored somewhere more appropriate so it will live
// until the PWL_Edit is done with it. pdfium:566
DestroyWindows();
- delete m_pFontMap;
}
-PWL_CREATEPARAM CFFL_ComboBox::GetCreateParam() {
- PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
-
- int nFlags = m_pWidget->GetFieldFlags();
- if (nFlags & FIELDFLAG_EDIT) {
+CPWL_Wnd::CreateParams CFFL_ComboBox::GetCreateParam() {
+ CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam();
+ if (m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT)
cp.dwFlags |= PCBS_ALLOWCUSTOMTEXT;
- }
- if (!m_pFontMap)
- m_pFontMap = new CBA_FontMap(m_pWidget, GetSystemHandler());
- cp.pFontMap = m_pFontMap;
+ cp.pFontMap = MaybeCreateFontMap();
cp.pFocusHandler = this;
-
return cp;
}
-CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) {
- CPWL_ComboBox* pWnd = new CPWL_ComboBox();
+CPWL_Wnd* CFFL_ComboBox::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) {
+ auto* pWnd = new CPWL_ComboBox();
pWnd->AttachFFLData(this);
pWnd->Create(cp);
@@ -60,7 +52,7 @@
pWnd->SetFillerNotify(pFormFiller);
int32_t nCurSel = m_pWidget->GetSelectedIndex(0);
- CFX_WideString swText;
+ WideString swText;
if (nCurSel < 0)
swText = m_pWidget->GetValue();
else
@@ -78,7 +70,7 @@
bool CFFL_ComboBox::OnChar(CPDFSDK_Annot* pAnnot,
uint32_t nChar,
uint32_t nFlags) {
- return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
+ return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags);
}
bool CFFL_ComboBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
@@ -102,7 +94,7 @@
if (!pWnd)
return;
- CFX_WideString swText = pWnd->GetText();
+ WideString swText = pWnd->GetText();
int32_t nCurSel = pWnd->GetSelect();
bool bSetValue = false;
@@ -116,11 +108,16 @@
m_pWidget->GetSelectedIndex(0);
m_pWidget->SetOptionSelection(nCurSel, true, false);
}
+ CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get());
+ CFFL_ComboBox::ObservedPtr observed_this(this);
m_pWidget->ResetFieldAppearance(true);
+ if (!observed_widget)
+ return;
m_pWidget->UpdateField();
+ if (!observed_widget || !observed_this)
+ return;
SetChangeMark();
-
m_pWidget->GetPDFPage();
}
@@ -135,7 +132,7 @@
fa.bFieldFull = pEdit->IsTextFull();
int nSelStart = 0;
int nSelEnd = 0;
- pEdit->GetSel(nSelStart, nSelEnd);
+ pEdit->GetSelection(nSelStart, nSelEnd);
fa.nSelEnd = nSelEnd;
fa.nSelStart = nSelStart;
fa.sValue = pEdit->GetText();
@@ -173,7 +170,7 @@
if (CPWL_ComboBox* pComboBox =
static_cast<CPWL_ComboBox*>(GetPDFWindow(pPageView, false))) {
if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
- pEdit->SetSel(fa.nSelStart, fa.nSelEnd);
+ pEdit->SetSelection(fa.nSelStart, fa.nSelEnd);
pEdit->ReplaceSel(fa.sChange);
}
}
@@ -206,7 +203,7 @@
m_State.nIndex = pComboBox->GetSelect();
if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
- pEdit->GetSel(m_State.nStart, m_State.nEnd);
+ pEdit->GetSelection(m_State.nStart, m_State.nEnd);
m_State.sValue = pEdit->GetText();
}
}
@@ -222,33 +219,12 @@
} else {
if (CPWL_Edit* pEdit = pComboBox->GetEdit()) {
pEdit->SetText(m_State.sValue);
- pEdit->SetSel(m_State.nStart, m_State.nEnd);
+ pEdit->SetSelection(m_State.nStart, m_State.nEnd);
}
}
}
}
-CPWL_Wnd* CFFL_ComboBox::ResetPDFWindow(CPDFSDK_PageView* pPageView,
- bool bRestoreValue) {
- if (bRestoreValue)
- SaveState(pPageView);
-
- DestroyPDFWindow(pPageView);
-
- CPWL_Wnd* pRet = nullptr;
-
- if (bRestoreValue) {
- RestoreState(pPageView);
- pRet = GetPDFWindow(pPageView, false);
- } else {
- pRet = GetPDFWindow(pPageView, true);
- }
-
- m_pWidget->UpdateField();
-
- return pRet;
-}
-
#ifdef PDF_ENABLE_XFA
bool CFFL_ComboBox::IsFieldFull(CPDFSDK_PageView* pPageView) {
if (CPWL_ComboBox* pComboBox =
@@ -260,25 +236,19 @@
}
#endif // PDF_ENABLE_XFA
-void CFFL_ComboBox::OnSetFocus(CPWL_Wnd* pWnd) {
- ASSERT(m_pFormFillEnv);
+void CFFL_ComboBox::OnSetFocus(CPWL_Edit* pEdit) {
+ pEdit->SetCharSet(FX_CHARSET_ChineseSimplified);
+ pEdit->SetReadyToInput();
- if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) {
- CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
- pEdit->SetCharSet(FXFONT_GB2312_CHARSET);
- pEdit->SetCodePage(936);
-
- pEdit->SetReadyToInput();
- CFX_WideString wsText = pEdit->GetText();
- int nCharacters = wsText.GetLength();
- CFX_ByteString bsUTFText = wsText.UTF16LE_Encode();
- unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str();
- m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
- }
+ WideString wsText = pEdit->GetText();
+ int nCharacters = wsText.GetLength();
+ ByteString bsUTFText = wsText.UTF16LE_Encode();
+ auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
+ m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
}
-CFX_WideString CFFL_ComboBox::GetSelectExportText() {
- CFX_WideString swRet;
+WideString CFFL_ComboBox::GetSelectExportText() {
+ WideString swRet;
int nExport = -1;
CPDFSDK_PageView* pPageView = GetCurPageView(true);
diff --git a/fpdfsdk/formfiller/cffl_combobox.h b/fpdfsdk/formfiller/cffl_combobox.h
index aab10b9..bdc0934 100644
--- a/fpdfsdk/formfiller/cffl_combobox.h
+++ b/fpdfsdk/formfiller/cffl_combobox.h
@@ -8,7 +8,7 @@
#define FPDFSDK_FORMFILLER_CFFL_COMBOBOX_H_
#include "core/fxcrt/fx_string.h"
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_textobject.h"
class CBA_FontMap;
@@ -16,18 +16,18 @@
int nIndex;
int nStart;
int nEnd;
- CFX_WideString sValue;
+ WideString sValue;
};
-class CFFL_ComboBox : public CFFL_FormFiller, public IPWL_FocusHandler {
+class CFFL_ComboBox : public CFFL_TextObject,
+ public CPWL_Wnd::FocusHandlerIface {
public:
- CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pWidget);
+ CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
~CFFL_ComboBox() override;
- // CFFL_FormFiller:
- PWL_CREATEPARAM GetCreateParam() override;
- CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) override;
+ // CFFL_TextObject:
+ CPWL_Wnd::CreateParams GetCreateParam() override;
+ CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override;
bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
bool IsDataChanged(CPDFSDK_PageView* pPageView) override;
void SaveData(CPDFSDK_PageView* pPageView) override;
@@ -42,21 +42,16 @@
const PDFSDK_FieldAction& faNew) override;
void SaveState(CPDFSDK_PageView* pPageView) override;
void RestoreState(CPDFSDK_PageView* pPageView) override;
- CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
- bool bRestoreValue) override;
-
- // IPWL_FocusHandler:
- void OnSetFocus(CPWL_Wnd* pWnd) override;
-
#ifdef PDF_ENABLE_XFA
- // CFFL_FormFiller:
bool IsFieldFull(CPDFSDK_PageView* pPageView) override;
-#endif // PDF_ENABLE_XFA
+#endif
+
+ // CPWL_Wnd::FocusHandlerIface:
+ void OnSetFocus(CPWL_Edit* pEdit) override;
private:
- CFX_WideString GetSelectExportText();
+ WideString GetSelectExportText();
- CBA_FontMap* m_pFontMap;
FFL_ComboBoxState m_State;
};
diff --git a/fpdfsdk/formfiller/cffl_formfiller.cpp b/fpdfsdk/formfiller/cffl_formfiller.cpp
index da6f920..d3aa37e 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_formfiller.cpp
@@ -6,6 +6,8 @@
#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include <utility>
+
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fxge/cfx_renderdevice.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
@@ -13,18 +15,19 @@
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cba_fontmap.h"
#include "fpdfsdk/fsdk_common.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#define GetRed(rgb) ((uint8_t)(rgb))
-#define GetGreen(rgb) ((uint8_t)(((uint16_t)(rgb)) >> 8))
-#define GetBlue(rgb) ((uint8_t)((rgb) >> 16))
+namespace {
-#define FFL_HINT_ELAPSE 800
+CPDFSDK_Widget* CPDFSDKAnnotToWidget(CPDFSDK_Annot* annot) {
+ return static_cast<CPDFSDK_Widget*>(annot);
+}
+
+} // namespace
CFFL_FormFiller::CFFL_FormFiller(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDFSDK_Annot* pAnnot)
- : m_pFormFillEnv(pFormFillEnv), m_pAnnot(pAnnot), m_bValid(false) {
- m_pWidget = static_cast<CPDFSDK_Widget*>(pAnnot);
+ CPDFSDK_Widget* pWidget)
+ : m_pFormFillEnv(pFormFillEnv), m_pWidget(pWidget), m_bValid(false) {
+ ASSERT(m_pFormFillEnv);
}
CFFL_FormFiller::~CFFL_FormFiller() {
@@ -34,7 +37,7 @@
void CFFL_FormFiller::DestroyWindows() {
for (const auto& it : m_Maps) {
CPWL_Wnd* pWnd = it.second;
- CFFL_PrivateData* pData = (CFFL_PrivateData*)pWnd->GetAttachedData();
+ auto* pData = static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData());
pWnd->InvalidateProvider(this);
pWnd->Destroy();
delete pWnd;
@@ -43,68 +46,53 @@
m_Maps.clear();
}
-void CFFL_FormFiller::SetWindowRect(CPDFSDK_PageView* pPageView,
- const CFX_FloatRect& rcWindow) {
- if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) {
- pWnd->Move(CFX_FloatRect(rcWindow), true, false);
- }
-}
-
-CFX_FloatRect CFFL_FormFiller::GetWindowRect(CPDFSDK_PageView* pPageView) {
- if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) {
- return pWnd->GetWindowRect();
- }
-
- return CFX_FloatRect(0, 0, 0, 0);
-}
-
FX_RECT CFFL_FormFiller::GetViewBBox(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot) {
ASSERT(pPageView);
ASSERT(pAnnot);
CFX_FloatRect rcAnnot = m_pWidget->GetRect();
-
- if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) {
- CFX_FloatRect rcWindow = pWnd->GetWindowRect();
- rcAnnot = PWLtoFFL(rcWindow);
- }
+ if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false))
+ rcAnnot = PWLtoFFL(pWnd->GetWindowRect());
CFX_FloatRect rcWin = rcAnnot;
-
CFX_FloatRect rcFocus = GetFocusBox(pPageView);
if (!rcFocus.IsEmpty())
rcWin.Union(rcFocus);
- CFX_FloatRect rect = CPWL_Utils::InflateRect(rcWin, 1);
-
- return rect.GetOuterRect();
+ if (!rcWin.IsEmpty()) {
+ rcWin.Inflate(1, 1);
+ rcWin.Normalize();
+ }
+ return rcWin.GetOuterRect();
}
void CFFL_FormFiller::OnDraw(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
+ const CFX_Matrix& mtUser2Device) {
ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) {
CFX_Matrix mt = GetCurMatrix();
- mt.Concat(*pUser2Device);
- pWnd->DrawAppearance(pDevice, &mt);
- } else {
- CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
- if (CFFL_InteractiveFormFiller::IsVisible(pWidget))
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal,
- nullptr);
+ mt.Concat(mtUser2Device);
+ pWnd->DrawAppearance(pDevice, mt);
+ return;
}
+
+ CPDFSDK_Widget* pWidget = CPDFSDKAnnotToWidget(pAnnot);
+ if (!CFFL_InteractiveFormFiller::IsVisible(pWidget))
+ return;
+
+ pWidget->DrawAppearance(pDevice, mtUser2Device, CPDF_Annot::Normal, nullptr);
}
void CFFL_FormFiller::OnDrawDeactive(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
+ const CFX_Matrix& mtUser2Device) {
+ CPDFSDKAnnotToWidget(pAnnot)->DrawAppearance(pDevice, mtUser2Device,
+ CPDF_Annot::Normal, nullptr);
}
void CFFL_FormFiller::OnMouseEnter(CPDFSDK_PageView* pPageView,
@@ -120,17 +108,16 @@
CPDFSDK_Annot* pAnnot,
uint32_t nFlags,
const CFX_PointF& point) {
- if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true)) {
- m_bValid = true;
- FX_RECT rect = GetViewBBox(pPageView, pAnnot);
- InvalidateRect(rect);
- if (!rect.Contains(static_cast<int>(point.x), static_cast<int>(point.y)))
- return false;
+ CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true);
+ if (!pWnd)
+ return false;
- return pWnd->OnLButtonDown(WndtoPWL(pPageView, point), nFlags);
- }
-
- return false;
+ m_bValid = true;
+ FX_RECT rect = GetViewBBox(pPageView, pAnnot);
+ InvalidateRect(rect);
+ if (!rect.Contains(static_cast<int>(point.x), static_cast<int>(point.y)))
+ return false;
+ return pWnd->OnLButtonDown(WndtoPWL(pPageView, point), nFlags);
}
bool CFFL_FormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView,
@@ -162,9 +149,6 @@
CPDFSDK_Annot* pAnnot,
uint32_t nFlags,
const CFX_PointF& point) {
- if (m_ptOldPos != point)
- m_ptOldPos = point;
-
CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false);
if (!pWnd)
return false;
@@ -212,31 +196,53 @@
bool CFFL_FormFiller::OnKeyDown(CPDFSDK_Annot* pAnnot,
uint32_t nKeyCode,
uint32_t nFlags) {
- if (IsValid()) {
- CPDFSDK_PageView* pPageView = GetCurPageView(true);
- ASSERT(pPageView);
+ if (!IsValid())
+ return false;
- if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) {
- return pWnd->OnKeyDown(nKeyCode, nFlags);
- }
- }
+ CPDFSDK_PageView* pPageView = GetCurPageView(true);
+ ASSERT(pPageView);
- return false;
+ CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false);
+ return pWnd && pWnd->OnKeyDown(nKeyCode, nFlags);
}
bool CFFL_FormFiller::OnChar(CPDFSDK_Annot* pAnnot,
uint32_t nChar,
uint32_t nFlags) {
- if (IsValid()) {
- CPDFSDK_PageView* pPageView = GetCurPageView(true);
- ASSERT(pPageView);
+ if (!IsValid())
+ return false;
- if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) {
- return pWnd->OnChar(nChar, nFlags);
- }
- }
+ CPDFSDK_PageView* pPageView = GetCurPageView(true);
+ ASSERT(pPageView);
- return false;
+ CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false);
+ return pWnd && pWnd->OnChar(nChar, nFlags);
+}
+
+WideString CFFL_FormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) {
+ if (!IsValid())
+ return WideString();
+
+ CPDFSDK_PageView* pPageView = GetCurPageView(true);
+ ASSERT(pPageView);
+
+ CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false);
+ return pWnd ? pWnd->GetSelectedText() : WideString();
+}
+
+void CFFL_FormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot,
+ const WideString& text) {
+ if (!IsValid())
+ return;
+
+ CPDFSDK_PageView* pPageView = GetCurPageView(true);
+ ASSERT(pPageView);
+
+ CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false);
+ if (!pWnd)
+ return;
+
+ pWnd->ReplaceSelection(text);
}
void CFFL_FormFiller::SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag) {
@@ -255,19 +261,16 @@
return;
CPDFSDK_PageView* pPageView = GetCurPageView(false);
- if (!pPageView)
+ if (!pPageView || !CommitData(pPageView, nFlag))
return;
-
- CommitData(pPageView, nFlag);
-
if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false))
pWnd->KillFocus();
bool bDestroyPDFWindow;
switch (m_pWidget->GetFieldType()) {
- case FIELDTYPE_PUSHBUTTON:
- case FIELDTYPE_CHECKBOX:
- case FIELDTYPE_RADIOBUTTON:
+ case FormFieldType::kPushButton:
+ case FormFieldType::kCheckBox:
+ case FormFieldType::kRadioButton:
bDestroyPDFWindow = true;
break;
default:
@@ -281,36 +284,27 @@
return m_bValid;
}
-PWL_CREATEPARAM CFFL_FormFiller::GetCreateParam() {
- ASSERT(m_pFormFillEnv);
-
- PWL_CREATEPARAM cp;
+CPWL_Wnd::CreateParams CFFL_FormFiller::GetCreateParam() {
+ CPWL_Wnd::CreateParams cp;
cp.pParentWnd = nullptr;
cp.pProvider.Reset(this);
cp.rcRectWnd = GetPDFWindowRect();
uint32_t dwCreateFlags = PWS_BORDER | PWS_BACKGROUND | PWS_VISIBLE;
uint32_t dwFieldFlag = m_pWidget->GetFieldFlags();
- if (dwFieldFlag & FIELDFLAG_READONLY) {
+ if (dwFieldFlag & FIELDFLAG_READONLY)
dwCreateFlags |= PWS_READONLY;
- }
FX_COLORREF color;
- if (m_pWidget->GetFillColor(color)) {
- cp.sBackgroundColor =
- CPWL_Color(GetRed(color), GetGreen(color), GetBlue(color));
- }
+ if (m_pWidget->GetFillColor(color))
+ cp.sBackgroundColor = CFX_Color(color);
+ if (m_pWidget->GetBorderColor(color))
+ cp.sBorderColor = CFX_Color(color);
- if (m_pWidget->GetBorderColor(color)) {
- cp.sBorderColor =
- CPWL_Color(GetRed(color), GetGreen(color), GetBlue(color));
- }
+ cp.sTextColor = CFX_Color(CFX_Color::kGray, 0);
- cp.sTextColor = CPWL_Color(COLORTYPE_GRAY, 0);
-
- if (m_pWidget->GetTextColor(color)) {
- cp.sTextColor = CPWL_Color(GetRed(color), GetGreen(color), GetBlue(color));
- }
+ if (m_pWidget->GetTextColor(color))
+ cp.sTextColor = CFX_Color(color);
cp.fFontSize = m_pWidget->GetFontSize();
cp.dwBorderWidth = m_pWidget->GetBorderWidth();
@@ -321,8 +315,6 @@
cp.sDash = CPWL_Dash(3, 3, 0);
break;
case BorderStyle::BEVELED:
- cp.dwBorderWidth *= 2;
- break;
case BorderStyle::INSET:
cp.dwBorderWidth *= 2;
break;
@@ -348,29 +340,27 @@
if (!bNew)
return pWnd;
- if (found) {
- CFFL_PrivateData* pPrivateData = (CFFL_PrivateData*)pWnd->GetAttachedData();
- if (pPrivateData->nWidgetAge != m_pWidget->GetAppearanceAge()) {
- return ResetPDFWindow(
- pPageView, m_pWidget->GetValueAge() == pPrivateData->nValueAge);
- }
- } else {
- PWL_CREATEPARAM cp = GetCreateParam();
- cp.pAttachedWidget.Reset(m_pWidget);
+ if (!found) {
+ CPWL_Wnd::CreateParams cp = GetCreateParam();
+ cp.pAttachedWidget.Reset(m_pWidget.Get());
- CFFL_PrivateData* pPrivateData = new CFFL_PrivateData;
- pPrivateData->pWidget = m_pWidget;
+ auto* pPrivateData = new CFFL_PrivateData;
+ pPrivateData->pWidget = m_pWidget.Get();
pPrivateData->pPageView = pPageView;
- pPrivateData->nWidgetAge = m_pWidget->GetAppearanceAge();
- pPrivateData->nValueAge = 0;
-
+ pPrivateData->nWidgetAppearanceAge = m_pWidget->GetAppearanceAge();
+ pPrivateData->nWidgetValueAge = 0;
cp.pAttachedData = pPrivateData;
-
- pWnd = NewPDFWindow(cp, pPageView);
- m_Maps[pPageView] = pWnd;
+ CPWL_Wnd* pNewWnd = NewPDFWindow(cp);
+ m_Maps[pPageView] = pNewWnd;
+ return pNewWnd;
}
- return pWnd;
+ auto* pPrivateData = static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData());
+ if (pPrivateData->nWidgetAppearanceAge == m_pWidget->GetAppearanceAge())
+ return pWnd;
+
+ return ResetPDFWindow(
+ pPageView, pPrivateData->nWidgetValueAge == m_pWidget->GetValueAge());
}
void CFFL_FormFiller::DestroyPDFWindow(CPDFSDK_PageView* pPageView) {
@@ -379,39 +369,30 @@
return;
CPWL_Wnd* pWnd = it->second;
- CFFL_PrivateData* pData = (CFFL_PrivateData*)pWnd->GetAttachedData();
+ auto* pData = static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData());
pWnd->Destroy();
delete pWnd;
delete pData;
-
m_Maps.erase(it);
}
-CFX_Matrix CFFL_FormFiller::GetWindowMatrix(void* pAttachedData) {
- if (CFFL_PrivateData* pPrivateData = (CFFL_PrivateData*)pAttachedData) {
- if (pPrivateData->pPageView) {
- CFX_Matrix mtPageView;
- pPrivateData->pPageView->GetCurrentMatrix(mtPageView);
+CFX_Matrix CFFL_FormFiller::GetWindowMatrix(CPWL_Wnd::PrivateData* pAttached) {
+ CFX_Matrix mt;
+ auto* pPrivateData = static_cast<CFFL_PrivateData*>(pAttached);
+ if (!pPrivateData || !pPrivateData->pPageView)
+ return mt;
- CFX_Matrix mt = GetCurMatrix();
- mt.Concat(mtPageView);
-
- return mt;
- }
- }
- return CFX_Matrix(1, 0, 0, 1, 0, 0);
+ CFX_Matrix mtPageView;
+ pPrivateData->pPageView->GetCurrentMatrix(mtPageView);
+ mt = GetCurMatrix();
+ mt.Concat(mtPageView);
+ return mt;
}
CFX_Matrix CFFL_FormFiller::GetCurMatrix() {
CFX_Matrix mt;
-
CFX_FloatRect rcDA = m_pWidget->GetPDFAnnot()->GetRect();
-
switch (m_pWidget->GetRotate()) {
- default:
- case 0:
- mt = CFX_Matrix(1, 0, 0, 1, 0, 0);
- break;
case 90:
mt = CFX_Matrix(0, 1, -1, 0, rcDA.right - rcDA.left, 0);
break;
@@ -422,6 +403,9 @@
case 270:
mt = CFX_Matrix(0, -1, 1, 0, 0, rcDA.top - rcDA.bottom);
break;
+ case 0:
+ default:
+ break;
}
mt.e += rcDA.left;
mt.f += rcDA.bottom;
@@ -429,61 +413,42 @@
return mt;
}
-CFX_WideString CFFL_FormFiller::LoadPopupMenuString(int nIndex) {
- ASSERT(m_pFormFillEnv);
-
- return L"";
-}
-
CFX_FloatRect CFFL_FormFiller::GetPDFWindowRect() const {
CFX_FloatRect rectAnnot = m_pWidget->GetPDFAnnot()->GetRect();
- FX_FLOAT fWidth = rectAnnot.right - rectAnnot.left;
- FX_FLOAT fHeight = rectAnnot.top - rectAnnot.bottom;
+ float fWidth = rectAnnot.right - rectAnnot.left;
+ float fHeight = rectAnnot.top - rectAnnot.bottom;
if ((m_pWidget->GetRotate() / 90) & 0x01)
- return CFX_FloatRect(0, 0, fHeight, fWidth);
-
+ std::swap(fWidth, fHeight);
return CFX_FloatRect(0, 0, fWidth, fHeight);
}
CPDFSDK_PageView* CFFL_FormFiller::GetCurPageView(bool renew) {
- UnderlyingPageType* pPage = m_pAnnot->GetUnderlyingPage();
- return m_pFormFillEnv ? m_pFormFillEnv->GetPageView(pPage, renew) : nullptr;
+ UnderlyingPageType* pPage = m_pWidget->GetUnderlyingPage();
+ return m_pFormFillEnv->GetPageView(pPage, renew);
}
CFX_FloatRect CFFL_FormFiller::GetFocusBox(CPDFSDK_PageView* pPageView) {
- if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false)) {
- CFX_FloatRect rcFocus = FFLtoWnd(pPageView, PWLtoFFL(pWnd->GetFocusRect()));
- CFX_FloatRect rcPage = pPageView->GetPDFPage()->GetPageBBox();
- if (rcPage.Contains(rcFocus))
- return rcFocus;
- }
- return CFX_FloatRect(0, 0, 0, 0);
+ CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false);
+ if (!pWnd)
+ return CFX_FloatRect();
+
+ CFX_FloatRect rcFocus = FFLtoWnd(pPageView, PWLtoFFL(pWnd->GetFocusRect()));
+ return pPageView->GetPDFPage()->GetPageBBox().Contains(rcFocus)
+ ? rcFocus
+ : CFX_FloatRect();
}
CFX_FloatRect CFFL_FormFiller::FFLtoPWL(const CFX_FloatRect& rect) {
- CFX_Matrix mt;
- mt.SetReverse(GetCurMatrix());
-
- CFX_FloatRect temp = rect;
- mt.TransformRect(temp);
-
- return temp;
+ return GetCurMatrix().GetInverse().TransformRect(rect);
}
CFX_FloatRect CFFL_FormFiller::PWLtoFFL(const CFX_FloatRect& rect) {
- CFX_Matrix mt = GetCurMatrix();
-
- CFX_FloatRect temp = rect;
- mt.TransformRect(temp);
-
- return temp;
+ return GetCurMatrix().TransformRect(rect);
}
CFX_PointF CFFL_FormFiller::FFLtoPWL(const CFX_PointF& point) {
- CFX_Matrix mt;
- mt.SetReverse(GetCurMatrix());
- return mt.Transform(point);
+ return GetCurMatrix().GetInverse().Transform(point);
}
CFX_PointF CFFL_FormFiller::PWLtoFFL(const CFX_PointF& point) {
@@ -501,33 +466,43 @@
}
bool CFFL_FormFiller::CommitData(CPDFSDK_PageView* pPageView, uint32_t nFlag) {
- if (IsDataChanged(pPageView)) {
- bool bRC = true;
- bool bExit = false;
- CFFL_InteractiveFormFiller* pFormFiller =
- m_pFormFillEnv->GetInteractiveFormFiller();
- CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget);
- pFormFiller->OnKeyStrokeCommit(&pObserved, pPageView, bRC, bExit, nFlag);
- if (!pObserved || bExit)
- return true;
- if (!bRC) {
- ResetPDFWindow(pPageView, false);
- return true;
- }
- pFormFiller->OnValidate(&pObserved, pPageView, bRC, bExit, nFlag);
- if (!pObserved || bExit)
- return true;
- if (!bRC) {
- ResetPDFWindow(pPageView, false);
- return true;
- }
- SaveData(pPageView);
- pFormFiller->OnCalculate(m_pWidget, pPageView, bExit, nFlag);
- if (bExit)
- return true;
+ if (!IsDataChanged(pPageView))
+ return true;
- pFormFiller->OnFormat(m_pWidget, pPageView, bExit, nFlag);
+ CFFL_InteractiveFormFiller* pFormFiller =
+ m_pFormFillEnv->GetInteractiveFormFiller();
+ CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget.Get());
+
+ if (!pFormFiller->OnKeyStrokeCommit(&pObserved, pPageView, nFlag)) {
+ if (!pObserved)
+ return false;
+ ResetPDFWindow(pPageView, false);
+ return true;
}
+ if (!pObserved)
+ return false;
+
+ if (!pFormFiller->OnValidate(&pObserved, pPageView, nFlag)) {
+ if (!pObserved)
+ return false;
+ ResetPDFWindow(pPageView, false);
+ return true;
+ }
+ if (!pObserved)
+ return false;
+
+ SaveData(pPageView); // may invoking JS to delete this widget.
+ if (!pObserved)
+ return false;
+
+ pFormFiller->OnCalculate(&pObserved, pPageView, nFlag);
+ if (!pObserved)
+ return false;
+
+ pFormFiller->OnFormat(&pObserved, pPageView, nFlag);
+ if (!pObserved)
+ return false;
+
return true;
}
@@ -582,7 +557,7 @@
bool bDestroyPDFWindow) {
m_bValid = false;
- InvalidateRect(GetViewBBox(pPageView, m_pWidget));
+ InvalidateRect(GetViewBBox(pPageView, m_pWidget.Get()));
if (bDestroyPDFWindow)
DestroyPDFWindow(pPageView);
}
@@ -590,98 +565,3 @@
void CFFL_FormFiller::InvalidateRect(const FX_RECT& rect) {
m_pFormFillEnv->Invalidate(m_pWidget->GetUnderlyingPage(), rect);
}
-
-CFFL_Button::CFFL_Button(CPDFSDK_FormFillEnvironment* pApp,
- CPDFSDK_Annot* pWidget)
- : CFFL_FormFiller(pApp, pWidget), m_bMouseIn(false), m_bMouseDown(false) {}
-
-CFFL_Button::~CFFL_Button() {}
-
-void CFFL_Button::OnMouseEnter(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot) {
- m_bMouseIn = true;
- InvalidateRect(GetViewBBox(pPageView, pAnnot));
-}
-
-void CFFL_Button::OnMouseExit(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot) {
- m_bMouseIn = false;
-
- InvalidateRect(GetViewBBox(pPageView, pAnnot));
- EndTimer();
- ASSERT(m_pWidget);
-}
-
-bool CFFL_Button::OnLButtonDown(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- uint32_t nFlags,
- const CFX_PointF& point) {
- if (!pAnnot->GetRect().Contains(point))
- return false;
-
- m_bMouseDown = true;
- m_bValid = true;
- InvalidateRect(GetViewBBox(pPageView, pAnnot));
- return true;
-}
-
-bool CFFL_Button::OnLButtonUp(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- uint32_t nFlags,
- const CFX_PointF& point) {
- if (!pAnnot->GetRect().Contains(point))
- return false;
-
- m_bMouseDown = false;
- m_pWidget->GetPDFPage();
-
- InvalidateRect(GetViewBBox(pPageView, pAnnot));
- return true;
-}
-
-bool CFFL_Button::OnMouseMove(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- uint32_t nFlags,
- const CFX_PointF& point) {
- ASSERT(m_pFormFillEnv);
- return true;
-}
-
-void CFFL_Button::OnDraw(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- ASSERT(pPageView);
- CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
- CPDF_FormControl* pCtrl = pWidget->GetFormControl();
- CPDF_FormControl::HighlightingMode eHM = pCtrl->GetHighlightingMode();
-
- if (eHM != CPDF_FormControl::Push) {
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
- return;
- }
-
- if (m_bMouseDown) {
- if (pWidget->IsWidgetAppearanceValid(CPDF_Annot::Down))
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Down, nullptr);
- else
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal,
- nullptr);
- } else if (m_bMouseIn) {
- if (pWidget->IsWidgetAppearanceValid(CPDF_Annot::Rollover))
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Rollover,
- nullptr);
- else
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal,
- nullptr);
- } else {
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
- }
-}
-
-void CFFL_Button::OnDrawDeactive(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- OnDraw(pPageView, pAnnot, pDevice, pUser2Device);
-}
diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h
index c6b1e59..11a2f8c 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.h
+++ b/fpdfsdk/formfiller/cffl_formfiller.h
@@ -9,6 +9,7 @@
#include <map>
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/formfiller/cba_fontmap.h"
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
#include "fpdfsdk/pdfsdk_fieldaction.h"
@@ -18,10 +19,11 @@
class CPDFSDK_PageView;
class CPDFSDK_Widget;
-class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler {
+class CFFL_FormFiller : public CPWL_Wnd::ProviderIface,
+ public CPWL_TimerHandler {
public:
CFFL_FormFiller(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDFSDK_Annot* pAnnot);
+ CPDFSDK_Widget* pWidget);
~CFFL_FormFiller() override;
virtual FX_RECT GetViewBBox(CPDFSDK_PageView* pPageView,
@@ -29,11 +31,11 @@
virtual void OnDraw(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device);
+ const CFX_Matrix& mtUser2Device);
virtual void OnDrawDeactive(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device);
+ const CFX_Matrix& mtUser2Device);
virtual void OnMouseEnter(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot);
virtual void OnMouseExit(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot);
@@ -73,6 +75,9 @@
uint32_t nFlags);
virtual bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags);
+ WideString GetSelectedText(CPDFSDK_Annot* pAnnot);
+ void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text);
+
void SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag);
void KillFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag);
@@ -80,9 +85,8 @@
void TimerProc() override;
CFX_SystemHandler* GetSystemHandler() const override;
- // IPWL_Provider
- CFX_Matrix GetWindowMatrix(void* pAttachedData) override;
- CFX_WideString LoadPopupMenuString(int nIndex) override;
+ // CPWL_Wnd::ProviderIface:
+ CFX_Matrix GetWindowMatrix(CPWL_Wnd::PrivateData* pAttached) override;
virtual void GetActionData(CPDFSDK_PageView* pPageView,
CPDF_AAction::AActionType type,
@@ -111,10 +115,6 @@
CFX_FloatRect FFLtoWnd(CPDFSDK_PageView* pPageView,
const CFX_FloatRect& rect);
- void SetWindowRect(CPDFSDK_PageView* pPageView,
- const CFX_FloatRect& rcWindow);
- CFX_FloatRect GetWindowRect(CPDFSDK_PageView* pPageView);
-
bool CommitData(CPDFSDK_PageView* pPageView, uint32_t nFlag);
virtual bool IsDataChanged(CPDFSDK_PageView* pPageView);
virtual void SaveData(CPDFSDK_PageView* pPageView);
@@ -127,9 +127,8 @@
void DestroyPDFWindow(CPDFSDK_PageView* pPageView);
void EscapeFiller(CPDFSDK_PageView* pPageView, bool bDestroyPDFWindow);
- virtual PWL_CREATEPARAM GetCreateParam();
- virtual CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) = 0;
+ virtual CPWL_Wnd::CreateParams GetCreateParam();
+ virtual CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) = 0;
virtual CFX_FloatRect GetFocusBox(CPDFSDK_PageView* pPageView);
bool IsValid() const;
@@ -138,8 +137,7 @@
CPDFSDK_PageView* GetCurPageView(bool renew);
void SetChangeMark();
- virtual void InvalidateRect(const FX_RECT& rect);
- CPDFSDK_Annot* GetSDKAnnot() { return m_pAnnot; }
+ CPDFSDK_Annot* GetSDKAnnot() { return m_pWidget.Get(); }
protected:
using CFFL_PageView2PDFWindow = std::map<CPDFSDK_PageView*, CPWL_Wnd*>;
@@ -152,48 +150,12 @@
// until the PWL_Edit is done with it. pdfium:566
void DestroyWindows();
- CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
- CPDFSDK_Widget* m_pWidget;
- CPDFSDK_Annot* m_pAnnot;
+ void InvalidateRect(const FX_RECT& rect);
+
+ UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
+ UnownedPtr<CPDFSDK_Widget> m_pWidget;
bool m_bValid;
CFFL_PageView2PDFWindow m_Maps;
- CFX_PointF m_ptOldPos;
-};
-
-class CFFL_Button : public CFFL_FormFiller {
- public:
- CFFL_Button(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDFSDK_Annot* pWidget);
- ~CFFL_Button() override;
-
- // CFFL_FormFiller
- void OnMouseEnter(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot) override;
- void OnMouseExit(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override;
- bool OnLButtonDown(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- uint32_t nFlags,
- const CFX_PointF& point) override;
- bool OnLButtonUp(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- uint32_t nFlags,
- const CFX_PointF& point) override;
- bool OnMouseMove(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- uint32_t nFlags,
- const CFX_PointF& point) override;
- void OnDraw(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
- void OnDrawDeactive(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
-
- protected:
- bool m_bMouseIn;
- bool m_bMouseDown;
};
#endif // FPDFSDK_FORMFILLER_CFFL_FORMFILLER_H_
diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
index a830d52..e74f902 100644
--- a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
@@ -8,6 +8,7 @@
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fxcrt/autorestorer.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_pathdata.h"
#include "core/fxge/cfx_renderdevice.h"
@@ -22,9 +23,7 @@
#include "fpdfsdk/formfiller/cffl_pushbutton.h"
#include "fpdfsdk/formfiller/cffl_radiobutton.h"
#include "fpdfsdk/formfiller/cffl_textfield.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-
-#define FFL_MAXLISTBOXHEIGHT 140.0f
+#include "third_party/base/stl_util.h"
CFFL_InteractiveFormFiller::CFFL_InteractiveFormFiller(
CPDFSDK_FormFillEnvironment* pFormFillEnv)
@@ -46,7 +45,11 @@
ASSERT(pPageView);
CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot();
- CFX_FloatRect rcWin = CPWL_Utils::InflateRect(pPDFAnnot->GetRect(), 1);
+ CFX_FloatRect rcWin = pPDFAnnot->GetRect();
+ if (!rcWin.IsEmpty()) {
+ rcWin.Inflate(1, 1);
+ rcWin.Normalize();
+ }
return rcWin.GetOuterRect();
}
@@ -55,48 +58,50 @@
CFX_RenderDevice* pDevice,
CFX_Matrix* pUser2Device) {
ASSERT(pPageView);
- CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
-
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot);
if (!IsVisible(pWidget))
return;
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false)) {
- if (pFormFiller->IsValid()) {
- pFormFiller->OnDraw(pPageView, pAnnot, pDevice, pUser2Device);
- pAnnot->GetPDFPage();
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
+ if (pFormFiller && pFormFiller->IsValid()) {
+ pFormFiller->OnDraw(pPageView, pAnnot, pDevice, *pUser2Device);
+ pAnnot->GetPDFPage();
- if (m_pFormFillEnv->GetFocusAnnot() == pAnnot) {
- CFX_FloatRect rcFocus = pFormFiller->GetFocusBox(pPageView);
- if (!rcFocus.IsEmpty()) {
- CFX_PathData path;
- path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top),
- FXPT_TYPE::MoveTo, false);
- path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.bottom),
- FXPT_TYPE::LineTo, false);
- path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.bottom),
- FXPT_TYPE::LineTo, false);
- path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.top),
- FXPT_TYPE::LineTo, false);
- path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top),
- FXPT_TYPE::LineTo, false);
-
- CFX_GraphStateData gsd;
- gsd.SetDashCount(1);
- gsd.m_DashArray[0] = 1.0f;
- gsd.m_DashPhase = 0;
- gsd.m_LineWidth = 1.0f;
- pDevice->DrawPath(&path, pUser2Device, &gsd, 0,
- ArgbEncode(255, 0, 0, 0), FXFILL_ALTERNATE);
- }
- }
+ if (m_pFormFillEnv->GetFocusAnnot() != pAnnot)
return;
- }
+
+ CFX_FloatRect rcFocus = pFormFiller->GetFocusBox(pPageView);
+ if (rcFocus.IsEmpty())
+ return;
+
+ CFX_PathData path;
+ path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), FXPT_TYPE::MoveTo,
+ false);
+ path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.bottom),
+ FXPT_TYPE::LineTo, false);
+ path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.bottom),
+ FXPT_TYPE::LineTo, false);
+ path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.top), FXPT_TYPE::LineTo,
+ false);
+ path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), FXPT_TYPE::LineTo,
+ false);
+
+ CFX_GraphStateData gsd;
+ gsd.SetDashCount(1);
+ gsd.m_DashArray[0] = 1.0f;
+ gsd.m_DashPhase = 0;
+ gsd.m_LineWidth = 1.0f;
+ pDevice->DrawPath(&path, pUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0),
+ FXFILL_ALTERNATE);
+ return;
}
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false)) {
- pFormFiller->OnDrawDeactive(pPageView, pAnnot, pDevice, pUser2Device);
+ pFormFiller = GetFormFiller(pAnnot, false);
+ if (pFormFiller) {
+ pFormFiller->OnDrawDeactive(pPageView, pAnnot, pDevice, *pUser2Device);
} else {
- pWidget->DrawAppearance(pDevice, pUser2Device, CPDF_Annot::Normal, nullptr);
+ pWidget->DrawAppearance(pDevice, *pUser2Device, CPDF_Annot::Normal,
+ nullptr);
}
if (!IsReadOnly(pWidget) && IsFillingAllowed(pWidget))
@@ -117,13 +122,13 @@
if (pWidget->GetAAction(CPDF_AAction::CursorEnter).GetDict()) {
m_bNotifying = true;
- int nValueAge = pWidget->GetValueAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
pWidget->ClearAppModified();
ASSERT(pPageView);
PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
pWidget->OnAAction(CPDF_AAction::CursorEnter, fa, pPageView);
m_bNotifying = false;
if (!(*pAnnot))
@@ -149,15 +154,14 @@
CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
if (pWidget->GetAAction(CPDF_AAction::CursorExit).GetDict()) {
m_bNotifying = true;
- pWidget->GetAppearanceAge();
- int nValueAge = pWidget->GetValueAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
pWidget->ClearAppModified();
ASSERT(pPageView);
PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
pWidget->OnAAction(CPDF_AAction::CursorExit, fa, pPageView);
m_bNotifying = false;
if (!(*pAnnot))
@@ -186,15 +190,14 @@
if (Annot_HitTest(pPageView, pAnnot->Get(), point) &&
pWidget->GetAAction(CPDF_AAction::ButtonDown).GetDict()) {
m_bNotifying = true;
- pWidget->GetAppearanceAge();
- int nValueAge = pWidget->GetValueAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
pWidget->ClearAppModified();
ASSERT(pPageView);
PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlags);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlags);
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlags);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlags);
pWidget->OnAAction(CPDF_AAction::ButtonDown, fa, pPageView);
m_bNotifying = false;
if (!(*pAnnot))
@@ -211,10 +214,9 @@
}
}
}
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false))
- return pFormFiller->OnLButtonDown(pPageView, pAnnot->Get(), nFlags, point);
-
- return false;
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
+ return pFormFiller &&
+ pFormFiller->OnLButtonDown(pPageView, pAnnot->Get(), nFlags, point);
}
bool CFFL_InteractiveFormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView,
@@ -224,70 +226,67 @@
ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ bool bSetFocus;
switch (pWidget->GetFieldType()) {
- case FIELDTYPE_PUSHBUTTON:
- case FIELDTYPE_CHECKBOX:
- case FIELDTYPE_RADIOBUTTON:
- if (GetViewBBox(pPageView, pAnnot->Get())
- .Contains((int)point.x, (int)point.y))
- m_pFormFillEnv->SetFocusAnnot(pAnnot);
+ case FormFieldType::kPushButton:
+ case FormFieldType::kCheckBox:
+ case FormFieldType::kRadioButton: {
+ FX_RECT bbox = GetViewBBox(pPageView, pAnnot->Get());
+ bSetFocus =
+ bbox.Contains(static_cast<int>(point.x), static_cast<int>(point.y));
break;
+ }
default:
- m_pFormFillEnv->SetFocusAnnot(pAnnot);
+ bSetFocus = true;
break;
}
+ if (bSetFocus)
+ m_pFormFillEnv->SetFocusAnnot(pAnnot);
- bool bRet = false;
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false))
- bRet = pFormFiller->OnLButtonUp(pPageView, pAnnot->Get(), nFlags, point);
-
- if (m_pFormFillEnv->GetFocusAnnot() == pAnnot->Get()) {
- bool bExit = false;
- bool bReset = false;
- OnButtonUp(pAnnot, pPageView, bReset, bExit, nFlags);
- if (!pAnnot || bExit)
- return true;
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
+ bool bRet = pFormFiller &&
+ pFormFiller->OnLButtonUp(pPageView, pAnnot->Get(), nFlags, point);
+ if (m_pFormFillEnv->GetFocusAnnot() != pAnnot->Get())
+ return bRet;
+ if (OnButtonUp(pAnnot, pPageView, nFlags) || !pAnnot)
+ return true;
#ifdef PDF_ENABLE_XFA
- OnClick(pWidget, pPageView, bReset, bExit, nFlags);
- if (!pAnnot || bExit)
- return true;
+ if (OnClick(pAnnot, pPageView, nFlags) || !pAnnot)
+ return true;
#endif // PDF_ENABLE_XFA
- }
return bRet;
}
-void CFFL_InteractiveFormFiller::OnButtonUp(CPDFSDK_Annot::ObservedPtr* pAnnot,
+bool CFFL_InteractiveFormFiller::OnButtonUp(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
- if (pWidget->GetAAction(CPDF_AAction::ButtonUp).GetDict()) {
- m_bNotifying = true;
+ if (m_bNotifying)
+ return false;
- int nAge = pWidget->GetAppearanceAge();
- int nValueAge = pWidget->GetValueAge();
- ASSERT(pPageView);
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (!pWidget->GetAAction(CPDF_AAction::ButtonUp).GetDict())
+ return false;
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
- pWidget->OnAAction(CPDF_AAction::ButtonUp, fa, pPageView);
- m_bNotifying = false;
- if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget)) {
- bExit = true;
- return;
- }
- if (nAge != pWidget->GetAppearanceAge()) {
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) {
- pFormFiller->ResetPDFWindow(pPageView,
- nValueAge == pWidget->GetValueAge());
- }
- bReset = true;
- }
- }
- }
+ m_bNotifying = true;
+
+ uint32_t nAge = pWidget->GetAppearanceAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
+ ASSERT(pPageView);
+
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
+ pWidget->OnAAction(CPDF_AAction::ButtonUp, fa, pPageView);
+ m_bNotifying = false;
+ if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
+ return true;
+ if (nAge == pWidget->GetAppearanceAge())
+ return false;
+
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
+ if (pFormFiller)
+ pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
+ return true;
}
bool CFFL_InteractiveFormFiller::OnLButtonDblClk(
@@ -350,11 +349,8 @@
uint32_t nFlags) {
ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false)) {
- return pFormFiller->OnKeyDown(pAnnot, nKeyCode, nFlags);
- }
-
- return false;
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
+ return pFormFiller && pFormFiller->OnKeyDown(pAnnot, nKeyCode, nFlags);
}
bool CFFL_InteractiveFormFiller::OnChar(CPDFSDK_Annot* pAnnot,
@@ -364,10 +360,8 @@
if (nChar == FWL_VKEY_Tab)
return true;
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false))
- return pFormFiller->OnChar(pAnnot, nChar, nFlags);
-
- return false;
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
+ return pFormFiller && pFormFiller->OnChar(pAnnot, nChar, nFlags);
}
bool CFFL_InteractiveFormFiller::OnSetFocus(CPDFSDK_Annot::ObservedPtr* pAnnot,
@@ -380,9 +374,8 @@
CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
if (pWidget->GetAAction(CPDF_AAction::GetFocus).GetDict()) {
m_bNotifying = true;
- pWidget->GetAppearanceAge();
- int nValueAge = pWidget->GetValueAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
pWidget->ClearAppModified();
CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, true);
@@ -393,8 +386,8 @@
ASSERT(pPageView);
PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
pFormFiller->GetActionData(pPageView, CPDF_AAction::GetFocus, fa);
pWidget->OnAAction(CPDF_AAction::GetFocus, fa, pPageView);
m_bNotifying = false;
@@ -422,29 +415,34 @@
return false;
ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false)) {
- pFormFiller->KillFocusForAnnot(pAnnot->Get(), nFlag);
- if (!m_bNotifying) {
- CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
- if (pWidget->GetAAction(CPDF_AAction::LoseFocus).GetDict()) {
- m_bNotifying = true;
- pWidget->ClearAppModified();
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
+ if (!pFormFiller)
+ return true;
- CPDFSDK_PageView* pPageView = pWidget->GetPageView();
- ASSERT(pPageView);
+ pFormFiller->KillFocusForAnnot(pAnnot->Get(), nFlag);
+ if (!(*pAnnot))
+ return false;
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
- pFormFiller->GetActionData(pPageView, CPDF_AAction::LoseFocus, fa);
- pWidget->OnAAction(CPDF_AAction::LoseFocus, fa, pPageView);
- m_bNotifying = false;
- if (!(*pAnnot))
- return false;
- }
- }
- }
- return true;
+ if (m_bNotifying)
+ return true;
+
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (!pWidget->GetAAction(CPDF_AAction::LoseFocus).GetDict())
+ return true;
+
+ m_bNotifying = true;
+ pWidget->ClearAppModified();
+
+ CPDFSDK_PageView* pPageView = pWidget->GetPageView();
+ ASSERT(pPageView);
+
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
+ pFormFiller->GetActionData(pPageView, CPDF_AAction::LoseFocus, fa);
+ pWidget->OnAAction(CPDF_AAction::LoseFocus, fa, pPageView);
+ m_bNotifying = false;
+ return !!(*pAnnot);
}
bool CFFL_InteractiveFormFiller::IsVisible(CPDFSDK_Widget* pWidget) {
@@ -457,12 +455,11 @@
}
bool CFFL_InteractiveFormFiller::IsFillingAllowed(CPDFSDK_Widget* pWidget) {
- if (pWidget->GetFieldType() == FIELDTYPE_PUSHBUTTON)
- return true;
+ if (pWidget->GetFieldType() == FormFieldType::kPushButton)
+ return false;
CPDF_Page* pPage = pWidget->GetPDFPage();
- CPDF_Document* pDocument = pPage->m_pDocument;
- uint32_t dwPermissions = pDocument->GetUserPermissions();
+ uint32_t dwPermissions = pPage->m_pDocument->GetUserPermissions();
return (dwPermissions & FPDFPERM_FILL_FORM) ||
(dwPermissions & FPDFPERM_ANNOT_FORM) ||
(dwPermissions & FPDFPERM_MODIFY);
@@ -478,29 +475,30 @@
if (!bRegister)
return nullptr;
- CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot;
- int nFieldType = pWidget->GetFieldType();
+ // TODO(thestig): How do we know |pAnnot| is a CPDFSDK_Widget?
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot);
+ FormFieldType fieldType = pWidget->GetFieldType();
CFFL_FormFiller* pFormFiller;
- switch (nFieldType) {
- case FIELDTYPE_PUSHBUTTON:
- pFormFiller = new CFFL_PushButton(m_pFormFillEnv, pWidget);
+ switch (fieldType) {
+ case FormFieldType::kPushButton:
+ pFormFiller = new CFFL_PushButton(m_pFormFillEnv.Get(), pWidget);
break;
- case FIELDTYPE_CHECKBOX:
- pFormFiller = new CFFL_CheckBox(m_pFormFillEnv, pWidget);
+ case FormFieldType::kCheckBox:
+ pFormFiller = new CFFL_CheckBox(m_pFormFillEnv.Get(), pWidget);
break;
- case FIELDTYPE_RADIOBUTTON:
- pFormFiller = new CFFL_RadioButton(m_pFormFillEnv, pWidget);
+ case FormFieldType::kRadioButton:
+ pFormFiller = new CFFL_RadioButton(m_pFormFillEnv.Get(), pWidget);
break;
- case FIELDTYPE_TEXTFIELD:
- pFormFiller = new CFFL_TextField(m_pFormFillEnv, pWidget);
+ case FormFieldType::kTextField:
+ pFormFiller = new CFFL_TextField(m_pFormFillEnv.Get(), pWidget);
break;
- case FIELDTYPE_LISTBOX:
- pFormFiller = new CFFL_ListBox(m_pFormFillEnv, pWidget);
+ case FormFieldType::kListBox:
+ pFormFiller = new CFFL_ListBox(m_pFormFillEnv.Get(), pWidget);
break;
- case FIELDTYPE_COMBOBOX:
- pFormFiller = new CFFL_ComboBox(m_pFormFillEnv, pWidget);
+ case FormFieldType::kComboBox:
+ pFormFiller = new CFFL_ComboBox(m_pFormFillEnv.Get(), pWidget);
break;
- case FIELDTYPE_UNKNOWN:
+ case FormFieldType::kUnknown:
default:
pFormFiller = nullptr;
break;
@@ -513,9 +511,20 @@
return pFormFiller;
}
-void CFFL_InteractiveFormFiller::RemoveFormFiller(CPDFSDK_Annot* pAnnot) {
- if (pAnnot)
- UnRegisterFormFiller(pAnnot);
+WideString CFFL_InteractiveFormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) {
+ ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
+ return pFormFiller ? pFormFiller->GetSelectedText(pAnnot) : WideString();
+}
+
+void CFFL_InteractiveFormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot,
+ const WideString& text) {
+ ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
+ if (!pFormFiller)
+ return;
+
+ pFormFiller->ReplaceSelection(pAnnot, text);
}
void CFFL_InteractiveFormFiller::UnRegisterFormFiller(CPDFSDK_Annot* pAnnot) {
@@ -526,24 +535,22 @@
m_Maps.erase(it);
}
-void CFFL_InteractiveFormFiller::QueryWherePopup(void* pPrivateData,
- FX_FLOAT fPopupMin,
- FX_FLOAT fPopupMax,
- int32_t& nRet,
- FX_FLOAT& fPopupRet) {
- CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData;
+void CFFL_InteractiveFormFiller::QueryWherePopup(
+ CPWL_Wnd::PrivateData* pAttached,
+ float fPopupMin,
+ float fPopupMax,
+ bool* bBottom,
+ float* fPopupRet) {
+ auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
+ CPDFSDK_Widget* pWidget = pData->pWidget;
+ CPDF_Page* pPage = pWidget->GetPDFPage();
- CFX_FloatRect rcPageView(0, 0, 0, 0);
- rcPageView.right = pData->pWidget->GetPDFPage()->GetPageWidth();
- rcPageView.bottom = pData->pWidget->GetPDFPage()->GetPageHeight();
+ CFX_FloatRect rcPageView(0, pPage->GetPageHeight(), pPage->GetPageWidth(), 0);
rcPageView.Normalize();
- CFX_FloatRect rcAnnot = pData->pWidget->GetRect();
-
- FX_FLOAT fTop = 0.0f;
- FX_FLOAT fBottom = 0.0f;
-
- CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pData->pWidget;
+ CFX_FloatRect rcAnnot = pWidget->GetRect();
+ float fTop = 0.0f;
+ float fBottom = 0.0f;
switch (pWidget->GetRotate() / 90) {
default:
case 0:
@@ -564,308 +571,276 @@
break;
}
- FX_FLOAT fFactHeight = 0;
- bool bBottom = true;
- FX_FLOAT fMaxListBoxHeight = 0;
- if (fPopupMax > FFL_MAXLISTBOXHEIGHT) {
- if (fPopupMin > FFL_MAXLISTBOXHEIGHT) {
- fMaxListBoxHeight = fPopupMin;
- } else {
- fMaxListBoxHeight = FFL_MAXLISTBOXHEIGHT;
- }
- } else {
- fMaxListBoxHeight = fPopupMax;
- }
+ constexpr float kMaxListBoxHeight = 140;
+ const float fMaxListBoxHeight =
+ pdfium::clamp(kMaxListBoxHeight, fPopupMin, fPopupMax);
if (fBottom > fMaxListBoxHeight) {
- fFactHeight = fMaxListBoxHeight;
- bBottom = true;
- } else {
- if (fTop > fMaxListBoxHeight) {
- fFactHeight = fMaxListBoxHeight;
- bBottom = false;
- } else {
- if (fTop > fBottom) {
- fFactHeight = fTop;
- bBottom = false;
- } else {
- fFactHeight = fBottom;
- bBottom = true;
- }
- }
+ *fPopupRet = fMaxListBoxHeight;
+ *bBottom = true;
+ return;
}
- nRet = bBottom ? 0 : 1;
- fPopupRet = fFactHeight;
+ if (fTop > fMaxListBoxHeight) {
+ *fPopupRet = fMaxListBoxHeight;
+ *bBottom = false;
+ return;
+ }
+
+ if (fTop > fBottom) {
+ *fPopupRet = fTop;
+ *bBottom = false;
+ } else {
+ *fPopupRet = fBottom;
+ *bBottom = true;
+ }
}
-void CFFL_InteractiveFormFiller::OnKeyStrokeCommit(
+bool CFFL_InteractiveFormFiller::OnKeyStrokeCommit(
CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bRC,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
- if (pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) {
- ASSERT(pPageView);
- m_bNotifying = true;
- pWidget->ClearAppModified();
+ if (m_bNotifying)
+ return true;
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
- fa.bWillCommit = true;
- fa.bKeyDown = true;
- fa.bRC = true;
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (!pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict())
+ return true;
- CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
- pFormFiller->GetActionData(pPageView, CPDF_AAction::KeyStroke, fa);
- pFormFiller->SaveState(pPageView);
- pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, pPageView);
- if (!(*pAnnot))
- return;
+ ASSERT(pPageView);
+ m_bNotifying = true;
+ pWidget->ClearAppModified();
- bRC = fa.bRC;
- m_bNotifying = false;
- }
- }
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
+ fa.bWillCommit = true;
+ fa.bKeyDown = true;
+ fa.bRC = true;
+
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
+ pFormFiller->GetActionData(pPageView, CPDF_AAction::KeyStroke, fa);
+ pFormFiller->SaveState(pPageView);
+ pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, pPageView);
+ if (!(*pAnnot))
+ return true;
+
+ m_bNotifying = false;
+ return fa.bRC;
}
-void CFFL_InteractiveFormFiller::OnValidate(CPDFSDK_Annot::ObservedPtr* pAnnot,
+bool CFFL_InteractiveFormFiller::OnValidate(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bRC,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
- if (pWidget->GetAAction(CPDF_AAction::Validate).GetDict()) {
- ASSERT(pPageView);
- m_bNotifying = true;
- pWidget->ClearAppModified();
+ if (m_bNotifying)
+ return true;
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
- fa.bKeyDown = true;
- fa.bRC = true;
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (!pWidget->GetAAction(CPDF_AAction::Validate).GetDict())
+ return true;
- CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
- pFormFiller->GetActionData(pPageView, CPDF_AAction::Validate, fa);
- pFormFiller->SaveState(pPageView);
- pWidget->OnAAction(CPDF_AAction::Validate, fa, pPageView);
- if (!(*pAnnot))
- return;
+ ASSERT(pPageView);
+ m_bNotifying = true;
+ pWidget->ClearAppModified();
- bRC = fa.bRC;
- m_bNotifying = false;
- }
- }
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
+ fa.bKeyDown = true;
+ fa.bRC = true;
+
+ CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
+ pFormFiller->GetActionData(pPageView, CPDF_AAction::Validate, fa);
+ pFormFiller->SaveState(pPageView);
+ pWidget->OnAAction(CPDF_AAction::Validate, fa, pPageView);
+ if (!(*pAnnot))
+ return true;
+
+ m_bNotifying = false;
+ return fa.bRC;
}
-void CFFL_InteractiveFormFiller::OnCalculate(CPDFSDK_Widget* pWidget,
+void CFFL_InteractiveFormFiller::OnCalculate(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- ASSERT(pWidget);
+ if (m_bNotifying)
+ return;
+
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (pWidget) {
CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm();
pInterForm->OnCalculate(pWidget->GetFormField());
- m_bNotifying = false;
}
+ m_bNotifying = false;
}
-void CFFL_InteractiveFormFiller::OnFormat(CPDFSDK_Widget* pWidget,
+void CFFL_InteractiveFormFiller::OnFormat(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- ASSERT(pWidget);
- CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm();
+ if (m_bNotifying)
+ return;
- bool bFormatted = false;
- CFX_WideString sValue =
- pInterForm->OnFormat(pWidget->GetFormField(), bFormatted);
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ ASSERT(pWidget);
+ CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm();
- if (bExit)
- return;
+ bool bFormatted = false;
+ WideString sValue = pInterForm->OnFormat(pWidget->GetFormField(), bFormatted);
+ if (!(*pAnnot))
+ return;
- if (bFormatted) {
- pInterForm->ResetFieldAppearance(pWidget->GetFormField(), &sValue, true);
- pInterForm->UpdateField(pWidget->GetFormField());
- }
-
- m_bNotifying = false;
+ if (bFormatted) {
+ pInterForm->ResetFieldAppearance(pWidget->GetFormField(), &sValue, true);
+ pInterForm->UpdateField(pWidget->GetFormField());
}
+
+ m_bNotifying = false;
}
#ifdef PDF_ENABLE_XFA
-void CFFL_InteractiveFormFiller::OnClick(CPDFSDK_Widget* pWidget,
+bool CFFL_InteractiveFormFiller::OnClick(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- if (pWidget->HasXFAAAction(PDFSDK_XFA_Click)) {
- m_bNotifying = true;
- int nAge = pWidget->GetAppearanceAge();
- int nValueAge = pWidget->GetValueAge();
+ if (m_bNotifying)
+ return false;
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (!pWidget->HasXFAAAction(PDFSDK_XFA_Click))
+ return false;
- pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView);
- m_bNotifying = false;
+ m_bNotifying = true;
+ uint32_t nAge = pWidget->GetAppearanceAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
- if (!IsValidAnnot(pPageView, pWidget)) {
- bExit = true;
- return;
- }
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
- if (nAge != pWidget->GetAppearanceAge()) {
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) {
- pFormFiller->ResetPDFWindow(pPageView,
- nValueAge == pWidget->GetValueAge());
- }
+ pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView);
+ m_bNotifying = false;
+ if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
+ return true;
+ if (nAge == pWidget->GetAppearanceAge())
+ return false;
- bReset = true;
- }
- }
- }
+ if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false))
+ pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
+ return false;
}
-void CFFL_InteractiveFormFiller::OnFull(CPDFSDK_Widget* pWidget,
+bool CFFL_InteractiveFormFiller::OnFull(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- if (pWidget->HasXFAAAction(PDFSDK_XFA_Full)) {
- m_bNotifying = true;
- int nAge = pWidget->GetAppearanceAge();
- int nValueAge = pWidget->GetValueAge();
+ if (m_bNotifying)
+ return false;
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (!pWidget->HasXFAAAction(PDFSDK_XFA_Full))
+ return false;
- pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView);
- m_bNotifying = false;
+ m_bNotifying = true;
+ uint32_t nAge = pWidget->GetAppearanceAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
- if (!IsValidAnnot(pPageView, pWidget)) {
- bExit = true;
- return;
- }
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
- if (nAge != pWidget->GetAppearanceAge()) {
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) {
- pFormFiller->ResetPDFWindow(pPageView,
- nValueAge == pWidget->GetValueAge());
- }
+ pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView);
+ m_bNotifying = false;
+ if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
+ return true;
+ if (nAge == pWidget->GetAppearanceAge())
+ return false;
- bReset = true;
- }
- }
- }
+ if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false))
+ pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
+
+ return true;
}
-void CFFL_InteractiveFormFiller::OnPopupPreOpen(void* pPrivateData,
- bool& bExit,
- uint32_t nFlag) {
- CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData;
+bool CFFL_InteractiveFormFiller::OnPopupPreOpen(
+ CPWL_Wnd::PrivateData* pAttached,
+ uint32_t nFlag) {
+ auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
ASSERT(pData);
ASSERT(pData->pWidget);
- bool bTempReset = false;
- bool bTempExit = false;
- OnPreOpen(pData->pWidget, pData->pPageView, bTempReset, bTempExit, nFlag);
- if (bTempReset || bTempExit)
- bExit = true;
+ CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget);
+ return OnPreOpen(&pObserved, pData->pPageView, nFlag) || !pObserved;
}
-void CFFL_InteractiveFormFiller::OnPopupPostOpen(void* pPrivateData,
- bool& bExit,
- uint32_t nFlag) {
- CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData;
+bool CFFL_InteractiveFormFiller::OnPopupPostOpen(
+ CPWL_Wnd::PrivateData* pAttached,
+ uint32_t nFlag) {
+ auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
ASSERT(pData);
ASSERT(pData->pWidget);
- bool bTempReset = false;
- bool bTempExit = false;
- OnPostOpen(pData->pWidget, pData->pPageView, bTempReset, bTempExit, nFlag);
- if (bTempReset || bTempExit)
- bExit = true;
+ CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget);
+ return OnPostOpen(&pObserved, pData->pPageView, nFlag) || !pObserved;
}
-void CFFL_InteractiveFormFiller::OnPreOpen(CPDFSDK_Widget* pWidget,
+bool CFFL_InteractiveFormFiller::OnPreOpen(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- if (pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen)) {
- m_bNotifying = true;
- int nAge = pWidget->GetAppearanceAge();
- int nValueAge = pWidget->GetValueAge();
+ if (m_bNotifying)
+ return false;
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (!pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen))
+ return false;
- pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView);
- m_bNotifying = false;
+ m_bNotifying = true;
+ uint32_t nAge = pWidget->GetAppearanceAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
- if (!IsValidAnnot(pPageView, pWidget)) {
- bExit = true;
- return;
- }
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
- if (nAge != pWidget->GetAppearanceAge()) {
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) {
- pFormFiller->ResetPDFWindow(pPageView,
- nValueAge == pWidget->GetValueAge());
- }
+ pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView);
+ m_bNotifying = false;
+ if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
+ return true;
+ if (nAge == pWidget->GetAppearanceAge())
+ return false;
- bReset = true;
- }
- }
- }
+ if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false))
+ pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
+
+ return true;
}
-void CFFL_InteractiveFormFiller::OnPostOpen(CPDFSDK_Widget* pWidget,
+bool CFFL_InteractiveFormFiller::OnPostOpen(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag) {
- if (!m_bNotifying) {
- if (pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen)) {
- m_bNotifying = true;
- int nAge = pWidget->GetAppearanceAge();
- int nValueAge = pWidget->GetValueAge();
+ if (m_bNotifying)
+ return false;
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
+ CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
+ if (!pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen))
+ return false;
- pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView);
- m_bNotifying = false;
+ m_bNotifying = true;
+ uint32_t nAge = pWidget->GetAppearanceAge();
+ uint32_t nValueAge = pWidget->GetValueAge();
- if (!IsValidAnnot(pPageView, pWidget)) {
- bExit = true;
- return;
- }
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
- if (nAge != pWidget->GetAppearanceAge()) {
- if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) {
- pFormFiller->ResetPDFWindow(pPageView,
- nValueAge == pWidget->GetValueAge());
- }
+ pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView);
+ m_bNotifying = false;
+ if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
+ return true;
+ if (nAge == pWidget->GetAppearanceAge())
+ return false;
- bReset = true;
- }
- }
- }
+ if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false))
+ pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
+
+ return true;
}
#endif // PDF_ENABLE_XFA
@@ -874,95 +849,83 @@
return pPageView && pPageView->IsValidAnnot(pAnnot->GetPDFAnnot());
}
-void CFFL_InteractiveFormFiller::OnBeforeKeyStroke(
- void* pPrivateData,
- CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
+std::pair<bool, bool> CFFL_InteractiveFormFiller::OnBeforeKeyStroke(
+ CPWL_Wnd::PrivateData* pAttached,
+ WideString& strChange,
+ const WideString& strChangeEx,
int nSelStart,
int nSelEnd,
bool bKeyDown,
- bool& bRC,
- bool& bExit,
uint32_t nFlag) {
- CFFL_PrivateData* pData = (CFFL_PrivateData*)pPrivateData;
- ASSERT(pData->pWidget);
+ // Copy the private data since the window owning it may not survive.
+ CFFL_PrivateData privateData = *static_cast<CFFL_PrivateData*>(pAttached);
+ ASSERT(privateData.pWidget);
- CFFL_FormFiller* pFormFiller = GetFormFiller(pData->pWidget, false);
+ CFFL_FormFiller* pFormFiller = GetFormFiller(privateData.pWidget, false);
#ifdef PDF_ENABLE_XFA
- if (pFormFiller->IsFieldFull(pData->pPageView)) {
- bool bFullExit = false;
- bool bFullReset = false;
- OnFull(pData->pWidget, pData->pPageView, bFullReset, bFullExit, nFlag);
-
- if (bFullReset || bFullExit) {
- bExit = true;
- return;
- }
+ if (pFormFiller->IsFieldFull(privateData.pPageView)) {
+ CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget);
+ if (OnFull(&pObserved, privateData.pPageView, nFlag) || !pObserved)
+ return {true, true};
}
#endif // PDF_ENABLE_XFA
- if (!m_bNotifying) {
- if (pData->pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) {
- m_bNotifying = true;
- int nAge = pData->pWidget->GetAppearanceAge();
- int nValueAge = pData->pWidget->GetValueAge();
-
- CPDFSDK_FormFillEnvironment* pFormFillEnv =
- pData->pPageView->GetFormFillEnv();
-
- PDFSDK_FieldAction fa;
- fa.bModifier = m_pFormFillEnv->IsCTRLKeyDown(nFlag);
- fa.bShift = m_pFormFillEnv->IsSHIFTKeyDown(nFlag);
- fa.sChange = strChange;
- fa.sChangeEx = strChangeEx;
- fa.bKeyDown = bKeyDown;
- fa.bWillCommit = false;
- fa.bRC = true;
- fa.nSelStart = nSelStart;
- fa.nSelEnd = nSelEnd;
-
- pFormFiller->GetActionData(pData->pPageView, CPDF_AAction::KeyStroke, fa);
- pFormFiller->SaveState(pData->pPageView);
-
- CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget);
- if (pData->pWidget->OnAAction(CPDF_AAction::KeyStroke, fa,
- pData->pPageView)) {
- if (!pObserved || !IsValidAnnot(pData->pPageView, pData->pWidget)) {
- bExit = true;
- m_bNotifying = false;
- return;
- }
-
- if (nAge != pData->pWidget->GetAppearanceAge()) {
- CPWL_Wnd* pWnd = pFormFiller->ResetPDFWindow(
- pData->pPageView, nValueAge == pData->pWidget->GetValueAge());
- pData = (CFFL_PrivateData*)pWnd->GetAttachedData();
- bExit = true;
- }
-
- if (fa.bRC) {
- pFormFiller->SetActionData(pData->pPageView, CPDF_AAction::KeyStroke,
- fa);
- bRC = false;
- } else {
- pFormFiller->RestoreState(pData->pPageView);
- bRC = false;
- }
-
- if (pFormFillEnv->GetFocusAnnot() != pData->pWidget) {
- pFormFiller->CommitData(pData->pPageView, nFlag);
- bExit = true;
- }
- } else {
- if (!IsValidAnnot(pData->pPageView, pData->pWidget)) {
- bExit = true;
- m_bNotifying = false;
- return;
- }
- }
-
- m_bNotifying = false;
- }
+ if (m_bNotifying ||
+ !privateData.pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) {
+ return {true, false};
}
+
+ AutoRestorer<bool> restorer(&m_bNotifying);
+ m_bNotifying = true;
+
+ uint32_t nAge = privateData.pWidget->GetAppearanceAge();
+ uint32_t nValueAge = privateData.pWidget->GetValueAge();
+ CPDFSDK_FormFillEnvironment* pFormFillEnv =
+ privateData.pPageView->GetFormFillEnv();
+
+ PDFSDK_FieldAction fa;
+ fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
+ fa.sChange = strChange;
+ fa.sChangeEx = strChangeEx;
+ fa.bKeyDown = bKeyDown;
+ fa.bWillCommit = false;
+ fa.bRC = true;
+ fa.nSelStart = nSelStart;
+ fa.nSelEnd = nSelEnd;
+ pFormFiller->GetActionData(privateData.pPageView, CPDF_AAction::KeyStroke,
+ fa);
+ pFormFiller->SaveState(privateData.pPageView);
+
+ CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget);
+ bool action_status = privateData.pWidget->OnAAction(
+ CPDF_AAction::KeyStroke, fa, privateData.pPageView);
+
+ if (!pObserved || !IsValidAnnot(privateData.pPageView, privateData.pWidget))
+ return {true, true};
+
+ if (!action_status)
+ return {true, false};
+
+ bool bExit = false;
+ if (nAge != privateData.pWidget->GetAppearanceAge()) {
+ CPWL_Wnd* pWnd = pFormFiller->ResetPDFWindow(
+ privateData.pPageView, nValueAge == privateData.pWidget->GetValueAge());
+ if (!pWnd)
+ return {true, true};
+ privateData = *static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData());
+ bExit = true;
+ }
+ if (fa.bRC) {
+ pFormFiller->SetActionData(privateData.pPageView, CPDF_AAction::KeyStroke,
+ fa);
+ } else {
+ pFormFiller->RestoreState(privateData.pPageView);
+ }
+ if (pFormFillEnv->GetFocusAnnot() == privateData.pWidget)
+ return {false, bExit};
+
+ pFormFiller->CommitData(privateData.pPageView, nFlag);
+ return {false, true};
}
diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.h b/fpdfsdk/formfiller/cffl_interactiveformfiller.h
index 90fd98c..0192752 100644
--- a/fpdfsdk/formfiller/cffl_interactiveformfiller.h
+++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.h
@@ -9,10 +9,12 @@
#include <map>
#include <memory>
+#include <utility>
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/cpdfsdk_annot.h"
#include "fpdfsdk/fsdk_define.h"
-#include "fpdfsdk/pdfwindow/PWL_Edit.h"
+#include "fpdfsdk/pwl/cpwl_edit.h"
class CFFL_FormFiller;
class CPDFSDK_FormFillEnvironment;
@@ -79,57 +81,42 @@
bool OnKillFocus(CPDFSDK_Annot::ObservedPtr* pAnnot, uint32_t nFlag);
CFFL_FormFiller* GetFormFiller(CPDFSDK_Annot* pAnnot, bool bRegister);
- void RemoveFormFiller(CPDFSDK_Annot* pAnnot);
+
+ WideString GetSelectedText(CPDFSDK_Annot* pAnnot);
+ void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text);
static bool IsVisible(CPDFSDK_Widget* pWidget);
static bool IsReadOnly(CPDFSDK_Widget* pWidget);
static bool IsFillingAllowed(CPDFSDK_Widget* pWidget);
static bool IsValidAnnot(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot);
- void OnKeyStrokeCommit(CPDFSDK_Annot::ObservedPtr* pWidget,
+ bool OnKeyStrokeCommit(CPDFSDK_Annot::ObservedPtr* pWidget,
CPDFSDK_PageView* pPageView,
- bool& bRC,
- bool& bExit,
uint32_t nFlag);
- void OnValidate(CPDFSDK_Annot::ObservedPtr* pWidget,
+ bool OnValidate(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bRC,
- bool& bExit,
uint32_t nFlag);
-
- void OnCalculate(CPDFSDK_Widget* pWidget,
+ void OnCalculate(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bExit,
uint32_t nFlag);
- void OnFormat(CPDFSDK_Widget* pWidget,
+ void OnFormat(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bExit,
uint32_t nFlag);
- void OnButtonUp(CPDFSDK_Annot::ObservedPtr* pWidget,
+ bool OnButtonUp(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag);
#ifdef PDF_ENABLE_XFA
- void OnClick(CPDFSDK_Widget* pWidget,
+ bool OnClick(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag);
- void OnFull(CPDFSDK_Widget* pWidget,
+ bool OnFull(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag);
- void OnPreOpen(CPDFSDK_Widget* pWidget,
+ bool OnPreOpen(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag);
- void OnPostOpen(CPDFSDK_Widget* pWidget,
+ bool OnPostOpen(CPDFSDK_Annot::ObservedPtr* pAnnot,
CPDFSDK_PageView* pPageView,
- bool& bReset,
- bool& bExit,
uint32_t nFlag);
#endif // PDF_ENABLE_XFA
@@ -138,40 +125,39 @@
std::map<CPDFSDK_Annot*, std::unique_ptr<CFFL_FormFiller>>;
// IPWL_Filler_Notify:
- void QueryWherePopup(void* pPrivateData,
- FX_FLOAT fPopupMin,
- FX_FLOAT fPopupMax,
- int32_t& nRet,
- FX_FLOAT& fPopupRet) override;
- void OnBeforeKeyStroke(void* pPrivateData,
- CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- int nSelStart,
- int nSelEnd,
- bool bKeyDown,
- bool& bRC,
- bool& bExit,
- uint32_t nFlag) override;
+ void QueryWherePopup(CPWL_Wnd::PrivateData* pAttached,
+ float fPopupMin,
+ float fPopupMax,
+ bool* bBottom,
+ float* fPopupRet) override;
+ // Returns {bRC, bExit}.
+ std::pair<bool, bool> OnBeforeKeyStroke(CPWL_Wnd::PrivateData* pAttached,
+ WideString& strChange,
+ const WideString& strChangeEx,
+ int nSelStart,
+ int nSelEnd,
+ bool bKeyDown,
+ uint32_t nFlag) override;
#ifdef PDF_ENABLE_XFA
- void OnPopupPreOpen(void* pPrivateData, bool& bExit, uint32_t nFlag) override;
- void OnPopupPostOpen(void* pPrivateData,
- bool& bExit,
+ bool OnPopupPreOpen(CPWL_Wnd::PrivateData* pAttached,
+ uint32_t nFlag) override;
+ bool OnPopupPostOpen(CPWL_Wnd::PrivateData* pAttached,
uint32_t nFlag) override;
void SetFocusAnnotTab(CPDFSDK_Annot* pWidget, bool bSameField, bool bNext);
#endif // PDF_ENABLE_XFA
void UnRegisterFormFiller(CPDFSDK_Annot* pAnnot);
- CPDFSDK_FormFillEnvironment* const m_pFormFillEnv;
+ UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
CFFL_Widget2Filler m_Maps;
bool m_bNotifying;
};
-class CFFL_PrivateData {
+class CFFL_PrivateData : public CPWL_Wnd::PrivateData {
public:
CPDFSDK_Widget* pWidget;
CPDFSDK_PageView* pPageView;
- int nWidgetAge;
- int nValueAge;
+ uint32_t nWidgetAppearanceAge;
+ uint32_t nWidgetValueAge;
};
#endif // FPDFSDK_FORMFILLER_CFFL_INTERACTIVEFORMFILLER_H_
diff --git a/fpdfsdk/formfiller/cffl_listbox.cpp b/fpdfsdk/formfiller/cffl_listbox.cpp
index 556e0e1..e628e59 100644
--- a/fpdfsdk/formfiller/cffl_listbox.cpp
+++ b/fpdfsdk/formfiller/cffl_listbox.cpp
@@ -9,46 +9,36 @@
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cba_fontmap.h"
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
#include "fpdfsdk/fsdk_common.h"
-#include "fpdfsdk/pdfwindow/PWL_ListBox.h"
+#include "fpdfsdk/pwl/cpwl_list_box.h"
#include "third_party/base/ptr_util.h"
#define FFL_DEFAULTLISTBOXFONTSIZE 12.0f
CFFL_ListBox::CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp,
- CPDFSDK_Annot* pWidget)
- : CFFL_FormFiller(pApp, pWidget) {}
+ CPDFSDK_Widget* pWidget)
+ : CFFL_TextObject(pApp, pWidget) {}
CFFL_ListBox::~CFFL_ListBox() {}
-PWL_CREATEPARAM CFFL_ListBox::GetCreateParam() {
- PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
-
+CPWL_Wnd::CreateParams CFFL_ListBox::GetCreateParam() {
+ CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam();
uint32_t dwFieldFlag = m_pWidget->GetFieldFlags();
-
- if (dwFieldFlag & FIELDFLAG_MULTISELECT) {
+ if (dwFieldFlag & FIELDFLAG_MULTISELECT)
cp.dwFlags |= PLBS_MULTIPLESEL;
- }
cp.dwFlags |= PWS_VSCROLL;
if (cp.dwFlags & PWS_AUTOFONTSIZE)
cp.fFontSize = FFL_DEFAULTLISTBOXFONTSIZE;
- if (!m_pFontMap) {
- m_pFontMap = pdfium::MakeUnique<CBA_FontMap>(
- m_pWidget, m_pFormFillEnv->GetSysHandler());
- }
- cp.pFontMap = m_pFontMap.get();
-
+ cp.pFontMap = MaybeCreateFontMap();
return cp;
}
-CPWL_Wnd* CFFL_ListBox::NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) {
- CPWL_ListBox* pWnd = new CPWL_ListBox();
+CPWL_Wnd* CFFL_ListBox::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) {
+ auto* pWnd = new CPWL_ListBox();
pWnd->AttachFFLData(this);
pWnd->Create(cp);
pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller());
@@ -87,7 +77,7 @@
bool CFFL_ListBox::OnChar(CPDFSDK_Annot* pAnnot,
uint32_t nChar,
uint32_t nFlags) {
- return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
+ return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags);
}
bool CFFL_ListBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
@@ -127,9 +117,18 @@
} else {
m_pWidget->SetOptionSelection(pListBox->GetCurSel(), true, false);
}
+ CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get());
+ CFFL_ListBox::ObservedPtr observed_this(this);
+
m_pWidget->SetTopVisibleIndex(nNewTopIndex);
+ if (!observed_widget)
+ return;
m_pWidget->ResetFieldAppearance(true);
+ if (!observed_widget)
+ return;
m_pWidget->UpdateField();
+ if (!observed_widget || !observed_this)
+ return;
SetChangeMark();
}
@@ -187,24 +186,3 @@
for (const auto& item : m_State)
pListBox->Select(item);
}
-
-CPWL_Wnd* CFFL_ListBox::ResetPDFWindow(CPDFSDK_PageView* pPageView,
- bool bRestoreValue) {
- if (bRestoreValue)
- SaveState(pPageView);
-
- DestroyPDFWindow(pPageView);
-
- CPWL_Wnd* pRet = nullptr;
-
- if (bRestoreValue) {
- RestoreState(pPageView);
- pRet = GetPDFWindow(pPageView, false);
- } else {
- pRet = GetPDFWindow(pPageView, true);
- }
-
- m_pWidget->UpdateField();
-
- return pRet;
-}
diff --git a/fpdfsdk/formfiller/cffl_listbox.h b/fpdfsdk/formfiller/cffl_listbox.h
index 609f2c4..014865d 100644
--- a/fpdfsdk/formfiller/cffl_listbox.h
+++ b/fpdfsdk/formfiller/cffl_listbox.h
@@ -7,23 +7,21 @@
#ifndef FPDFSDK_FORMFILLER_CFFL_LISTBOX_H_
#define FPDFSDK_FORMFILLER_CFFL_LISTBOX_H_
-#include <memory>
#include <set>
#include <vector>
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_textobject.h"
class CBA_FontMap;
-class CFFL_ListBox : public CFFL_FormFiller {
+class CFFL_ListBox : public CFFL_TextObject {
public:
- CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pWidget);
+ CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
~CFFL_ListBox() override;
- // CFFL_FormFiller
- PWL_CREATEPARAM GetCreateParam() override;
- CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) override;
+ // CFFL_TextObject:
+ CPWL_Wnd::CreateParams GetCreateParam() override;
+ CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override;
bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
bool IsDataChanged(CPDFSDK_PageView* pPageView) override;
void SaveData(CPDFSDK_PageView* pPageView) override;
@@ -32,11 +30,8 @@
PDFSDK_FieldAction& fa) override;
void SaveState(CPDFSDK_PageView* pPageView) override;
void RestoreState(CPDFSDK_PageView* pPageView) override;
- CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
- bool bRestoreValue) override;
private:
- std::unique_ptr<CBA_FontMap> m_pFontMap;
std::set<int> m_OriginSelections;
std::vector<int> m_State;
};
diff --git a/fpdfsdk/formfiller/cffl_pushbutton.cpp b/fpdfsdk/formfiller/cffl_pushbutton.cpp
index 9b4121a..7310da6 100644
--- a/fpdfsdk/formfiller/cffl_pushbutton.cpp
+++ b/fpdfsdk/formfiller/cffl_pushbutton.cpp
@@ -7,31 +7,16 @@
#include "fpdfsdk/formfiller/cffl_pushbutton.h"
#include "fpdfsdk/formfiller/cffl_formfiller.h"
-#include "fpdfsdk/pdfwindow/PWL_SpecialButton.h"
+#include "fpdfsdk/pwl/cpwl_special_button.h"
CFFL_PushButton::CFFL_PushButton(CPDFSDK_FormFillEnvironment* pApp,
- CPDFSDK_Annot* pAnnot)
- : CFFL_Button(pApp, pAnnot) {}
+ CPDFSDK_Widget* pWidget)
+ : CFFL_Button(pApp, pWidget) {}
CFFL_PushButton::~CFFL_PushButton() {}
-CPWL_Wnd* CFFL_PushButton::NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) {
- CPWL_PushButton* pWnd = new CPWL_PushButton();
+CPWL_Wnd* CFFL_PushButton::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) {
+ auto* pWnd = new CPWL_PushButton();
pWnd->Create(cp);
-
return pWnd;
}
-
-bool CFFL_PushButton::OnChar(CPDFSDK_Annot* pAnnot,
- uint32_t nChar,
- uint32_t nFlags) {
- return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
-}
-
-void CFFL_PushButton::OnDraw(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- CFFL_Button::OnDraw(pPageView, pAnnot, pDevice, pUser2Device);
-}
diff --git a/fpdfsdk/formfiller/cffl_pushbutton.h b/fpdfsdk/formfiller/cffl_pushbutton.h
index 1d50595..7ee0767 100644
--- a/fpdfsdk/formfiller/cffl_pushbutton.h
+++ b/fpdfsdk/formfiller/cffl_pushbutton.h
@@ -7,21 +7,15 @@
#ifndef FPDFSDK_FORMFILLER_CFFL_PUSHBUTTON_H_
#define FPDFSDK_FORMFILLER_CFFL_PUSHBUTTON_H_
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_button.h"
class CFFL_PushButton : public CFFL_Button {
public:
- CFFL_PushButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pAnnot);
+ CFFL_PushButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
~CFFL_PushButton() override;
- // CFFL_Button
- CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) override;
- bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
- void OnDraw(CPDFSDK_PageView* pPageView,
- CPDFSDK_Annot* pAnnot,
- CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
+ // CFFL_Button:
+ CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override;
};
#endif // FPDFSDK_FORMFILLER_CFFL_PUSHBUTTON_H_
diff --git a/fpdfsdk/formfiller/cffl_radiobutton.cpp b/fpdfsdk/formfiller/cffl_radiobutton.cpp
index e78160e..73ac44d 100644
--- a/fpdfsdk/formfiller/cffl_radiobutton.cpp
+++ b/fpdfsdk/formfiller/cffl_radiobutton.cpp
@@ -9,22 +9,19 @@
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cffl_formfiller.h"
-#include "fpdfsdk/pdfwindow/PWL_SpecialButton.h"
+#include "fpdfsdk/pwl/cpwl_special_button.h"
#include "public/fpdf_fwlevent.h"
CFFL_RadioButton::CFFL_RadioButton(CPDFSDK_FormFillEnvironment* pApp,
- CPDFSDK_Annot* pWidget)
+ CPDFSDK_Widget* pWidget)
: CFFL_Button(pApp, pWidget) {}
CFFL_RadioButton::~CFFL_RadioButton() {}
-CPWL_Wnd* CFFL_RadioButton::NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) {
- CPWL_RadioButton* pWnd = new CPWL_RadioButton();
+CPWL_Wnd* CFFL_RadioButton::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) {
+ auto* pWnd = new CPWL_RadioButton();
pWnd->Create(cp);
-
pWnd->SetCheck(m_pWidget->IsChecked());
-
return pWnd;
}
@@ -49,20 +46,18 @@
CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
ASSERT(pPageView);
- bool bReset = false;
- bool bExit = false;
- CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget);
- m_pFormFillEnv->GetInteractiveFormFiller()->OnButtonUp(
- &pObserved, pPageView, bReset, bExit, nFlags);
- if (!pObserved || bReset || bExit)
+ CPDFSDK_Annot::ObservedPtr pObserved(m_pWidget.Get());
+ if (m_pFormFillEnv->GetInteractiveFormFiller()->OnButtonUp(
+ &pObserved, pPageView, nFlags) ||
+ !pObserved) {
return true;
+ }
CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
- if (CPWL_RadioButton* pWnd =
- (CPWL_RadioButton*)GetPDFWindow(pPageView, true))
+ CPWL_RadioButton* pWnd = GetRadioButton(pPageView, true);
+ if (pWnd)
pWnd->SetCheck(true);
- CommitData(pPageView, nFlags);
- return true;
+ return CommitData(pPageView, nFlags);
}
default:
return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
@@ -75,45 +70,51 @@
const CFX_PointF& point) {
CFFL_Button::OnLButtonUp(pPageView, pAnnot, nFlags, point);
- if (IsValid()) {
- if (CPWL_RadioButton* pWnd =
- (CPWL_RadioButton*)GetPDFWindow(pPageView, true))
- pWnd->SetCheck(true);
+ if (!IsValid())
+ return true;
- if (!CommitData(pPageView, nFlags))
- return false;
- }
+ CPWL_RadioButton* pWnd = GetRadioButton(pPageView, true);
+ if (pWnd)
+ pWnd->SetCheck(true);
- return true;
+ return CommitData(pPageView, nFlags);
}
bool CFFL_RadioButton::IsDataChanged(CPDFSDK_PageView* pPageView) {
- if (CPWL_RadioButton* pWnd =
- (CPWL_RadioButton*)GetPDFWindow(pPageView, false)) {
- return pWnd->IsChecked() != m_pWidget->IsChecked();
- }
-
- return false;
+ CPWL_RadioButton* pWnd = GetRadioButton(pPageView, false);
+ return pWnd && pWnd->IsChecked() != m_pWidget->IsChecked();
}
void CFFL_RadioButton::SaveData(CPDFSDK_PageView* pPageView) {
- if (CPWL_RadioButton* pWnd =
- (CPWL_RadioButton*)GetPDFWindow(pPageView, false)) {
- bool bNewChecked = pWnd->IsChecked();
+ CPWL_RadioButton* pWnd = GetRadioButton(pPageView, false);
+ if (!pWnd)
+ return;
- if (bNewChecked) {
- CPDF_FormField* pField = m_pWidget->GetFormField();
- for (int32_t i = 0, sz = pField->CountControls(); i < sz; i++) {
- if (CPDF_FormControl* pCtrl = pField->GetControl(i)) {
- if (pCtrl->IsChecked()) {
- break;
- }
+ bool bNewChecked = pWnd->IsChecked();
+
+ if (bNewChecked) {
+ CPDF_FormField* pField = m_pWidget->GetFormField();
+ for (int32_t i = 0, sz = pField->CountControls(); i < sz; i++) {
+ if (CPDF_FormControl* pCtrl = pField->GetControl(i)) {
+ if (pCtrl->IsChecked()) {
+ break;
}
}
}
-
- m_pWidget->SetCheck(bNewChecked, false);
- m_pWidget->UpdateField();
- SetChangeMark();
}
+ CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get());
+ CFFL_RadioButton::ObservedPtr observed_this(this);
+
+ m_pWidget->SetCheck(bNewChecked, false);
+ if (!observed_widget)
+ return;
+ m_pWidget->UpdateField();
+ if (!observed_widget || !observed_this)
+ return;
+ SetChangeMark();
+}
+
+CPWL_RadioButton* CFFL_RadioButton::GetRadioButton(CPDFSDK_PageView* pPageView,
+ bool bNew) {
+ return static_cast<CPWL_RadioButton*>(GetPDFWindow(pPageView, bNew));
}
diff --git a/fpdfsdk/formfiller/cffl_radiobutton.h b/fpdfsdk/formfiller/cffl_radiobutton.h
index 10ac37d..2838254 100644
--- a/fpdfsdk/formfiller/cffl_radiobutton.h
+++ b/fpdfsdk/formfiller/cffl_radiobutton.h
@@ -7,16 +7,17 @@
#ifndef FPDFSDK_FORMFILLER_CFFL_RADIOBUTTON_H_
#define FPDFSDK_FORMFILLER_CFFL_RADIOBUTTON_H_
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_button.h"
+
+class CPWL_RadioButton;
class CFFL_RadioButton : public CFFL_Button {
public:
- CFFL_RadioButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pAnnot);
+ CFFL_RadioButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
~CFFL_RadioButton() override;
- // CFFL_Button
- CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) override;
+ // CFFL_Button:
+ CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override;
bool OnKeyDown(CPDFSDK_Annot* pAnnot,
uint32_t nKeyCode,
uint32_t nFlags) override;
@@ -27,6 +28,9 @@
const CFX_PointF& point) override;
bool IsDataChanged(CPDFSDK_PageView* pPageView) override;
void SaveData(CPDFSDK_PageView* pPageView) override;
+
+ private:
+ CPWL_RadioButton* GetRadioButton(CPDFSDK_PageView* pPageView, bool bNew);
};
#endif // FPDFSDK_FORMFILLER_CFFL_RADIOBUTTON_H_
diff --git a/fpdfsdk/formfiller/cffl_textfield.cpp b/fpdfsdk/formfiller/cffl_textfield.cpp
index 91db095..ad8d27c 100644
--- a/fpdfsdk/formfiller/cffl_textfield.cpp
+++ b/fpdfsdk/formfiller/cffl_textfield.cpp
@@ -13,8 +13,8 @@
#include "third_party/base/ptr_util.h"
CFFL_TextField::CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp,
- CPDFSDK_Annot* pAnnot)
- : CFFL_FormFiller(pApp, pAnnot) {}
+ CPDFSDK_Widget* pWidget)
+ : CFFL_TextObject(pApp, pWidget) {}
CFFL_TextField::~CFFL_TextField() {
for (const auto& it : m_Maps)
@@ -26,36 +26,27 @@
DestroyWindows();
}
-PWL_CREATEPARAM CFFL_TextField::GetCreateParam() {
- PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
-
+CPWL_Wnd::CreateParams CFFL_TextField::GetCreateParam() {
+ CPWL_Wnd::CreateParams cp = CFFL_TextObject::GetCreateParam();
int nFlags = m_pWidget->GetFieldFlags();
-
- if (nFlags & FIELDFLAG_PASSWORD) {
+ if (nFlags & FIELDFLAG_PASSWORD)
cp.dwFlags |= PES_PASSWORD;
- }
if (nFlags & FIELDFLAG_MULTILINE) {
cp.dwFlags |= PES_MULTILINE | PES_AUTORETURN | PES_TOP;
-
- if (!(nFlags & FIELDFLAG_DONOTSCROLL)) {
+ if (!(nFlags & FIELDFLAG_DONOTSCROLL))
cp.dwFlags |= PWS_VSCROLL | PES_AUTOSCROLL;
- }
} else {
cp.dwFlags |= PES_CENTER;
-
- if (!(nFlags & FIELDFLAG_DONOTSCROLL)) {
+ if (!(nFlags & FIELDFLAG_DONOTSCROLL))
cp.dwFlags |= PES_AUTOSCROLL;
- }
}
- if (nFlags & FIELDFLAG_COMB) {
+ if (nFlags & FIELDFLAG_COMB)
cp.dwFlags |= PES_CHARARRAY;
- }
- if (nFlags & FIELDFLAG_RICHTEXT) {
+ if (nFlags & FIELDFLAG_RICHTEXT)
cp.dwFlags |= PES_RICH;
- }
cp.dwFlags |= PES_UNDO;
@@ -71,26 +62,19 @@
cp.dwFlags |= PES_RIGHT;
break;
}
-
- if (!m_pFontMap) {
- m_pFontMap = pdfium::MakeUnique<CBA_FontMap>(
- m_pWidget, m_pFormFillEnv->GetSysHandler());
- }
- cp.pFontMap = m_pFontMap.get();
+ cp.pFontMap = MaybeCreateFontMap();
cp.pFocusHandler = this;
-
return cp;
}
-CPWL_Wnd* CFFL_TextField::NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) {
- CPWL_Edit* pWnd = new CPWL_Edit();
+CPWL_Wnd* CFFL_TextField::NewPDFWindow(const CPWL_Wnd::CreateParams& cp) {
+ auto* pWnd = new CPWL_Edit();
pWnd->AttachFFLData(this);
pWnd->Create(cp);
pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller());
int32_t nMaxLen = m_pWidget->GetMaxLen();
- CFX_WideString swValue = m_pWidget->GetValue();
+ WideString swValue = m_pWidget->GetValue();
if (nMaxLen > 0) {
if (pWnd->HasFlag(PES_CHARARRAY)) {
@@ -109,26 +93,28 @@
uint32_t nChar,
uint32_t nFlags) {
switch (nChar) {
- case FWL_VKEY_Return:
- if (!(m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE)) {
- CPDFSDK_PageView* pPageView = GetCurPageView(true);
- ASSERT(pPageView);
- m_bValid = !m_bValid;
- m_pFormFillEnv->Invalidate(pAnnot->GetUnderlyingPage(),
- pAnnot->GetRect().ToFxRect());
+ case FWL_VKEY_Return: {
+ if (m_pWidget->GetFieldFlags() & FIELDFLAG_MULTILINE)
+ break;
- if (m_bValid) {
- if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true))
- pWnd->SetFocus();
- } else {
- if (CommitData(pPageView, nFlags)) {
- DestroyPDFWindow(pPageView);
- return true;
- }
- return false;
- }
+ CPDFSDK_PageView* pPageView = GetCurPageView(true);
+ ASSERT(pPageView);
+ m_bValid = !m_bValid;
+ m_pFormFillEnv->Invalidate(pAnnot->GetUnderlyingPage(),
+ pAnnot->GetRect().GetOuterRect());
+
+ if (m_bValid) {
+ if (CPWL_Wnd* pWnd = GetPDFWindow(pPageView, true))
+ pWnd->SetFocus();
+ break;
}
- break;
+
+ if (!CommitData(pPageView, nFlags))
+ return false;
+
+ DestroyPDFWindow(pPageView);
+ return true;
+ }
case FWL_VKEY_Escape: {
CPDFSDK_PageView* pPageView = GetCurPageView(true);
ASSERT(pPageView);
@@ -137,26 +123,35 @@
}
}
- return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
+ return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags);
}
bool CFFL_TextField::IsDataChanged(CPDFSDK_PageView* pPageView) {
- if (CPWL_Edit* pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, false))
- return pEdit->GetText() != m_pWidget->GetValue();
-
- return false;
+ CPWL_Edit* pEdit = GetEdit(pPageView, false);
+ return pEdit && pEdit->GetText() != m_pWidget->GetValue();
}
void CFFL_TextField::SaveData(CPDFSDK_PageView* pPageView) {
- if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
- CFX_WideString sOldValue = m_pWidget->GetValue();
- CFX_WideString sNewValue = pWnd->GetText();
+ CPWL_Edit* pWnd = GetEdit(pPageView, false);
+ if (!pWnd)
+ return;
- m_pWidget->SetValue(sNewValue, false);
- m_pWidget->ResetFieldAppearance(true);
- m_pWidget->UpdateField();
- SetChangeMark();
- }
+ WideString sOldValue = m_pWidget->GetValue();
+ WideString sNewValue = pWnd->GetText();
+
+ CPDFSDK_Widget::ObservedPtr observed_widget(m_pWidget.Get());
+ CFFL_TextField::ObservedPtr observed_this(this);
+
+ m_pWidget->SetValue(sNewValue, false);
+ if (!observed_widget)
+ return;
+ m_pWidget->ResetFieldAppearance(true);
+ if (!observed_widget)
+ return;
+ m_pWidget->UpdateField();
+ if (!observed_widget || !observed_this)
+ return;
+ SetChangeMark();
}
void CFFL_TextField::GetActionData(CPDFSDK_PageView* pPageView,
@@ -164,7 +159,7 @@
PDFSDK_FieldAction& fa) {
switch (type) {
case CPDF_AAction::KeyStroke:
- if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
+ if (CPWL_Edit* pWnd = GetEdit(pPageView, false)) {
fa.bFieldFull = pWnd->IsTextFull();
fa.sValue = pWnd->GetText();
@@ -176,7 +171,7 @@
}
break;
case CPDF_AAction::Validate:
- if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
+ if (CPWL_Edit* pWnd = GetEdit(pPageView, false)) {
fa.sValue = pWnd->GetText();
}
break;
@@ -194,9 +189,9 @@
const PDFSDK_FieldAction& fa) {
switch (type) {
case CPDF_AAction::KeyStroke:
- if (CPWL_Edit* pEdit = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
+ if (CPWL_Edit* pEdit = GetEdit(pPageView, false)) {
pEdit->SetFocus();
- pEdit->SetSel(fa.nSelStart, fa.nSelEnd);
+ pEdit->SetSelection(fa.nSelStart, fa.nSelEnd);
pEdit->ReplaceSel(fa.sChange);
}
break;
@@ -223,64 +218,43 @@
void CFFL_TextField::SaveState(CPDFSDK_PageView* pPageView) {
ASSERT(pPageView);
- if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
- pWnd->GetSel(m_State.nStart, m_State.nEnd);
- m_State.sValue = pWnd->GetText();
- }
+ CPWL_Edit* pWnd = GetEdit(pPageView, false);
+ if (!pWnd)
+ return;
+
+ pWnd->GetSelection(m_State.nStart, m_State.nEnd);
+ m_State.sValue = pWnd->GetText();
}
void CFFL_TextField::RestoreState(CPDFSDK_PageView* pPageView) {
ASSERT(pPageView);
- if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, true)) {
- pWnd->SetText(m_State.sValue);
- pWnd->SetSel(m_State.nStart, m_State.nEnd);
- }
-}
+ CPWL_Edit* pWnd = GetEdit(pPageView, true);
+ if (!pWnd)
+ return;
-CPWL_Wnd* CFFL_TextField::ResetPDFWindow(CPDFSDK_PageView* pPageView,
- bool bRestoreValue) {
- if (bRestoreValue)
- SaveState(pPageView);
-
- DestroyPDFWindow(pPageView);
-
- CPWL_Wnd* pRet = nullptr;
-
- if (bRestoreValue) {
- RestoreState(pPageView);
- pRet = GetPDFWindow(pPageView, false);
- } else {
- pRet = GetPDFWindow(pPageView, true);
- }
-
- m_pWidget->UpdateField();
-
- return pRet;
+ pWnd->SetText(m_State.sValue);
+ pWnd->SetSelection(m_State.nStart, m_State.nEnd);
}
#ifdef PDF_ENABLE_XFA
bool CFFL_TextField::IsFieldFull(CPDFSDK_PageView* pPageView) {
- if (CPWL_Edit* pWnd = (CPWL_Edit*)GetPDFWindow(pPageView, false)) {
- return pWnd->IsTextFull();
- }
-
- return false;
+ CPWL_Edit* pWnd = GetEdit(pPageView, false);
+ return pWnd && pWnd->IsTextFull();
}
#endif // PDF_ENABLE_XFA
-void CFFL_TextField::OnSetFocus(CPWL_Wnd* pWnd) {
- ASSERT(m_pFormFillEnv);
- if (pWnd->GetClassName() == PWL_CLASSNAME_EDIT) {
- CPWL_Edit* pEdit = (CPWL_Edit*)pWnd;
- pEdit->SetCharSet(FXFONT_GB2312_CHARSET);
- pEdit->SetCodePage(936);
+void CFFL_TextField::OnSetFocus(CPWL_Edit* pEdit) {
+ pEdit->SetCharSet(FX_CHARSET_ChineseSimplified);
+ pEdit->SetReadyToInput();
- pEdit->SetReadyToInput();
- CFX_WideString wsText = pEdit->GetText();
- int nCharacters = wsText.GetLength();
- CFX_ByteString bsUTFText = wsText.UTF16LE_Encode();
- unsigned short* pBuffer = (unsigned short*)bsUTFText.c_str();
- m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
- }
+ WideString wsText = pEdit->GetText();
+ int nCharacters = wsText.GetLength();
+ ByteString bsUTFText = wsText.UTF16LE_Encode();
+ auto* pBuffer = reinterpret_cast<const unsigned short*>(bsUTFText.c_str());
+ m_pFormFillEnv->OnSetFieldInputFocus(pBuffer, nCharacters, true);
+}
+
+CPWL_Edit* CFFL_TextField::GetEdit(CPDFSDK_PageView* pPageView, bool bNew) {
+ return static_cast<CPWL_Edit*>(GetPDFWindow(pPageView, bNew));
}
diff --git a/fpdfsdk/formfiller/cffl_textfield.h b/fpdfsdk/formfiller/cffl_textfield.h
index 29579f7..49ffc0f 100644
--- a/fpdfsdk/formfiller/cffl_textfield.h
+++ b/fpdfsdk/formfiller/cffl_textfield.h
@@ -7,33 +7,32 @@
#ifndef FPDFSDK_FORMFILLER_CFFL_TEXTFIELD_H_
#define FPDFSDK_FORMFILLER_CFFL_TEXTFIELD_H_
-#include <memory>
-
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_textobject.h"
#define BF_ALIGN_LEFT 0
#define BF_ALIGN_MIDDLE 1
#define BF_ALIGN_RIGHT 2
class CBA_FontMap;
+class CPWL_Edit;
struct FFL_TextFieldState {
FFL_TextFieldState() : nStart(0), nEnd(0) {}
int nStart;
int nEnd;
- CFX_WideString sValue;
+ WideString sValue;
};
-class CFFL_TextField : public CFFL_FormFiller, public IPWL_FocusHandler {
+class CFFL_TextField : public CFFL_TextObject,
+ public CPWL_Wnd::FocusHandlerIface {
public:
- CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Annot* pAnnot);
+ CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
~CFFL_TextField() override;
- // CFFL_FormFiller:
- PWL_CREATEPARAM GetCreateParam() override;
- CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp,
- CPDFSDK_PageView* pPageView) override;
+ // CFFL_TextObject:
+ CPWL_Wnd::CreateParams GetCreateParam() override;
+ CPWL_Wnd* NewPDFWindow(const CPWL_Wnd::CreateParams& cp) override;
bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
bool IsDataChanged(CPDFSDK_PageView* pPageView) override;
void SaveData(CPDFSDK_PageView* pPageView) override;
@@ -48,19 +47,16 @@
const PDFSDK_FieldAction& faNew) override;
void SaveState(CPDFSDK_PageView* pPageView) override;
void RestoreState(CPDFSDK_PageView* pPageView) override;
- CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
- bool bRestoreValue) override;
-
- // IPWL_FocusHandler:
- void OnSetFocus(CPWL_Wnd* pWnd) override;
-
#ifdef PDF_ENABLE_XFA
- // CFFL_FormFiller:
bool IsFieldFull(CPDFSDK_PageView* pPageView) override;
-#endif // PDF_ENABLE_XFA
+#endif
+
+ // CPWL_Wnd::FocusHandlerIface:
+ void OnSetFocus(CPWL_Edit* pEdit) override;
private:
- std::unique_ptr<CBA_FontMap> m_pFontMap;
+ CPWL_Edit* GetEdit(CPDFSDK_PageView* pPageView, bool bNew);
+
FFL_TextFieldState m_State;
};
diff --git a/fpdfsdk/formfiller/cffl_textobject.cpp b/fpdfsdk/formfiller/cffl_textobject.cpp
new file mode 100644
index 0000000..df2f5e5
--- /dev/null
+++ b/fpdfsdk/formfiller/cffl_textobject.cpp
@@ -0,0 +1,39 @@
+// 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/formfiller/cffl_textobject.h"
+
+CPWL_Wnd* CFFL_TextObject::ResetPDFWindow(CPDFSDK_PageView* pPageView,
+ bool bRestoreValue) {
+ if (bRestoreValue)
+ SaveState(pPageView);
+
+ DestroyPDFWindow(pPageView);
+ if (bRestoreValue)
+ RestoreState(pPageView);
+
+ CPWL_Wnd::ObservedPtr pRet(GetPDFWindow(pPageView, !bRestoreValue));
+ m_pWidget->UpdateField(); // May invoke JS, invalidating |pRet|.
+ return pRet.Get();
+}
+
+CFFL_TextObject::CFFL_TextObject(CPDFSDK_FormFillEnvironment* pApp,
+ CPDFSDK_Widget* pWidget)
+ : CFFL_FormFiller(pApp, pWidget) {}
+
+CFFL_TextObject::~CFFL_TextObject() {
+ // Destroy view classes before this object's members are destroyed since
+ // the view classes have pointers to m_pFontMap that would be left dangling.
+ DestroyWindows();
+}
+
+CBA_FontMap* CFFL_TextObject::MaybeCreateFontMap() {
+ if (!m_pFontMap) {
+ m_pFontMap =
+ pdfium::MakeUnique<CBA_FontMap>(m_pWidget.Get(), GetSystemHandler());
+ }
+ return m_pFontMap.get();
+}
diff --git a/fpdfsdk/formfiller/cffl_textobject.h b/fpdfsdk/formfiller/cffl_textobject.h
new file mode 100644
index 0000000..fcb3c1b
--- /dev/null
+++ b/fpdfsdk/formfiller/cffl_textobject.h
@@ -0,0 +1,32 @@
+// 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_FORMFILLER_CFFL_TEXTOBJECT_H_
+#define FPDFSDK_FORMFILLER_CFFL_TEXTOBJECT_H_
+
+#include <memory>
+
+#include "fpdfsdk/formfiller/cffl_formfiller.h"
+
+// Class to implement common functionality for CFFL_FormFiller sub-classes with
+// text fields.
+class CFFL_TextObject : public CFFL_FormFiller {
+ public:
+ // CFFL_FormFiller:
+ CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
+ bool bRestoreValue) override;
+
+ protected:
+ CFFL_TextObject(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
+ ~CFFL_TextObject() override;
+
+ CBA_FontMap* MaybeCreateFontMap();
+
+ private:
+ std::unique_ptr<CBA_FontMap> m_pFontMap;
+};
+
+#endif // FPDFSDK_FORMFILLER_CFFL_TEXTOBJECT_H_
diff --git a/fpdfsdk/fpdf_dataavail.cpp b/fpdfsdk/fpdf_dataavail.cpp
index b1bc1e3..b1a134d 100644
--- a/fpdfsdk/fpdf_dataavail.cpp
+++ b/fpdfsdk/fpdf_dataavail.cpp
@@ -11,7 +11,8 @@
#include "core/fpdfapi/parser/cpdf_data_avail.h"
#include "core/fpdfapi/parser/cpdf_document.h"
-#include "core/fxcrt/cfx_retain_ptr.h"
+#include "core/fxcrt/fx_stream.h"
+#include "core/fxcrt/retain_ptr.h"
#include "fpdfsdk/fsdk_define.h"
#include "public/fpdf_formfill.h"
#include "third_party/base/ptr_util.h"
@@ -42,15 +43,15 @@
namespace {
-class CFPDF_FileAvailWrap : public CPDF_DataAvail::FileAvail {
+class FPDF_FileAvailContext : public CPDF_DataAvail::FileAvail {
public:
- CFPDF_FileAvailWrap() : m_pfileAvail(nullptr) {}
- ~CFPDF_FileAvailWrap() override {}
+ FPDF_FileAvailContext() : m_pfileAvail(nullptr) {}
+ ~FPDF_FileAvailContext() override {}
void Set(FX_FILEAVAIL* pfileAvail) { m_pfileAvail = pfileAvail; }
// CPDF_DataAvail::FileAvail:
- bool IsDataAvail(FX_FILESIZE offset, uint32_t size) override {
+ bool IsDataAvail(FX_FILESIZE offset, size_t size) override {
return !!m_pfileAvail->IsDataAvail(m_pfileAvail, offset, size);
}
@@ -58,12 +59,12 @@
FX_FILEAVAIL* m_pfileAvail;
};
-class CFPDF_FileAccessWrap : public IFX_SeekableReadStream {
+class FPDF_FileAccessContext : public IFX_SeekableReadStream {
public:
- static CFX_RetainPtr<CFPDF_FileAccessWrap> Create() {
- return CFX_RetainPtr<CFPDF_FileAccessWrap>(new CFPDF_FileAccessWrap());
- }
- ~CFPDF_FileAccessWrap() override {}
+ template <typename T, typename... Args>
+ friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
+
+ ~FPDF_FileAccessContext() override {}
void Set(FPDF_FILEACCESS* pFile) { m_pFileAccess = pFile; }
@@ -76,119 +77,115 @@
}
private:
- CFPDF_FileAccessWrap() : m_pFileAccess(nullptr) {}
+ FPDF_FileAccessContext() : m_pFileAccess(nullptr) {}
FPDF_FILEACCESS* m_pFileAccess;
};
-class CFPDF_DownloadHintsWrap : public CPDF_DataAvail::DownloadHints {
+class FPDF_DownloadHintsContext : public CPDF_DataAvail::DownloadHints {
public:
- explicit CFPDF_DownloadHintsWrap(FX_DOWNLOADHINTS* pDownloadHints) {
+ explicit FPDF_DownloadHintsContext(FX_DOWNLOADHINTS* pDownloadHints) {
m_pDownloadHints = pDownloadHints;
}
- ~CFPDF_DownloadHintsWrap() override {}
+ ~FPDF_DownloadHintsContext() override {}
public:
// IFX_DownloadHints
- void AddSegment(FX_FILESIZE offset, uint32_t size) override {
- m_pDownloadHints->AddSegment(m_pDownloadHints, offset, size);
+ void AddSegment(FX_FILESIZE offset, size_t size) override {
+ if (m_pDownloadHints)
+ m_pDownloadHints->AddSegment(m_pDownloadHints, offset, size);
}
private:
FX_DOWNLOADHINTS* m_pDownloadHints;
};
-class CFPDF_DataAvail {
+class FPDF_AvailContext {
public:
- CFPDF_DataAvail()
- : m_FileAvail(new CFPDF_FileAvailWrap),
- m_FileRead(CFPDF_FileAccessWrap::Create()) {}
- ~CFPDF_DataAvail() {}
+ FPDF_AvailContext()
+ : m_FileAvail(pdfium::MakeUnique<FPDF_FileAvailContext>()),
+ m_FileRead(pdfium::MakeRetain<FPDF_FileAccessContext>()) {}
+ ~FPDF_AvailContext() {}
+ std::unique_ptr<FPDF_FileAvailContext> m_FileAvail;
+ RetainPtr<FPDF_FileAccessContext> m_FileRead;
std::unique_ptr<CPDF_DataAvail> m_pDataAvail;
- std::unique_ptr<CFPDF_FileAvailWrap> m_FileAvail;
- CFX_RetainPtr<CFPDF_FileAccessWrap> m_FileRead;
};
-CFPDF_DataAvail* CFPDFDataAvailFromFPDFAvail(FPDF_AVAIL avail) {
- return static_cast<CFPDF_DataAvail*>(avail);
+FPDF_AvailContext* FPDFAvailContextFromFPDFAvail(FPDF_AVAIL avail) {
+ return static_cast<FPDF_AvailContext*>(avail);
}
} // namespace
-DLLEXPORT FPDF_AVAIL STDCALL FPDFAvail_Create(FX_FILEAVAIL* file_avail,
- FPDF_FILEACCESS* file) {
- CFPDF_DataAvail* pAvail = new CFPDF_DataAvail;
+FPDF_EXPORT FPDF_AVAIL FPDF_CALLCONV FPDFAvail_Create(FX_FILEAVAIL* file_avail,
+ FPDF_FILEACCESS* file) {
+ auto pAvail = pdfium::MakeUnique<FPDF_AvailContext>();
pAvail->m_FileAvail->Set(file_avail);
pAvail->m_FileRead->Set(file);
pAvail->m_pDataAvail = pdfium::MakeUnique<CPDF_DataAvail>(
pAvail->m_FileAvail.get(), pAvail->m_FileRead, true);
- return pAvail;
+ return pAvail.release(); // Caller takes ownership.
}
-DLLEXPORT void STDCALL FPDFAvail_Destroy(FPDF_AVAIL avail) {
- delete (CFPDF_DataAvail*)avail;
+FPDF_EXPORT void FPDF_CALLCONV FPDFAvail_Destroy(FPDF_AVAIL avail) {
+ // Take ownership back from caller and destroy.
+ std::unique_ptr<FPDF_AvailContext>(FPDFAvailContextFromFPDFAvail(avail));
}
-DLLEXPORT int STDCALL FPDFAvail_IsDocAvail(FPDF_AVAIL avail,
- FX_DOWNLOADHINTS* hints) {
- if (!avail || !hints)
+FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsDocAvail(FPDF_AVAIL avail,
+ FX_DOWNLOADHINTS* hints) {
+ if (!avail)
return PDF_DATA_ERROR;
- CFPDF_DownloadHintsWrap hints_wrap(hints);
- return CFPDFDataAvailFromFPDFAvail(avail)->m_pDataAvail->IsDocAvail(
- &hints_wrap);
+ FPDF_DownloadHintsContext hints_context(hints);
+ return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsDocAvail(
+ &hints_context);
}
-DLLEXPORT FPDF_DOCUMENT STDCALL
+FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
FPDFAvail_GetDocument(FPDF_AVAIL avail, FPDF_BYTESTRING password) {
- CFPDF_DataAvail* pDataAvail = static_cast<CFPDF_DataAvail*>(avail);
+ auto* pDataAvail = FPDFAvailContextFromFPDFAvail(avail);
if (!pDataAvail)
return nullptr;
-
- std::unique_ptr<CPDF_Parser> pParser(new CPDF_Parser);
- pParser->SetPassword(password);
-
- std::unique_ptr<CPDF_Document> pDocument(
- new CPDF_Document(std::move(pParser)));
- CPDF_Parser::Error error = pDocument->GetParser()->StartLinearizedParse(
- pDataAvail->m_pDataAvail->GetFileRead(), pDocument.get());
+ CPDF_Parser::Error error;
+ std::unique_ptr<CPDF_Document> document;
+ std::tie(error, document) = pDataAvail->m_pDataAvail->ParseDocument(password);
if (error != CPDF_Parser::SUCCESS) {
ProcessParseError(error);
return nullptr;
}
- pDataAvail->m_pDataAvail->SetDocument(pDocument.get());
- CheckUnSupportError(pDocument.get(), FPDF_ERR_SUCCESS);
- return FPDFDocumentFromCPDFDocument(pDocument.release());
+ CheckUnSupportError(document.get(), FPDF_ERR_SUCCESS);
+ return FPDFDocumentFromCPDFDocument(document.release());
}
-DLLEXPORT int STDCALL FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(doc);
return pDoc ? pDoc->GetParser()->GetFirstPageNo() : 0;
}
-DLLEXPORT int STDCALL FPDFAvail_IsPageAvail(FPDF_AVAIL avail,
- int page_index,
- FX_DOWNLOADHINTS* hints) {
- if (!avail || !hints)
+FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsPageAvail(FPDF_AVAIL avail,
+ int page_index,
+ FX_DOWNLOADHINTS* hints) {
+ if (!avail)
return PDF_DATA_ERROR;
if (page_index < 0)
return PDF_DATA_NOTAVAIL;
- CFPDF_DownloadHintsWrap hints_wrap(hints);
- return CFPDFDataAvailFromFPDFAvail(avail)->m_pDataAvail->IsPageAvail(
- page_index, &hints_wrap);
+ FPDF_DownloadHintsContext hints_context(hints);
+ return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsPageAvail(
+ page_index, &hints_context);
}
-DLLEXPORT int STDCALL FPDFAvail_IsFormAvail(FPDF_AVAIL avail,
- FX_DOWNLOADHINTS* hints) {
- if (!avail || !hints)
+FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsFormAvail(FPDF_AVAIL avail,
+ FX_DOWNLOADHINTS* hints) {
+ if (!avail)
return PDF_FORM_ERROR;
- CFPDF_DownloadHintsWrap hints_wrap(hints);
- return CFPDFDataAvailFromFPDFAvail(avail)->m_pDataAvail->IsFormAvail(
- &hints_wrap);
+ FPDF_DownloadHintsContext hints_context(hints);
+ return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsFormAvail(
+ &hints_context);
}
-DLLEXPORT int STDCALL FPDFAvail_IsLinearized(FPDF_AVAIL avail) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsLinearized(FPDF_AVAIL avail) {
if (!avail)
return PDF_LINEARIZATION_UNKNOWN;
- return CFPDFDataAvailFromFPDFAvail(avail)->m_pDataAvail->IsLinearizedPDF();
+ return FPDFAvailContextFromFPDFAvail(avail)->m_pDataAvail->IsLinearizedPDF();
}
diff --git a/fpdfsdk/fpdf_dataavail_embeddertest.cpp b/fpdfsdk/fpdf_dataavail_embeddertest.cpp
index c226a31..2084153 100644
--- a/fpdfsdk/fpdf_dataavail_embeddertest.cpp
+++ b/fpdfsdk/fpdf_dataavail_embeddertest.cpp
@@ -12,10 +12,25 @@
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/range_set.h"
#include "testing/test_support.h"
#include "testing/utils/path_service.h"
namespace {
+
+class MockDownloadHints : public FX_DOWNLOADHINTS {
+ public:
+ static void SAddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
+ }
+
+ MockDownloadHints() {
+ FX_DOWNLOADHINTS::version = 1;
+ FX_DOWNLOADHINTS::AddSegment = SAddSegment;
+ }
+
+ ~MockDownloadHints() {}
+};
+
class TestAsyncLoader : public FX_DOWNLOADHINTS, FX_FILEAVAIL {
public:
explicit TestAsyncLoader(const std::string& file_name) {
@@ -60,50 +75,25 @@
}
size_t max_already_available_bound() const {
- return available_ranges_.empty() ? 0 : available_ranges_.rbegin()->second;
+ return available_ranges_.IsEmpty()
+ ? 0
+ : available_ranges_.ranges().rbegin()->second;
+ }
+
+ void FlushRequestedData() {
+ for (const auto& it : requested_segments_) {
+ SetDataAvailable(it.first, it.second);
+ }
+ ClearRequestedSegments();
}
private:
void SetDataAvailable(size_t start, size_t size) {
- if (size == 0)
- return;
- const auto range = std::make_pair(start, start + size);
- if (available_ranges_.empty()) {
- available_ranges_.insert(range);
- return;
- }
- auto start_it = available_ranges_.upper_bound(range);
- if (start_it != available_ranges_.begin())
- --start_it; // start now points to the key equal or lower than offset.
- if (start_it->second < range.first)
- ++start_it; // start element is entirely before current range, skip it.
-
- auto end_it = available_ranges_.upper_bound(
- std::make_pair(range.second, range.second));
- if (start_it == end_it) { // No ranges to merge.
- available_ranges_.insert(range);
- return;
- }
-
- --end_it;
-
- size_t new_start = std::min<size_t>(start_it->first, range.first);
- size_t new_end = std::max(end_it->second, range.second);
-
- available_ranges_.erase(start_it, ++end_it);
- available_ranges_.insert(std::make_pair(new_start, new_end));
+ available_ranges_.Union(RangeSet::Range(start, start + size));
}
bool CheckDataAlreadyAvailable(size_t start, size_t size) const {
- if (size == 0)
- return false;
- const auto range = std::make_pair(start, start + size);
- auto it = available_ranges_.upper_bound(range);
- if (it == available_ranges_.begin())
- return false; // No ranges includes range.start().
-
- --it; // Now it starts equal or before range.start().
- return it->second >= range.second;
+ return available_ranges_.Contains(RangeSet::Range(start, start + size));
}
int GetBlockImpl(unsigned long pos, unsigned char* pBuf, unsigned long size) {
@@ -158,14 +148,7 @@
size_t max_requested_bound_ = 0;
bool is_new_data_available_ = true;
- using Range = std::pair<size_t, size_t>;
- struct range_compare {
- bool operator()(const Range& lval, const Range& rval) const {
- return lval.first < rval.first;
- }
- };
- using RangesContainer = std::set<Range, range_compare>;
- RangesContainer available_ranges_;
+ RangeSet available_ranges_;
};
} // namespace
@@ -175,13 +158,15 @@
TEST_F(FPDFDataAvailEmbeddertest, TrailerUnterminated) {
// Document must load without crashing but is too malformed to be available.
EXPECT_FALSE(OpenDocument("trailer_unterminated.pdf"));
- EXPECT_FALSE(FPDFAvail_IsDocAvail(avail_, &hints_));
+ MockDownloadHints hints;
+ EXPECT_FALSE(FPDFAvail_IsDocAvail(avail_, &hints));
}
TEST_F(FPDFDataAvailEmbeddertest, TrailerAsHexstring) {
// Document must load without crashing but is too malformed to be available.
EXPECT_FALSE(OpenDocument("trailer_as_hexstring.pdf"));
- EXPECT_FALSE(FPDFAvail_IsDocAvail(avail_, &hints_));
+ MockDownloadHints hints;
+ EXPECT_FALSE(FPDFAvail_IsDocAvail(avail_, &hints));
}
TEST_F(FPDFDataAvailEmbeddertest, LoadUsingHintTables) {
@@ -194,9 +179,29 @@
// No new data available, to prevent load "Pages" node.
loader.set_is_new_data_available(false);
- FPDF_PAGE page = LoadPage(1);
+ FPDF_PAGE page = FPDF_LoadPage(document(), 1);
EXPECT_TRUE(page);
- UnloadPage(page);
+ FPDF_ClosePage(page);
+}
+
+TEST_F(FPDFDataAvailEmbeddertest, CheckFormAvailIfLinearized) {
+ TestAsyncLoader loader("feature_linearized_loading.pdf");
+ avail_ = FPDFAvail_Create(loader.file_avail(), loader.file_access());
+ ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsDocAvail(avail_, loader.hints()));
+ document_ = FPDFAvail_GetDocument(avail_, nullptr);
+ ASSERT_TRUE(document_);
+
+ // Prevent access to non requested data to coerce the parser to send new
+ // request for non available (non requested before) data.
+ loader.set_is_new_data_available(false);
+ loader.ClearRequestedSegments();
+
+ int status = PDF_FORM_NOTAVAIL;
+ while (status == PDF_FORM_NOTAVAIL) {
+ loader.FlushRequestedData();
+ status = FPDFAvail_IsFormAvail(avail_, loader.hints());
+ }
+ EXPECT_NE(PDF_FORM_ERROR, status);
}
TEST_F(FPDFDataAvailEmbeddertest,
@@ -234,7 +239,35 @@
// Prevent loading data, while page loading.
loader.set_is_new_data_available(false);
- FPDF_PAGE page = LoadPage(first_page_num);
+ FPDF_PAGE page = FPDF_LoadPage(document(), first_page_num);
EXPECT_TRUE(page);
- UnloadPage(page);
+ FPDF_ClosePage(page);
+}
+
+TEST_F(FPDFDataAvailEmbeddertest, LoadSecondPageIfLinearizedWithHints) {
+ TestAsyncLoader loader("feature_linearized_loading.pdf");
+ avail_ = FPDFAvail_Create(loader.file_avail(), loader.file_access());
+ ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsDocAvail(avail_, loader.hints()));
+ document_ = FPDFAvail_GetDocument(avail_, nullptr);
+ ASSERT_TRUE(document_);
+
+ static constexpr uint32_t kSecondPageNum = 1;
+
+ // Prevent access to non requested data to coerce the parser to send new
+ // request for non available (non requested before) data.
+ loader.set_is_new_data_available(false);
+ loader.ClearRequestedSegments();
+
+ int status = PDF_DATA_NOTAVAIL;
+ while (status == PDF_DATA_NOTAVAIL) {
+ loader.FlushRequestedData();
+ status = FPDFAvail_IsPageAvail(avail_, kSecondPageNum, loader.hints());
+ }
+ EXPECT_EQ(PDF_DATA_AVAIL, status);
+
+ // Prevent loading data, while page loading.
+ loader.set_is_new_data_available(false);
+ FPDF_PAGE page = FPDF_LoadPage(document(), kSecondPageNum);
+ EXPECT_TRUE(page);
+ FPDF_ClosePage(page);
}
diff --git a/fpdfsdk/fpdf_ext.cpp b/fpdfsdk/fpdf_ext.cpp
index 3bcb0c0..87605cf 100644
--- a/fpdfsdk/fpdf_ext.cpp
+++ b/fpdfsdk/fpdf_ext.cpp
@@ -14,9 +14,9 @@
#include "core/fpdfdoc/cpdf_annot.h"
#include "core/fpdfdoc/cpdf_interform.h"
#include "core/fpdfdoc/cpdf_metadata.h"
-#include "core/fxcrt/fx_basic.h"
#include "core/fxcrt/fx_memory.h"
-#include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml/cxml_content.h"
+#include "core/fxcrt/xml/cxml_element.h"
#include "fpdfsdk/fsdk_define.h"
#include "third_party/base/ptr_util.h"
@@ -36,7 +36,7 @@
return true;
}
-DLLEXPORT FPDF_BOOL STDCALL
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO* unsp_info) {
if (!unsp_info || unsp_info->version != 1)
return false;
@@ -52,7 +52,7 @@
FPDF_UnSupportError(FPDF_UNSP_ANNOT_3DANNOT);
} else if (nAnnotSubtype == CPDF_Annot::Subtype::SCREEN) {
const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict();
- CFX_ByteString cbString;
+ ByteString cbString;
if (pAnnotDict->KeyExist("IT"))
cbString = pAnnotDict->GetStringFor("IT");
if (cbString.Compare("Img") != 0)
@@ -67,7 +67,7 @@
FPDF_UnSupportError(FPDF_UNSP_ANNOT_ATTACHMENT);
} else if (nAnnotSubtype == CPDF_Annot::Subtype::WIDGET) {
const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict();
- CFX_ByteString cbString;
+ ByteString cbString;
if (pAnnotDict->KeyExist("FT"))
cbString = pAnnotDict->GetStringFor("FT");
if (cbString.Compare("Sig") == 0)
@@ -75,22 +75,23 @@
}
}
-bool CheckSharedForm(const CXML_Element* pElement, CFX_ByteString cbName) {
- int count = pElement->CountAttrs();
- int i = 0;
- for (i = 0; i < count; i++) {
- CFX_ByteString space, name;
- CFX_WideString value;
- pElement->GetAttrByIndex(i, space, name, value);
+bool CheckSharedForm(const CXML_Element* pElement, ByteString cbName) {
+ size_t count = pElement->CountAttrs();
+ for (size_t i = 0; i < count; ++i) {
+ ByteString space;
+ ByteString name;
+ WideString value;
+ pElement->GetAttrByIndex(i, &space, &name, &value);
if (space == "xmlns" && name == "adhocwf" &&
value == L"http://ns.adobe.com/AcrobatAdhocWorkflow/1.0/") {
CXML_Element* pVersion =
- pElement->GetElement("adhocwf", cbName.AsStringC());
+ pElement->GetElement("adhocwf", cbName.AsStringView(), 0);
if (!pVersion)
continue;
- CFX_WideString wsContent = pVersion->GetContent(0);
- int nType = wsContent.GetInteger();
- switch (nType) {
+ CXML_Content* pContent = ToContent(pVersion->GetChild(0));
+ if (!pContent)
+ continue;
+ switch (pContent->m_Content.GetInteger()) {
case 1:
FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_ACROBAT);
break;
@@ -104,14 +105,11 @@
}
}
- uint32_t nCount = pElement->CountChildren();
- for (i = 0; i < (int)nCount; i++) {
- CXML_Element::ChildType childType = pElement->GetChildType(i);
- if (childType == CXML_Element::Element) {
- CXML_Element* pChild = pElement->GetElement(i);
- if (CheckSharedForm(pChild, cbName))
- return true;
- }
+ size_t nCount = pElement->CountChildren();
+ for (size_t i = 0; i < nCount; ++i) {
+ CXML_Element* pChild = ToElement(pElement->GetChild(i));
+ if (pChild && CheckSharedForm(pChild, cbName))
+ return true;
}
return false;
}
@@ -126,9 +124,9 @@
return;
// Portfolios and Packages
- CPDF_Dictionary* pRootDict = pDoc->GetRoot();
+ const CPDF_Dictionary* pRootDict = pDoc->GetRoot();
if (pRootDict) {
- CFX_ByteString cbString;
+ ByteString cbString;
if (pRootDict->KeyExist("Collection")) {
FPDF_UnSupportError(FPDF_UNSP_DOC_PORTABLECOLLECTION);
return;
@@ -144,7 +142,7 @@
CPDF_Array* pArray = pJSDict ? pJSDict->GetArrayFor("Names") : nullptr;
if (pArray) {
for (size_t i = 0; i < pArray->GetCount(); i++) {
- CFX_ByteString cbStr = pArray->GetStringAt(i);
+ ByteString cbStr = pArray->GetStringAt(i);
if (cbStr.Compare("com.adobe.acrobat.SharedReview.Register") == 0) {
FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDREVIEW);
return;
@@ -169,12 +167,12 @@
#endif // PDF_ENABLE_XFA
}
-DLLEXPORT int STDCALL FPDFDoc_GetPageMode(FPDF_DOCUMENT document) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFDoc_GetPageMode(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
return PAGEMODE_UNKNOWN;
- CPDF_Dictionary* pRoot = pDoc->GetRoot();
+ const CPDF_Dictionary* pRoot = pDoc->GetRoot();
if (!pRoot)
return PAGEMODE_UNKNOWN;
@@ -182,7 +180,7 @@
if (!pName)
return PAGEMODE_USENONE;
- CFX_ByteString strPageMode = pName->GetString();
+ ByteString strPageMode = pName->GetString();
if (strPageMode.IsEmpty() || strPageMode.EqualNoCase("UseNone"))
return PAGEMODE_USENONE;
if (strPageMode.EqualNoCase("UseOutlines"))
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index e649bac..4d06693 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -29,29 +29,25 @@
namespace {
-bool IsValiableRect(CFX_FloatRect rect, CFX_FloatRect rcPage) {
- if (rect.left - rect.right > 0.000001f || rect.bottom - rect.top > 0.000001f)
+bool IsValidRect(const CFX_FloatRect& rect, const CFX_FloatRect& rcPage) {
+ constexpr float kMinSize = 0.000001f;
+ if (rect.IsEmpty() || rect.Width() < kMinSize || rect.Height() < kMinSize)
return false;
- if (rect.left == 0.0f && rect.top == 0.0f && rect.right == 0.0f &&
- rect.bottom == 0.0f)
- return false;
+ if (rcPage.IsEmpty())
+ return true;
- if (!rcPage.IsEmpty()) {
- if (rect.left - rcPage.left < -10.000001f ||
- rect.right - rcPage.right > 10.000001f ||
- rect.top - rcPage.top > 10.000001f ||
- rect.bottom - rcPage.bottom < -10.000001f)
- return false;
- }
-
- return true;
+ constexpr float kMinBorderSize = 10.000001f;
+ return rect.left - rcPage.left >= -kMinBorderSize &&
+ rect.right - rcPage.right <= kMinBorderSize &&
+ rect.top - rcPage.top <= kMinBorderSize &&
+ rect.bottom - rcPage.bottom >= -kMinBorderSize;
}
void GetContentsRect(CPDF_Document* pDoc,
CPDF_Dictionary* pDict,
std::vector<CFX_FloatRect>* pRectArray) {
- std::unique_ptr<CPDF_Page> pPDFPage(new CPDF_Page(pDoc, pDict, false));
+ auto pPDFPage = pdfium::MakeUnique<CPDF_Page>(pDoc, pDict, false);
pPDFPage->ParseContent();
for (const auto& pPageObject : *pPDFPage->GetPageObjectList()) {
@@ -60,7 +56,7 @@
rc.right = pPageObject->m_Right;
rc.bottom = pPageObject->m_Bottom;
rc.top = pPageObject->m_Top;
- if (IsValiableRect(rc, pDict->GetRectFor("MediaBox")))
+ if (IsValidRect(rc, pDict->GetRectFor("MediaBox")))
pRectArray->push_back(rc);
}
}
@@ -77,7 +73,7 @@
else if (pStream->KeyExist("BBox"))
rect = pStream->GetRectFor("BBox");
- if (IsValiableRect(rect, pPageDic->GetRectFor("MediaBox")))
+ if (IsValidRect(rect, pPageDic->GetRectFor("MediaBox")))
pRectArray->push_back(rect);
pObjectArray->push_back(pStream);
@@ -96,13 +92,12 @@
if (!pAnnots)
return FLATTEN_NOTHINGTODO;
- uint32_t dwSize = pAnnots->GetCount();
- for (int i = 0; i < (int)dwSize; i++) {
- CPDF_Dictionary* pAnnotDic = ToDictionary(pAnnots->GetDirectObjectAt(i));
+ for (const auto& pAnnot : *pAnnots) {
+ CPDF_Dictionary* pAnnotDic = ToDictionary(pAnnot->GetDirect());
if (!pAnnotDic)
continue;
- CFX_ByteString sSubtype = pAnnotDic->GetStringFor("Subtype");
+ ByteString sSubtype = pAnnotDic->GetStringFor("Subtype");
if (sSubtype == "Popup")
continue;
@@ -110,27 +105,25 @@
if (nAnnotFlag & ANNOTFLAG_HIDDEN)
continue;
- if (nUsage == FLAT_NORMALDISPLAY) {
- if (nAnnotFlag & ANNOTFLAG_INVISIBLE)
- continue;
-
+ bool bParseStream;
+ if (nUsage == FLAT_NORMALDISPLAY)
+ bParseStream = !(nAnnotFlag & ANNOTFLAG_INVISIBLE);
+ else
+ bParseStream = !!(nAnnotFlag & ANNOTFLAG_PRINT);
+ if (bParseStream)
ParserStream(pPageDic, pAnnotDic, pRectArray, pObjectArray);
- } else {
- if (nAnnotFlag & ANNOTFLAG_PRINT)
- ParserStream(pPageDic, pAnnotDic, pRectArray, pObjectArray);
- }
}
return FLATTEN_SUCCESS;
}
-FX_FLOAT GetMinMaxValue(const std::vector<CFX_FloatRect>& array,
- FPDF_TYPE type,
- FPDF_VALUE value) {
- size_t nRects = array.size();
- if (nRects <= 0)
+float GetMinMaxValue(const std::vector<CFX_FloatRect>& array,
+ FPDF_TYPE type,
+ FPDF_VALUE value) {
+ if (array.empty())
return 0.0f;
- std::vector<FX_FLOAT> pArray(nRects);
+ size_t nRects = array.size();
+ std::vector<float> pArray(nRects);
switch (value) {
case LEFT:
for (size_t i = 0; i < nRects; i++)
@@ -149,11 +142,11 @@
pArray[i] = array[i].bottom;
break;
default:
- // Not reachable.
+ NOTREACHED();
return 0.0f;
}
- FX_FLOAT fRet = pArray[0];
+ float fRet = pArray[0];
if (type == MAX) {
for (size_t i = 1; i < nRects; i++)
fRet = std::max(fRet, pArray[i]);
@@ -175,18 +168,18 @@
return rcRet;
}
-uint32_t NewIndirectContentsStream(const CFX_ByteString& key,
+uint32_t NewIndirectContentsStream(const ByteString& key,
CPDF_Document* pDocument) {
CPDF_Stream* pNewContents = pDocument->NewIndirect<CPDF_Stream>(
nullptr, 0,
pdfium::MakeUnique<CPDF_Dictionary>(pDocument->GetByteStringPool()));
- CFX_ByteString sStream;
- sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
+ ByteString sStream =
+ ByteString::Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
pNewContents->SetData(sStream.raw_str(), sStream.GetLength());
return pNewContents->GetObjNum();
}
-void SetPageContents(const CFX_ByteString& key,
+void SetPageContents(const ByteString& key,
CPDF_Dictionary* pPage,
CPDF_Document* pDocument) {
CPDF_Array* pContentsArray = nullptr;
@@ -204,13 +197,13 @@
pPage->ConvertToIndirectObjectFor("Contents", pDocument);
if (!pContentsArray) {
pContentsArray = pDocument->NewIndirect<CPDF_Array>();
- CPDF_StreamAcc acc;
- acc.LoadAllData(pContentsStream);
- CFX_ByteString sStream = "q\n";
- CFX_ByteString sBody =
- CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize());
+ auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pContentsStream);
+ pAcc->LoadAllDataFiltered();
+ ByteString sStream = "q\n";
+ ByteString sBody = ByteString(pAcc->GetData(), pAcc->GetSize());
sStream = sStream + sBody + "\nQ";
- pContentsStream->SetData(sStream.raw_str(), sStream.GetLength());
+ pContentsStream->SetDataAndRemoveFilter(sStream.raw_str(),
+ sStream.GetLength());
pContentsArray->AddNew<CPDF_Reference>(pDocument,
pContentsStream->GetObjNum());
pPage->SetNewFor<CPDF_Reference>("Contents", pDocument,
@@ -228,26 +221,26 @@
if (rcStream.IsEmpty())
return CFX_Matrix();
- matrix.TransformRect(rcStream);
+ rcStream = matrix.TransformRect(rcStream);
rcStream.Normalize();
- FX_FLOAT a = rcAnnot.Width() / rcStream.Width();
- FX_FLOAT d = rcAnnot.Height() / rcStream.Height();
+ float a = rcAnnot.Width() / rcStream.Width();
+ float d = rcAnnot.Height() / rcStream.Height();
- FX_FLOAT e = rcAnnot.left - rcStream.left * a;
- FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d;
+ float e = rcAnnot.left - rcStream.left * a;
+ float f = rcAnnot.bottom - rcStream.bottom * d;
return CFX_Matrix(a, 0, 0, d, e, f);
}
} // namespace
-DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFPage_Flatten(FPDF_PAGE page, int nFlag) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!page)
return FLATTEN_FAIL;
- CPDF_Document* pDocument = pPage->m_pDocument;
- CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
+ CPDF_Document* pDocument = pPage->m_pDocument.Get();
+ CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get();
if (!pDocument || !pPageDict)
return FLATTEN_FAIL;
@@ -305,15 +298,16 @@
if (!pPageXObject)
pPageXObject = pRes->SetNewFor<CPDF_Dictionary>("XObject");
- CFX_ByteString key = "";
- int nStreams = pdfium::CollectionSize<int>(ObjectArray);
- if (nStreams > 0) {
- for (int iKey = 0; /*iKey < 100*/; iKey++) {
- char sExtend[5] = {};
- FXSYS_itoa(iKey, sExtend, 10);
- key = CFX_ByteString("FFT") + CFX_ByteString(sExtend);
- if (!pPageXObject->KeyExist(key))
+ ByteString key;
+ if (!ObjectArray.empty()) {
+ int i = 0;
+ while (i < INT_MAX) {
+ ByteString sKey = ByteString::Format("FFT%d", i);
+ if (!pPageXObject->KeyExist(sKey)) {
+ key = sKey;
break;
+ }
+ ++i;
}
}
@@ -327,12 +321,11 @@
pNewOXbjectDic->SetNewFor<CPDF_Name>("Type", "XObject");
pNewOXbjectDic->SetNewFor<CPDF_Name>("Subtype", "Form");
pNewOXbjectDic->SetNewFor<CPDF_Number>("FormType", 1);
- pNewOXbjectDic->SetNewFor<CPDF_Name>("Name", "FRM");
CFX_FloatRect rcBBox = pPageDict->GetRectFor("ArtBox");
pNewOXbjectDic->SetRectFor("BBox", rcBBox);
}
- for (int i = 0; i < nStreams; i++) {
+ for (size_t i = 0; i < ObjectArray.size(); ++i) {
CPDF_Dictionary* pAnnotDic = ObjectArray[i];
if (!pAnnotDic)
continue;
@@ -340,7 +333,7 @@
CFX_FloatRect rcAnnot = pAnnotDic->GetRectFor("Rect");
rcAnnot.Normalize();
- CFX_ByteString sAnnotState = pAnnotDic->GetStringFor("AS");
+ ByteString sAnnotState = pAnnotDic->GetStringFor("AS");
CPDF_Dictionary* pAnnotAP = pAnnotDic->GetDictFor("AP");
if (!pAnnotAP)
continue;
@@ -354,9 +347,8 @@
if (!sAnnotState.IsEmpty()) {
pAPStream = pAPDic->GetStreamFor(sAnnotState);
} else {
- auto it = pAPDic->begin();
- if (it != pAPDic->end()) {
- CPDF_Object* pFirstObj = it->second.get();
+ if (pAPDic->GetCount() > 0) {
+ CPDF_Object* pFirstObj = pAPDic->begin()->second.get();
if (pFirstObj) {
if (pFirstObj->IsReference())
pFirstObj = pFirstObj->GetDirect();
@@ -397,32 +389,18 @@
if (!pXObject)
pXObject = pNewXORes->SetNewFor<CPDF_Dictionary>("XObject");
- CFX_ByteString sFormName;
- sFormName.Format("F%d", i);
+ ByteString sFormName = ByteString::Format("F%d", i);
pXObject->SetNewFor<CPDF_Reference>(sFormName, pDocument,
pObj->GetObjNum());
- CPDF_StreamAcc acc;
- acc.LoadAllData(pNewXObject);
-
- const uint8_t* pData = acc.GetData();
- CFX_ByteString sStream(pData, acc.GetSize());
+ auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pNewXObject);
+ pAcc->LoadAllDataFiltered();
+ ByteString sStream(pAcc->GetData(), pAcc->GetSize());
CFX_Matrix matrix = pAPDic->GetMatrixFor("Matrix");
- if (matrix.IsIdentity()) {
- matrix.a = 1.0f;
- matrix.b = 0.0f;
- matrix.c = 0.0f;
- matrix.d = 1.0f;
- matrix.e = 0.0f;
- matrix.f = 0.0f;
- }
-
- CFX_ByteString sTemp;
CFX_Matrix m = GetMatrix(rcAnnot, rcStream, matrix);
- sTemp.Format("q %f 0 0 %f %f %f cm /%s Do Q\n", m.a, m.d, m.e, m.f,
- sFormName.c_str());
- sStream += sTemp;
- pNewXObject->SetData(sStream.raw_str(), sStream.GetLength());
+ sStream += ByteString::Format("q %f 0 0 %f %f %f cm /%s Do Q\n", m.a, m.d,
+ m.e, m.f, sFormName.c_str());
+ pNewXObject->SetDataAndRemoveFilter(sStream.raw_str(), sStream.GetLength());
}
pPageDict->RemoveFor("Annots");
return FLATTEN_SUCCESS;
diff --git a/fpdfsdk/fpdf_flatten_embeddertest.cpp b/fpdfsdk/fpdf_flatten_embeddertest.cpp
index d709f59..a8915fe 100644
--- a/fpdfsdk/fpdf_flatten_embeddertest.cpp
+++ b/fpdfsdk/fpdf_flatten_embeddertest.cpp
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "core/fxcrt/fx_basic.h"
#include "public/fpdf_flatten.h"
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
diff --git a/fpdfsdk/fpdf_progressive.cpp b/fpdfsdk/fpdf_progressive.cpp
index cc09d07..730ba48 100644
--- a/fpdfsdk/fpdf_progressive.cpp
+++ b/fpdfsdk/fpdf_progressive.cpp
@@ -6,11 +6,13 @@
#include "public/fpdf_progressive.h"
+#include <utility>
+
#include "core/fpdfapi/cpdf_pagerendercontext.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
#include "core/fxcrt/fx_memory.h"
-#include "core/fxge/cfx_fxgedevice.h"
+#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_renderdevice.h"
#include "fpdfsdk/fsdk_define.h"
#include "fpdfsdk/fsdk_pauseadapter.h"
@@ -18,25 +20,25 @@
#include "third_party/base/ptr_util.h"
// These checks are here because core/ and public/ cannot depend on each other.
-static_assert(CPDF_ProgressiveRenderer::Ready == FPDF_RENDER_READER,
+static_assert(CPDF_ProgressiveRenderer::Ready == FPDF_RENDER_READY,
"CPDF_ProgressiveRenderer::Ready value mismatch");
static_assert(CPDF_ProgressiveRenderer::ToBeContinued ==
- FPDF_RENDER_TOBECOUNTINUED,
+ FPDF_RENDER_TOBECONTINUED,
"CPDF_ProgressiveRenderer::ToBeContinued value mismatch");
static_assert(CPDF_ProgressiveRenderer::Done == FPDF_RENDER_DONE,
"CPDF_ProgressiveRenderer::Done value mismatch");
static_assert(CPDF_ProgressiveRenderer::Failed == FPDF_RENDER_FAILED,
"CPDF_ProgressiveRenderer::Failed value mismatch");
-DLLEXPORT int STDCALL FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap,
- FPDF_PAGE page,
- int start_x,
- int start_y,
- int size_x,
- int size_y,
- int rotate,
- int flags,
- IFSDK_PAUSE* pause) {
+FPDF_EXPORT int FPDF_CALLCONV FPDF_RenderPageBitmap_Start(FPDF_BITMAP bitmap,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags,
+ IFSDK_PAUSE* pause) {
if (!bitmap || !pause || pause->version != 1)
return FPDF_RENDER_FAILED;
@@ -44,17 +46,24 @@
if (!pPage)
return FPDF_RENDER_FAILED;
- CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
- pPage->SetRenderContext(pdfium::WrapUnique(pContext));
- CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
- pContext->m_pDevice.reset(pDevice);
- CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
+ auto pOwnedContext = pdfium::MakeUnique<CPDF_PageRenderContext>();
+ CPDF_PageRenderContext* pContext = pOwnedContext.get();
+ pPage->SetRenderContext(std::move(pOwnedContext));
+
+ RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
+ auto pOwnedDevice = pdfium::MakeUnique<CFX_DefaultRenderDevice>();
+ CFX_DefaultRenderDevice* pDevice = pOwnedDevice.get();
+ pContext->m_pDevice = std::move(pOwnedDevice);
pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
IFSDK_PAUSE_Adapter IPauseAdapter(pause);
FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
rotate, flags, false, &IPauseAdapter);
+#ifdef _SKIA_SUPPORT_PATHS_
+ pDevice->Flush(false);
+ pBitmap->UnPreMultiply();
+#endif
if (pContext->m_pRenderer) {
return CPDF_ProgressiveRenderer::ToFPDFStatus(
pContext->m_pRenderer->GetStatus());
@@ -62,8 +71,8 @@
return FPDF_RENDER_FAILED;
}
-DLLEXPORT int STDCALL FPDF_RenderPage_Continue(FPDF_PAGE page,
- IFSDK_PAUSE* pause) {
+FPDF_EXPORT int FPDF_CALLCONV FPDF_RenderPage_Continue(FPDF_PAGE page,
+ IFSDK_PAUSE* pause) {
if (!pause || pause->version != 1)
return FPDF_RENDER_FAILED;
@@ -75,21 +84,28 @@
if (pContext && pContext->m_pRenderer) {
IFSDK_PAUSE_Adapter IPauseAdapter(pause);
pContext->m_pRenderer->Continue(&IPauseAdapter);
+#ifdef _SKIA_SUPPORT_PATHS_
+ CFX_RenderDevice* pDevice = pContext->m_pDevice.get();
+ pDevice->Flush(false);
+ pDevice->GetBitmap()->UnPreMultiply();
+#endif
return CPDF_ProgressiveRenderer::ToFPDFStatus(
pContext->m_pRenderer->GetStatus());
}
return FPDF_RENDER_FAILED;
}
-DLLEXPORT void STDCALL FPDF_RenderPage_Close(FPDF_PAGE page) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage_Close(FPDF_PAGE page) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
- if (!pPage)
- return;
-
- CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
- if (!pContext)
- return;
-
- pContext->m_pDevice->RestoreState(false);
- pPage->SetRenderContext(nullptr);
+ if (pPage) {
+#ifdef _SKIA_SUPPORT_PATHS_
+ CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
+ if (pContext && pContext->m_pRenderer) {
+ CFX_RenderDevice* pDevice = pContext->m_pDevice.get();
+ pDevice->Flush(true);
+ pDevice->GetBitmap()->UnPreMultiply();
+ }
+#endif
+ pPage->SetRenderContext(nullptr);
+ }
}
diff --git a/fpdfsdk/fpdf_searchex.cpp b/fpdfsdk/fpdf_searchex.cpp
index f82db37..9d48ceb 100644
--- a/fpdfsdk/fpdf_searchex.cpp
+++ b/fpdfsdk/fpdf_searchex.cpp
@@ -8,10 +8,18 @@
#include "core/fpdftext/cpdf_textpage.h"
-DLLEXPORT int STDCALL
+FPDF_EXPORT int FPDF_CALLCONV
FPDFText_GetCharIndexFromTextIndex(FPDF_TEXTPAGE text_page, int nTextIndex) {
if (!text_page)
return -1;
return static_cast<CPDF_TextPage*>(text_page)
->CharIndexFromTextIndex(nTextIndex);
}
+
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFText_GetTextIndexFromCharIndex(FPDF_TEXTPAGE text_page, int nCharIndex) {
+ if (!text_page)
+ return -1;
+ return static_cast<CPDF_TextPage*>(text_page)->TextIndexFromCharIndex(
+ nCharIndex);
+}
diff --git a/fpdfsdk/fpdf_structtree.cpp b/fpdfsdk/fpdf_structtree.cpp
index 5a922a1..676824e 100644
--- a/fpdfsdk/fpdf_structtree.cpp
+++ b/fpdfsdk/fpdf_structtree.cpp
@@ -8,82 +8,124 @@
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
-#include "core/fpdfdoc/fpdf_tagged.h"
+#include "core/fpdfdoc/cpdf_structelement.h"
+#include "core/fpdfdoc/cpdf_structtree.h"
#include "fpdfsdk/fsdk_define.h"
namespace {
-IPDF_StructTree* ToStructTree(FPDF_STRUCTTREE struct_tree) {
- return reinterpret_cast<IPDF_StructTree*>(struct_tree);
+CPDF_StructTree* ToStructTree(FPDF_STRUCTTREE struct_tree) {
+ return static_cast<CPDF_StructTree*>(struct_tree);
}
-IPDF_StructElement* ToStructTreeElement(FPDF_STRUCTELEMENT struct_element) {
- return reinterpret_cast<IPDF_StructElement*>(struct_element);
+CPDF_StructElement* ToStructTreeElement(FPDF_STRUCTELEMENT struct_element) {
+ return static_cast<CPDF_StructElement*>(struct_element);
+}
+
+unsigned long WideStringToBuffer(const WideString& str,
+ void* buffer,
+ unsigned long buflen) {
+ if (str.IsEmpty())
+ return 0;
+
+ ByteString encodedStr = str.UTF16LE_Encode();
+ const unsigned long len = encodedStr.GetLength();
+ if (buffer && len <= buflen)
+ memcpy(buffer, encodedStr.c_str(), len);
+ return len;
}
} // namespace
-DLLEXPORT FPDF_STRUCTTREE STDCALL FPDF_StructTree_GetForPage(FPDF_PAGE page) {
+FPDF_EXPORT FPDF_STRUCTTREE FPDF_CALLCONV
+FPDF_StructTree_GetForPage(FPDF_PAGE page) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return nullptr;
- return IPDF_StructTree::LoadPage(pPage->m_pDocument, pPage->m_pFormDict)
+ return CPDF_StructTree::LoadPage(pPage->m_pDocument.Get(),
+ pPage->m_pFormDict.Get())
.release();
}
-DLLEXPORT void STDCALL FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree) {
- std::unique_ptr<IPDF_StructTree>(ToStructTree(struct_tree));
+FPDF_EXPORT void FPDF_CALLCONV
+FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree) {
+ std::unique_ptr<CPDF_StructTree>(ToStructTree(struct_tree));
}
-DLLEXPORT int STDCALL
+FPDF_EXPORT int FPDF_CALLCONV
FPDF_StructTree_CountChildren(FPDF_STRUCTTREE struct_tree) {
- IPDF_StructTree* tree = ToStructTree(struct_tree);
- return tree ? tree->CountTopElements() : -1;
+ CPDF_StructTree* tree = ToStructTree(struct_tree);
+ if (!tree)
+ return -1;
+
+ pdfium::base::CheckedNumeric<int> tmp_size = tree->CountTopElements();
+ return tmp_size.ValueOrDefault(-1);
}
-DLLEXPORT FPDF_STRUCTELEMENT STDCALL
+FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV
FPDF_StructTree_GetChildAtIndex(FPDF_STRUCTTREE struct_tree, int index) {
- IPDF_StructTree* tree = ToStructTree(struct_tree);
- if (!tree || index < 0 || index >= tree->CountTopElements())
+ CPDF_StructTree* tree = ToStructTree(struct_tree);
+ if (!tree || index < 0 ||
+ static_cast<size_t>(index) >= tree->CountTopElements()) {
return nullptr;
- return tree->GetTopElement(index);
+ }
+ return tree->GetTopElement(static_cast<size_t>(index));
}
-DLLEXPORT unsigned long STDCALL
+FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDF_StructElement_GetAltText(FPDF_STRUCTELEMENT struct_element,
void* buffer,
unsigned long buflen) {
- IPDF_StructElement* elem = ToStructTreeElement(struct_element);
- if (!elem)
- return 0;
-
- CPDF_Dictionary* dict = elem->GetDict();
- if (!dict)
- return 0;
-
- CFX_WideString str = elem->GetDict()->GetUnicodeTextFor("Alt");
- if (str.IsEmpty())
- return 0;
-
- CFX_ByteString encodedStr = str.UTF16LE_Encode();
- const unsigned long len = encodedStr.GetLength();
- if (buffer && len <= buflen)
- FXSYS_memcpy(buffer, encodedStr.c_str(), len);
- return len;
+ CPDF_StructElement* elem = ToStructTreeElement(struct_element);
+ return (elem && elem->GetDict())
+ ? WideStringToBuffer(elem->GetDict()->GetUnicodeTextFor("Alt"),
+ buffer, buflen)
+ : 0;
}
-DLLEXPORT int STDCALL
+FPDF_EXPORT int FPDF_CALLCONV
+FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element) {
+ CPDF_StructElement* elem = ToStructTreeElement(struct_element);
+ CPDF_Object* p =
+ (elem && elem->GetDict()) ? elem->GetDict()->GetObjectFor("K") : nullptr;
+ return p && p->IsNumber() ? p->GetInteger() : -1;
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDF_StructElement_GetType(FPDF_STRUCTELEMENT struct_element,
+ void* buffer,
+ unsigned long buflen) {
+ CPDF_StructElement* elem = ToStructTreeElement(struct_element);
+ return elem ? WideStringToBuffer(elem->GetType().UTF8Decode(), buffer, buflen)
+ : 0;
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDF_StructElement_GetTitle(FPDF_STRUCTELEMENT struct_element,
+ void* buffer,
+ unsigned long buflen) {
+ CPDF_StructElement* elem = ToStructTreeElement(struct_element);
+ return elem
+ ? WideStringToBuffer(elem->GetTitle().UTF8Decode(), buffer, buflen)
+ : 0;
+}
+
+FPDF_EXPORT int FPDF_CALLCONV
FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element) {
- IPDF_StructElement* elem = ToStructTreeElement(struct_element);
- return elem ? elem->CountKids() : -1;
+ CPDF_StructElement* elem = ToStructTreeElement(struct_element);
+ if (!elem)
+ return -1;
+
+ pdfium::base::CheckedNumeric<int> tmp_size = elem->CountKids();
+ return tmp_size.ValueOrDefault(-1);
}
-DLLEXPORT FPDF_STRUCTELEMENT STDCALL
+FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV
FPDF_StructElement_GetChildAtIndex(FPDF_STRUCTELEMENT struct_element,
int index) {
- IPDF_StructElement* elem = ToStructTreeElement(struct_element);
- if (!elem || index < 0 || index >= elem->CountKids())
+ CPDF_StructElement* elem = ToStructTreeElement(struct_element);
+ if (!elem || index < 0 || static_cast<size_t>(index) >= elem->CountKids())
return nullptr;
- return elem->GetKidIfElement(index);
+ return elem->GetKidIfElement(static_cast<size_t>(index));
}
diff --git a/fpdfsdk/fpdf_structtree_embeddertest.cpp b/fpdfsdk/fpdf_structtree_embeddertest.cpp
index 58b3172..7ca81f7 100644
--- a/fpdfsdk/fpdf_structtree_embeddertest.cpp
+++ b/fpdfsdk/fpdf_structtree_embeddertest.cpp
@@ -6,8 +6,9 @@
#include "public/fpdf_structtree.h"
#include "testing/embedder_test.h"
#include "testing/test_support.h"
+#include "third_party/base/optional.h"
-class FPDFStructTreeEmbeddertest : public EmbedderTest, public TestSaver {};
+class FPDFStructTreeEmbeddertest : public EmbedderTest {};
TEST_F(FPDFStructTreeEmbeddertest, GetAltText) {
ASSERT_TRUE(OpenDocument("tagged_alt_text.pdf"));
@@ -24,6 +25,7 @@
EXPECT_EQ(nullptr, element);
element = FPDF_StructTree_GetChildAtIndex(struct_tree, 0);
ASSERT_NE(nullptr, element);
+ EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(element));
EXPECT_EQ(0U, FPDF_StructElement_GetAltText(element, nullptr, 0));
ASSERT_EQ(1, FPDF_StructElement_CountChildren(element));
@@ -34,6 +36,7 @@
EXPECT_EQ(nullptr, child_element);
child_element = FPDF_StructElement_GetChildAtIndex(element, 0);
ASSERT_NE(nullptr, child_element);
+ EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(child_element));
EXPECT_EQ(0U, FPDF_StructElement_GetAltText(child_element, nullptr, 0));
ASSERT_EQ(1, FPDF_StructElement_CountChildren(child_element));
@@ -44,6 +47,7 @@
EXPECT_EQ(nullptr, gchild_element);
gchild_element = FPDF_StructElement_GetChildAtIndex(child_element, 0);
ASSERT_NE(nullptr, gchild_element);
+ EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(gchild_element));
ASSERT_EQ(24U, FPDF_StructElement_GetAltText(gchild_element, nullptr, 0));
unsigned short buffer[12];
@@ -54,11 +58,12 @@
for (size_t i = 0; i < FX_ArraySize(buffer); ++i)
EXPECT_EQ(0U, buffer[i]);
+ EXPECT_EQ(-1, FPDF_StructElement_GetMarkedContentID(gchild_element));
ASSERT_EQ(24U, FPDF_StructElement_GetAltText(gchild_element, buffer,
sizeof(buffer)));
- const FX_WCHAR kExpected[] = L"Black Image";
- EXPECT_EQ(CFX_WideString(kExpected),
- CFX_WideString::FromUTF16LE(buffer, FXSYS_len(kExpected)));
+ const wchar_t kExpected[] = L"Black Image";
+ EXPECT_EQ(WideString(kExpected),
+ WideString::FromUTF16LE(buffer, FXSYS_len(kExpected)));
ASSERT_EQ(1, FPDF_StructElement_CountChildren(gchild_element));
FPDF_STRUCTELEMENT ggchild_element =
@@ -68,3 +73,48 @@
FPDF_StructTree_Close(struct_tree);
FPDF_ClosePage(page);
}
+
+TEST_F(FPDFStructTreeEmbeddertest, GetMarkedContentID) {
+ ASSERT_TRUE(OpenDocument("marked_content_id.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ FPDF_STRUCTTREE struct_tree = FPDF_StructTree_GetForPage(page);
+ ASSERT_TRUE(struct_tree);
+ ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree));
+
+ FPDF_STRUCTELEMENT element = FPDF_StructTree_GetChildAtIndex(struct_tree, 0);
+ EXPECT_EQ(0, FPDF_StructElement_GetMarkedContentID(element));
+
+ FPDF_StructTree_Close(struct_tree);
+ FPDF_ClosePage(page);
+}
+
+TEST_F(FPDFStructTreeEmbeddertest, GetType) {
+ ASSERT_TRUE(OpenDocument("tagged_alt_text.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ FPDF_STRUCTTREE struct_tree = FPDF_StructTree_GetForPage(page);
+ ASSERT_TRUE(struct_tree);
+ ASSERT_EQ(1, FPDF_StructTree_CountChildren(struct_tree));
+
+ FPDF_STRUCTELEMENT element = FPDF_StructTree_GetChildAtIndex(struct_tree, 0);
+ ASSERT_NE(nullptr, element);
+
+ unsigned short buffer[12];
+ memset(buffer, 0, sizeof(buffer));
+ // Deliberately pass in a small buffer size to make sure |buffer| remains
+ // untouched.
+ ASSERT_EQ(18U, FPDF_StructElement_GetType(element, buffer, 1));
+ for (size_t i = 0; i < FX_ArraySize(buffer); ++i)
+ EXPECT_EQ(0U, buffer[i]);
+
+ ASSERT_EQ(18U, FPDF_StructElement_GetType(element, buffer, sizeof(buffer)));
+ const wchar_t kExpected[] = L"Document";
+ EXPECT_EQ(WideString(kExpected),
+ WideString::FromUTF16LE(buffer, FXSYS_len(kExpected)));
+
+ FPDF_StructTree_Close(struct_tree);
+ FPDF_ClosePage(page);
+}
diff --git a/fpdfsdk/fpdf_sysfontinfo.cpp b/fpdfsdk/fpdf_sysfontinfo.cpp
index 1b62dc4..97d02e8 100644
--- a/fpdfsdk/fpdf_sysfontinfo.cpp
+++ b/fpdfsdk/fpdf_sysfontinfo.cpp
@@ -8,12 +8,28 @@
#include <memory>
+#include "core/fxcrt/fx_codepage.h"
#include "core/fxge/cfx_fontmapper.h"
+#include "core/fxge/cfx_fontmgr.h"
#include "core/fxge/cfx_gemodule.h"
#include "core/fxge/fx_font.h"
#include "core/fxge/ifx_systemfontinfo.h"
#include "fpdfsdk/fsdk_define.h"
-#include "fpdfsdk/pdfwindow/PWL_FontMap.h"
+#include "fpdfsdk/pwl/cpwl_font_map.h"
+#include "third_party/base/ptr_util.h"
+
+static_assert(FXFONT_ANSI_CHARSET == FX_CHARSET_ANSI, "Charset must match");
+static_assert(FXFONT_DEFAULT_CHARSET == FX_CHARSET_Default,
+ "Charset must match");
+static_assert(FXFONT_SYMBOL_CHARSET == FX_CHARSET_Symbol, "Charset must match");
+static_assert(FXFONT_SHIFTJIS_CHARSET == FX_CHARSET_ShiftJIS,
+ "Charset must match");
+static_assert(FXFONT_HANGEUL_CHARSET == FX_CHARSET_Hangul,
+ "Charset must match");
+static_assert(FXFONT_GB2312_CHARSET == FX_CHARSET_ChineseSimplified,
+ "Charset must match");
+static_assert(FXFONT_CHINESEBIG5_CHARSET == FX_CHARSET_ChineseTraditional,
+ "Charset must match");
class CFX_ExternalFontInfo final : public IFX_SystemFontInfo {
public:
@@ -35,15 +51,16 @@
bool bItalic,
int charset,
int pitch_family,
- const FX_CHAR* family,
- int& iExact) override {
+ const char* family) override {
if (!m_pInfo->MapFont)
return nullptr;
+
+ int iExact;
return m_pInfo->MapFont(m_pInfo, weight, bItalic, charset, pitch_family,
family, &iExact);
}
- void* GetFont(const FX_CHAR* family) override {
+ void* GetFont(const char* family) override {
if (!m_pInfo->GetFont)
return nullptr;
return m_pInfo->GetFont(m_pInfo, family);
@@ -58,7 +75,7 @@
return m_pInfo->GetFontData(m_pInfo, hFont, table, buffer, size);
}
- bool GetFaceName(void* hFont, CFX_ByteString& name) override {
+ bool GetFaceName(void* hFont, ByteString* name) override {
if (!m_pInfo->GetFaceName)
return false;
uint32_t size = m_pInfo->GetFaceName(m_pInfo, hFont, nullptr, 0);
@@ -66,16 +83,16 @@
return false;
char* buffer = FX_Alloc(char, size);
size = m_pInfo->GetFaceName(m_pInfo, hFont, buffer, size);
- name = CFX_ByteString(buffer, size);
+ *name = ByteString(buffer, size);
FX_Free(buffer);
return true;
}
- bool GetFontCharset(void* hFont, int& charset) override {
+ bool GetFontCharset(void* hFont, int* charset) override {
if (!m_pInfo->GetFontCharset)
return false;
- charset = m_pInfo->GetFontCharset(m_pInfo, hFont);
+ *charset = m_pInfo->GetFontCharset(m_pInfo, hFont);
return true;
}
@@ -88,34 +105,33 @@
FPDF_SYSFONTINFO* const m_pInfo;
};
-DLLEXPORT void STDCALL FPDF_AddInstalledFont(void* mapper,
- const char* name,
- int charset) {
- CFX_FontMapper* pMapper = reinterpret_cast<CFX_FontMapper*>(mapper);
+FPDF_EXPORT void FPDF_CALLCONV FPDF_AddInstalledFont(void* mapper,
+ const char* name,
+ int charset) {
+ CFX_FontMapper* pMapper = static_cast<CFX_FontMapper*>(mapper);
pMapper->AddInstalledFont(name, charset);
}
-DLLEXPORT void STDCALL FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO* pFontInfoExt) {
+FPDF_EXPORT void FPDF_CALLCONV
+FPDF_SetSystemFontInfo(FPDF_SYSFONTINFO* pFontInfoExt) {
if (pFontInfoExt->version != 1)
return;
CFX_GEModule::Get()->GetFontMgr()->SetSystemFontInfo(
- std::unique_ptr<IFX_SystemFontInfo>(
- new CFX_ExternalFontInfo(pFontInfoExt)));
+ pdfium::MakeUnique<CFX_ExternalFontInfo>(pFontInfoExt));
}
-DLLEXPORT const FPDF_CharsetFontMap* STDCALL FPDF_GetDefaultTTFMap() {
+FPDF_EXPORT const FPDF_CharsetFontMap* FPDF_CALLCONV FPDF_GetDefaultTTFMap() {
return CPWL_FontMap::defaultTTFMap;
}
struct FPDF_SYSFONTINFO_DEFAULT : public FPDF_SYSFONTINFO {
- IFX_SystemFontInfo* m_pFontInfo;
+ UnownedPtr<IFX_SystemFontInfo> m_pFontInfo;
};
static void DefaultRelease(struct _FPDF_SYSFONTINFO* pThis) {
auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
- // TODO(thestig): Should this be set to nullptr too?
- delete pDefault->m_pFontInfo;
+ delete pDefault->m_pFontInfo.Release();
}
static void DefaultEnumFonts(struct _FPDF_SYSFONTINFO* pThis, void* pMapper) {
@@ -132,7 +148,7 @@
int* bExact) {
auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
return pDefault->m_pFontInfo->MapFont(weight, !!bItalic, charset,
- pitch_family, family, *bExact);
+ pitch_family, family);
}
void* DefaultGetFont(struct _FPDF_SYSFONTINFO* pThis, const char* family) {
@@ -153,20 +169,22 @@
void* hFont,
char* buffer,
unsigned long buf_size) {
- CFX_ByteString name;
+ ByteString name;
auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
- if (!pDefault->m_pFontInfo->GetFaceName(hFont, name))
+ if (!pDefault->m_pFontInfo->GetFaceName(hFont, &name))
return 0;
- if (name.GetLength() >= (long)buf_size)
+ if (name.GetLength() >= static_cast<size_t>(buf_size))
return name.GetLength() + 1;
- FXSYS_strcpy(buffer, name.c_str());
+
+ strncpy(buffer, name.c_str(),
+ (name.GetLength() + 1) * sizeof(ByteString::CharType));
return name.GetLength() + 1;
}
static int DefaultGetFontCharset(struct _FPDF_SYSFONTINFO* pThis, void* hFont) {
int charset;
auto* pDefault = static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pThis);
- if (!pDefault->m_pFontInfo->GetFontCharset(hFont, charset))
+ if (!pDefault->m_pFontInfo->GetFontCharset(hFont, &charset))
return 0;
return charset;
}
@@ -176,7 +194,7 @@
pDefault->m_pFontInfo->DeleteFont(hFont);
}
-DLLEXPORT FPDF_SYSFONTINFO* STDCALL FPDF_GetDefaultSystemFontInfo() {
+FPDF_EXPORT FPDF_SYSFONTINFO* FPDF_CALLCONV FPDF_GetDefaultSystemFontInfo() {
std::unique_ptr<IFX_SystemFontInfo> pFontInfo =
IFX_SystemFontInfo::CreateDefault(nullptr);
if (!pFontInfo)
@@ -197,7 +215,7 @@
return pFontInfoExt;
}
-DLLEXPORT void FPDF_FreeDefaultSystemFontInfo(
- FPDF_SYSFONTINFO* pDefaultFontInfo) {
+FPDF_EXPORT void FPDF_CALLCONV
+FPDF_FreeDefaultSystemFontInfo(FPDF_SYSFONTINFO* pDefaultFontInfo) {
FX_Free(static_cast<FPDF_SYSFONTINFO_DEFAULT*>(pDefaultFontInfo));
}
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index 3427f4e..565d90b 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -6,6 +6,8 @@
#include "public/fpdf_transformpage.h"
+#include <memory>
+#include <sstream>
#include <vector>
#include "core/fpdfapi/page/cpdf_clippath.h"
@@ -23,7 +25,7 @@
namespace {
void SetBoundingBox(CPDF_Page* page,
- const CFX_ByteString& key,
+ const ByteString& key,
float left,
float bottom,
float right,
@@ -36,7 +38,7 @@
}
bool GetBoundingBox(CPDF_Page* page,
- const CFX_ByteString& key,
+ const ByteString& key,
float* left,
float* bottom,
float* right,
@@ -52,13 +54,17 @@
return true;
}
+CPDF_Object* GetPageContent(CPDF_Dictionary* pPageDict) {
+ return pPageDict ? pPageDict->GetDirectObjectFor("Contents") : nullptr;
+}
+
} // namespace
-DLLEXPORT void STDCALL FPDFPage_SetMediaBox(FPDF_PAGE page,
- float left,
- float bottom,
- float right,
- float top) {
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetMediaBox(FPDF_PAGE page,
+ float left,
+ float bottom,
+ float right,
+ float top) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return;
@@ -66,11 +72,11 @@
SetBoundingBox(pPage, "MediaBox", left, bottom, right, top);
}
-DLLEXPORT void STDCALL FPDFPage_SetCropBox(FPDF_PAGE page,
- float left,
- float bottom,
- float right,
- float top) {
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetCropBox(FPDF_PAGE page,
+ float left,
+ float bottom,
+ float right,
+ float top) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return;
@@ -78,96 +84,83 @@
SetBoundingBox(pPage, "CropBox", left, bottom, right, top);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetMediaBox(FPDF_PAGE page,
- float* left,
- float* bottom,
- float* right,
- float* top) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetMediaBox(FPDF_PAGE page,
+ float* left,
+ float* bottom,
+ float* right,
+ float* top) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
return pPage && GetBoundingBox(pPage, "MediaBox", left, bottom, right, top);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetCropBox(FPDF_PAGE page,
- float* left,
- float* bottom,
- float* right,
- float* top) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GetCropBox(FPDF_PAGE page,
+ float* left,
+ float* bottom,
+ float* right,
+ float* top) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
return pPage && GetBoundingBox(pPage, "CropBox", left, bottom, right, top);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page,
- FS_MATRIX* matrix,
- FS_RECTF* clipRect) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPage_TransFormWithClip(FPDF_PAGE page,
+ FS_MATRIX* matrix,
+ FS_RECTF* clipRect) {
+ if (!matrix && !clipRect)
+ return false;
+
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return false;
- CFX_ByteTextBuf textBuf;
+ std::ostringstream textBuf;
textBuf << "q ";
- CFX_FloatRect rect(clipRect->left, clipRect->bottom, clipRect->right,
- clipRect->top);
- rect.Normalize();
- CFX_ByteString bsClipping;
- bsClipping.Format("%f %f %f %f re W* n ", rect.left, rect.bottom,
- rect.Width(), rect.Height());
- textBuf << bsClipping;
- CFX_ByteString bsMatix;
- bsMatix.Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b, matrix->c,
- matrix->d, matrix->e, matrix->f);
- textBuf << bsMatix;
+ if (clipRect) {
+ CFX_FloatRect rect = CFXFloatRectFromFSRECTF(*clipRect);
+ rect.Normalize();
- CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
- CPDF_Object* pContentObj =
- pPageDic ? pPageDic->GetObjectFor("Contents") : nullptr;
- if (!pContentObj)
- pContentObj = pPageDic ? pPageDic->GetArrayFor("Contents") : nullptr;
+ textBuf << ByteString::Format("%f %f %f %f re W* n ", rect.left,
+ rect.bottom, rect.Width(), rect.Height());
+ }
+ if (matrix) {
+ textBuf << ByteString::Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b,
+ matrix->c, matrix->d, matrix->e, matrix->f);
+ }
+
+ CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get();
+ CPDF_Object* pContentObj = GetPageContent(pPageDict);
if (!pContentObj)
return false;
- CPDF_Document* pDoc = pPage->m_pDocument;
+ CPDF_Document* pDoc = pPage->m_pDocument.Get();
if (!pDoc)
return false;
CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>(
nullptr, 0,
pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool()));
- pStream->SetData(textBuf.GetBuffer(), textBuf.GetSize());
+ pStream->SetData(&textBuf);
CPDF_Stream* pEndStream = pDoc->NewIndirect<CPDF_Stream>(
nullptr, 0,
pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool()));
pEndStream->SetData((const uint8_t*)" Q", 2);
- CPDF_Array* pContentArray = nullptr;
- CPDF_Array* pArray = ToArray(pContentObj);
- if (pArray) {
- pContentArray = pArray;
+ if (CPDF_Array* pContentArray = ToArray(pContentObj)) {
pContentArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
- } else if (CPDF_Reference* pReference = ToReference(pContentObj)) {
- CPDF_Object* pDirectObj = pReference->GetDirect();
- if (pDirectObj) {
- CPDF_Array* pObjArray = pDirectObj->AsArray();
- if (pObjArray) {
- pContentArray = pObjArray;
- pContentArray->InsertNewAt<CPDF_Reference>(0, pDoc,
- pStream->GetObjNum());
- pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
- } else if (pDirectObj->IsStream()) {
- pContentArray = pDoc->NewIndirect<CPDF_Array>();
- pContentArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
- pContentArray->AddNew<CPDF_Reference>(pDoc, pDirectObj->GetObjNum());
- pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
- pPageDic->SetNewFor<CPDF_Reference>("Contents", pDoc,
- pContentArray->GetObjNum());
- }
- }
+ } else if (pContentObj->IsStream() && !pContentObj->IsInline()) {
+ CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>();
+ pContentArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
+ pContentArray->AddNew<CPDF_Reference>(pDoc, pContentObj->GetObjNum());
+ pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
+ pPageDict->SetNewFor<CPDF_Reference>("Contents", pDoc,
+ pContentArray->GetObjNum());
}
// Need to transform the patterns as well.
- CPDF_Dictionary* pRes = pPageDic->GetDictFor("Resources");
+ CPDF_Dictionary* pRes = pPageDict->GetDictFor("Resources");
if (pRes) {
CPDF_Dictionary* pPattenDict = pRes->GetDictFor("Pattern");
if (pPattenDict) {
@@ -195,7 +188,7 @@
return true;
}
-DLLEXPORT void STDCALL
+FPDF_EXPORT void FPDF_CALLCONV
FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object,
double a,
double b,
@@ -206,8 +199,7 @@
CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_object;
if (!pPageObj)
return;
- CFX_Matrix matrix((FX_FLOAT)a, (FX_FLOAT)b, (FX_FLOAT)c, (FX_FLOAT)d,
- (FX_FLOAT)e, (FX_FLOAT)f);
+ CFX_Matrix matrix((float)a, (float)b, (float)c, (float)d, (float)e, (float)f);
// Special treatment to shading object, because the ClipPath for shading
// object is already transformed.
@@ -216,23 +208,24 @@
pPageObj->TransformGeneralState(matrix);
}
-DLLEXPORT FPDF_CLIPPATH STDCALL FPDF_CreateClipPath(float left,
- float bottom,
- float right,
- float top) {
+FPDF_EXPORT FPDF_CLIPPATH FPDF_CALLCONV FPDF_CreateClipPath(float left,
+ float bottom,
+ float right,
+ float top) {
CPDF_Path Path;
Path.AppendRect(left, bottom, right, top);
- CPDF_ClipPath* pNewClipPath = new CPDF_ClipPath();
+ auto pNewClipPath = pdfium::MakeUnique<CPDF_ClipPath>();
pNewClipPath->AppendPath(Path, FXFILL_ALTERNATE, false);
- return pNewClipPath;
+ return pNewClipPath.release(); // Caller takes ownership.
}
-DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath) {
- delete (CPDF_ClipPath*)clipPath;
+FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath) {
+ // Take ownership back from caller and destroy.
+ std::unique_ptr<CPDF_ClipPath>(static_cast<CPDF_ClipPath*>(clipPath));
}
-void OutputPath(CFX_ByteTextBuf& buf, CPDF_Path path) {
+void OutputPath(std::ostringstream& buf, CPDF_Path path) {
const CFX_PathData* pPathData = path.GetObject();
if (!pPathData)
return;
@@ -245,7 +238,7 @@
return;
}
- CFX_ByteString temp;
+ ByteString temp;
for (size_t i = 0; i < pPoints.size(); i++) {
buf << pPoints[i].m_Point.x << " " << pPoints[i].m_Point.y;
FXPT_TYPE point_type = pPoints[i].m_Type;
@@ -269,69 +262,48 @@
}
}
-DLLEXPORT void STDCALL FPDFPage_InsertClipPath(FPDF_PAGE page,
- FPDF_CLIPPATH clipPath) {
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertClipPath(FPDF_PAGE page,
+ FPDF_CLIPPATH clipPath) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return;
- CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
- CPDF_Object* pContentObj =
- pPageDic ? pPageDic->GetObjectFor("Contents") : nullptr;
- if (!pContentObj)
- pContentObj = pPageDic ? pPageDic->GetArrayFor("Contents") : nullptr;
+ CPDF_Dictionary* pPageDict = pPage->m_pFormDict.Get();
+ CPDF_Object* pContentObj = GetPageContent(pPageDict);
if (!pContentObj)
return;
- CFX_ByteTextBuf strClip;
+ std::ostringstream strClip;
CPDF_ClipPath* pClipPath = (CPDF_ClipPath*)clipPath;
- uint32_t i;
- for (i = 0; i < pClipPath->GetPathCount(); i++) {
+ for (size_t i = 0; i < pClipPath->GetPathCount(); ++i) {
CPDF_Path path = pClipPath->GetPath(i);
- int iClipType = pClipPath->GetClipType(i);
if (path.GetPoints().empty()) {
// Empty clipping (totally clipped out)
strClip << "0 0 m W n ";
} else {
OutputPath(strClip, path);
- if (iClipType == FXFILL_WINDING)
+ if (pClipPath->GetClipType(i) == FXFILL_WINDING)
strClip << "W n\n";
else
strClip << "W* n\n";
}
}
- CPDF_Document* pDoc = pPage->m_pDocument;
+ CPDF_Document* pDoc = pPage->m_pDocument.Get();
if (!pDoc)
return;
CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>(
nullptr, 0,
pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool()));
- pStream->SetData(strClip.GetBuffer(), strClip.GetSize());
+ pStream->SetData(&strClip);
- CPDF_Array* pArray = ToArray(pContentObj);
- if (pArray) {
+ if (CPDF_Array* pArray = ToArray(pContentObj)) {
pArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
- return;
- }
- CPDF_Reference* pReference = ToReference(pContentObj);
- if (!pReference)
- return;
-
- CPDF_Object* pDirectObj = pReference->GetDirect();
- if (!pDirectObj)
- return;
-
- CPDF_Array* pObjArray = pDirectObj->AsArray();
- if (pObjArray) {
- pObjArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
- return;
- }
- if (pDirectObj->IsStream()) {
+ } else if (pContentObj->IsStream() && !pContentObj->IsInline()) {
CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>();
pContentArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
- pContentArray->AddNew<CPDF_Reference>(pDoc, pDirectObj->GetObjNum());
- pPageDic->SetNewFor<CPDF_Reference>("Contents", pDoc,
- pContentArray->GetObjNum());
+ pContentArray->AddNew<CPDF_Reference>(pDoc, pContentObj->GetObjNum());
+ pPageDict->SetNewFor<CPDF_Reference>("Contents", pDoc,
+ pContentArray->GetObjNum());
}
}
diff --git a/fpdfsdk/fpdfannot.cpp b/fpdfsdk/fpdfannot.cpp
new file mode 100644
index 0000000..9b0cb39
--- /dev/null
+++ b/fpdfsdk/fpdfannot.cpp
@@ -0,0 +1,890 @@
+// 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.
+
+#include "public/fpdf_annot.h"
+
+#include <memory>
+#include <utility>
+
+#include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h"
+#include "core/fpdfapi/page/cpdf_form.h"
+#include "core/fpdfapi/page/cpdf_page.h"
+#include "core/fpdfapi/page/cpdf_pageobject.h"
+#include "core/fpdfapi/parser/cpdf_array.h"
+#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_string.h"
+#include "core/fpdfdoc/cpdf_annot.h"
+#include "core/fpdfdoc/cpdf_formfield.h"
+#include "core/fpdfdoc/cpdf_interform.h"
+#include "core/fpdfdoc/cpvt_generateap.h"
+#include "core/fxge/cfx_color.h"
+#include "fpdfsdk/fsdk_define.h"
+
+namespace {
+
+// These checks ensure the consistency of annotation subtype values across core/
+// and public.
+static_assert(static_cast<int>(CPDF_Annot::Subtype::UNKNOWN) ==
+ FPDF_ANNOT_UNKNOWN,
+ "CPDF_Annot::UNKNOWN value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::TEXT) == FPDF_ANNOT_TEXT,
+ "CPDF_Annot::TEXT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::LINK) == FPDF_ANNOT_LINK,
+ "CPDF_Annot::LINK value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::FREETEXT) ==
+ FPDF_ANNOT_FREETEXT,
+ "CPDF_Annot::FREETEXT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::LINE) == FPDF_ANNOT_LINE,
+ "CPDF_Annot::LINE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::SQUARE) ==
+ FPDF_ANNOT_SQUARE,
+ "CPDF_Annot::SQUARE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::CIRCLE) ==
+ FPDF_ANNOT_CIRCLE,
+ "CPDF_Annot::CIRCLE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::POLYGON) ==
+ FPDF_ANNOT_POLYGON,
+ "CPDF_Annot::POLYGON value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::POLYLINE) ==
+ FPDF_ANNOT_POLYLINE,
+ "CPDF_Annot::POLYLINE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::HIGHLIGHT) ==
+ FPDF_ANNOT_HIGHLIGHT,
+ "CPDF_Annot::HIGHLIGHT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::UNDERLINE) ==
+ FPDF_ANNOT_UNDERLINE,
+ "CPDF_Annot::UNDERLINE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::SQUIGGLY) ==
+ FPDF_ANNOT_SQUIGGLY,
+ "CPDF_Annot::SQUIGGLY value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::STRIKEOUT) ==
+ FPDF_ANNOT_STRIKEOUT,
+ "CPDF_Annot::STRIKEOUT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::STAMP) == FPDF_ANNOT_STAMP,
+ "CPDF_Annot::STAMP value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::CARET) == FPDF_ANNOT_CARET,
+ "CPDF_Annot::CARET value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::INK) == FPDF_ANNOT_INK,
+ "CPDF_Annot::INK value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::POPUP) == FPDF_ANNOT_POPUP,
+ "CPDF_Annot::POPUP value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::FILEATTACHMENT) ==
+ FPDF_ANNOT_FILEATTACHMENT,
+ "CPDF_Annot::FILEATTACHMENT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::SOUND) == FPDF_ANNOT_SOUND,
+ "CPDF_Annot::SOUND value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::MOVIE) == FPDF_ANNOT_MOVIE,
+ "CPDF_Annot::MOVIE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::WIDGET) ==
+ FPDF_ANNOT_WIDGET,
+ "CPDF_Annot::WIDGET value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::SCREEN) ==
+ FPDF_ANNOT_SCREEN,
+ "CPDF_Annot::SCREEN value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::PRINTERMARK) ==
+ FPDF_ANNOT_PRINTERMARK,
+ "CPDF_Annot::PRINTERMARK value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::TRAPNET) ==
+ FPDF_ANNOT_TRAPNET,
+ "CPDF_Annot::TRAPNET value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::WATERMARK) ==
+ FPDF_ANNOT_WATERMARK,
+ "CPDF_Annot::WATERMARK value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::THREED) ==
+ FPDF_ANNOT_THREED,
+ "CPDF_Annot::THREED value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::RICHMEDIA) ==
+ FPDF_ANNOT_RICHMEDIA,
+ "CPDF_Annot::RICHMEDIA value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::XFAWIDGET) ==
+ FPDF_ANNOT_XFAWIDGET,
+ "CPDF_Annot::XFAWIDGET value mismatch");
+
+// These checks ensure the consistency of annotation appearance mode values
+// across core/ and public.
+static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::Normal) ==
+ FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+ "CPDF_Annot::AppearanceMode::Normal value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::Rollover) ==
+ FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
+ "CPDF_Annot::AppearanceMode::Rollover value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::AppearanceMode::Down) ==
+ FPDF_ANNOT_APPEARANCEMODE_DOWN,
+ "CPDF_Annot::AppearanceMode::Down value mismatch");
+
+// These checks ensure the consistency of dictionary value types across core/
+// and public/.
+static_assert(static_cast<int>(CPDF_Object::Type::BOOLEAN) ==
+ FPDF_OBJECT_BOOLEAN,
+ "CPDF_Object::BOOLEAN value mismatch");
+static_assert(static_cast<int>(CPDF_Object::Type::NUMBER) == FPDF_OBJECT_NUMBER,
+ "CPDF_Object::NUMBER value mismatch");
+static_assert(static_cast<int>(CPDF_Object::Type::STRING) == FPDF_OBJECT_STRING,
+ "CPDF_Object::STRING value mismatch");
+static_assert(static_cast<int>(CPDF_Object::Type::NAME) == FPDF_OBJECT_NAME,
+ "CPDF_Object::NAME value mismatch");
+static_assert(static_cast<int>(CPDF_Object::Type::ARRAY) == FPDF_OBJECT_ARRAY,
+ "CPDF_Object::ARRAY value mismatch");
+static_assert(static_cast<int>(CPDF_Object::Type::DICTIONARY) ==
+ FPDF_OBJECT_DICTIONARY,
+ "CPDF_Object::DICTIONARY value mismatch");
+static_assert(static_cast<int>(CPDF_Object::Type::STREAM) == FPDF_OBJECT_STREAM,
+ "CPDF_Object::STREAM value mismatch");
+static_assert(static_cast<int>(CPDF_Object::Type::NULLOBJ) ==
+ FPDF_OBJECT_NULLOBJ,
+ "CPDF_Object::NULLOBJ value mismatch");
+static_assert(static_cast<int>(CPDF_Object::Type::REFERENCE) ==
+ FPDF_OBJECT_REFERENCE,
+ "CPDF_Object::REFERENCE value mismatch");
+
+class CPDF_AnnotContext {
+ public:
+ CPDF_AnnotContext(CPDF_Dictionary* pAnnotDict,
+ CPDF_Page* pPage,
+ CPDF_Stream* pStream)
+ : m_pAnnotDict(pAnnotDict), m_pPage(pPage) {
+ SetForm(pStream);
+ }
+ ~CPDF_AnnotContext() {}
+
+ bool HasForm() const { return !!m_pAnnotForm; }
+
+ void SetForm(CPDF_Stream* pStream) {
+ if (!pStream)
+ return;
+
+ // Reset the annotation matrix to be the identity matrix, since the
+ // appearance stream already takes matrix into account.
+ pStream->GetDict()->SetMatrixFor("Matrix", CFX_Matrix());
+
+ m_pAnnotForm = pdfium::MakeUnique<CPDF_Form>(
+ m_pPage->m_pDocument.Get(), m_pPage->m_pResources.Get(), pStream);
+ m_pAnnotForm->ParseContent();
+ }
+
+ CPDF_Form* GetForm() const { return m_pAnnotForm.get(); }
+ CPDF_Dictionary* GetAnnotDict() const { return m_pAnnotDict.Get(); }
+ CPDF_Page* GetPage() const { return m_pPage.Get(); }
+
+ private:
+ std::unique_ptr<CPDF_Form> m_pAnnotForm;
+ UnownedPtr<CPDF_Dictionary> m_pAnnotDict;
+ UnownedPtr<CPDF_Page> m_pPage;
+};
+
+CPDF_AnnotContext* CPDFAnnotContextFromFPDFAnnotation(FPDF_ANNOTATION annot) {
+ return static_cast<CPDF_AnnotContext*>(annot);
+}
+
+bool HasAPStream(const CPDF_Dictionary* pAnnotDict) {
+ return !!FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal);
+}
+
+void UpdateContentStream(CPDF_Form* pForm, CPDF_Stream* pStream) {
+ ASSERT(pForm);
+ ASSERT(pStream);
+
+ CPDF_PageContentGenerator generator(pForm);
+ std::ostringstream buf;
+ generator.ProcessPageObjects(&buf);
+ pStream->SetDataAndRemoveFilter(&buf);
+}
+
+} // namespace
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_IsSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) {
+ // The supported subtypes must also be communicated in the user doc.
+ return subtype == FPDF_ANNOT_CIRCLE || subtype == FPDF_ANNOT_HIGHLIGHT ||
+ subtype == FPDF_ANNOT_INK || subtype == FPDF_ANNOT_POPUP ||
+ subtype == FPDF_ANNOT_SQUARE || subtype == FPDF_ANNOT_SQUIGGLY ||
+ subtype == FPDF_ANNOT_STAMP || subtype == FPDF_ANNOT_STRIKEOUT ||
+ subtype == FPDF_ANNOT_TEXT || subtype == FPDF_ANNOT_UNDERLINE;
+}
+
+FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
+FPDFPage_CreateAnnot(FPDF_PAGE page, FPDF_ANNOTATION_SUBTYPE subtype) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage || !FPDFAnnot_IsSupportedSubtype(subtype))
+ return nullptr;
+
+ auto pDict = pdfium::MakeUnique<CPDF_Dictionary>(
+ pPage->m_pDocument->GetByteStringPool());
+ pDict->SetNewFor<CPDF_Name>("Type", "Annot");
+ pDict->SetNewFor<CPDF_Name>("Subtype",
+ CPDF_Annot::AnnotSubtypeToString(
+ static_cast<CPDF_Annot::Subtype>(subtype)));
+ auto pNewAnnot =
+ pdfium::MakeUnique<CPDF_AnnotContext>(pDict.get(), pPage, nullptr);
+
+ CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayFor("Annots");
+ if (!pAnnotList)
+ pAnnotList = pPage->m_pFormDict->SetNewFor<CPDF_Array>("Annots");
+
+ pAnnotList->Add(std::move(pDict));
+ return pNewAnnot.release();
+}
+
+FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotCount(FPDF_PAGE page) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage || !pPage->m_pFormDict)
+ return 0;
+
+ CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots");
+ return pAnnots ? pAnnots->GetCount() : 0;
+}
+
+FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV FPDFPage_GetAnnot(FPDF_PAGE page,
+ int index) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage || !pPage->m_pFormDict || index < 0)
+ return nullptr;
+
+ CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots");
+ if (!pAnnots || static_cast<size_t>(index) >= pAnnots->GetCount())
+ return nullptr;
+
+ CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(index));
+ auto pNewAnnot = pdfium::MakeUnique<CPDF_AnnotContext>(pDict, pPage, nullptr);
+ return pNewAnnot.release();
+}
+
+FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotIndex(FPDF_PAGE page,
+ FPDF_ANNOTATION annot) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+ if (!pPage || !pPage->m_pFormDict || !pAnnot || !pAnnot->GetAnnotDict())
+ return -1;
+
+ CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots");
+ if (!pAnnots)
+ return -1;
+
+ CPDF_Dictionary* pDict = pAnnot->GetAnnotDict();
+ auto it =
+ std::find_if(pAnnots->begin(), pAnnots->end(),
+ [pDict](const std::unique_ptr<CPDF_Object>& candidate) {
+ return candidate->GetDirect() == pDict;
+ });
+
+ if (it == pAnnots->end())
+ return -1;
+
+ return it - pAnnots->begin();
+}
+
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_CloseAnnot(FPDF_ANNOTATION annot) {
+ delete CPDFAnnotContextFromFPDFAnnotation(annot);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_RemoveAnnot(FPDF_PAGE page,
+ int index) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage || !pPage->m_pFormDict || index < 0)
+ return false;
+
+ CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots");
+ if (!pAnnots || static_cast<size_t>(index) >= pAnnots->GetCount())
+ return false;
+
+ pAnnots->RemoveAt(index);
+ return true;
+}
+
+FPDF_EXPORT FPDF_ANNOTATION_SUBTYPE FPDF_CALLCONV
+FPDFAnnot_GetSubtype(FPDF_ANNOTATION annot) {
+ if (!annot)
+ return FPDF_ANNOT_UNKNOWN;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return FPDF_ANNOT_UNKNOWN;
+
+ return static_cast<FPDF_ANNOTATION_SUBTYPE>(
+ CPDF_Annot::StringToAnnotSubtype(pAnnotDict->GetStringFor("Subtype")));
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_IsObjectSupportedSubtype(FPDF_ANNOTATION_SUBTYPE subtype) {
+ // The supported subtypes must also be communicated in the user doc.
+ return subtype == FPDF_ANNOT_INK || subtype == FPDF_ANNOT_STAMP;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_UpdateObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) {
+ CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+ CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(obj);
+ if (!pAnnot || !pAnnot->GetAnnotDict() || !pAnnot->HasForm() || !pObj)
+ return false;
+
+ // Check that the annotation type is supported by this method.
+ if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot)))
+ return false;
+
+ // Check that the annotation already has an appearance stream, since an
+ // existing object is to be updated.
+ CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(pAnnot->GetAnnotDict(),
+ CPDF_Annot::AppearanceMode::Normal);
+ if (!pStream)
+ return false;
+
+ // Check that the object is already in this annotation's object list.
+ CPDF_Form* pForm = pAnnot->GetForm();
+ CPDF_PageObjectList* pObjList = pForm->GetPageObjectList();
+ auto it =
+ std::find_if(pObjList->begin(), pObjList->end(),
+ [pObj](const std::unique_ptr<CPDF_PageObject>& candidate) {
+ return candidate.get() == pObj;
+ });
+ if (it == pObjList->end())
+ return false;
+
+ // Update the content stream data in the annotation's AP stream.
+ UpdateContentStream(pForm, pStream);
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_AppendObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) {
+ CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+ CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(obj);
+ if (!pAnnot || !pObj)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();
+ CPDF_Page* pPage = pAnnot->GetPage();
+ if (!pAnnotDict || !pPage)
+ return false;
+
+ // Check that the annotation type is supported by this method.
+ if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot)))
+ return false;
+
+ // If the annotation does not have an AP stream yet, generate and set it.
+ CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(pAnnot->GetAnnotDict(),
+ CPDF_Annot::AppearanceMode::Normal);
+ if (!pStream) {
+ CPVT_GenerateAP::GenerateEmptyAP(pPage->m_pDocument.Get(), pAnnotDict);
+ pStream =
+ FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal);
+ if (!pStream)
+ return false;
+ }
+
+ // Get the annotation's corresponding form object for parsing its AP stream.
+ if (!pAnnot->HasForm())
+ pAnnot->SetForm(pStream);
+
+ // Check that the object did not come from the same annotation. If this check
+ // succeeds, then it is assumed that the object came from
+ // FPDFPageObj_CreateNew{Path|Rect}() or FPDFPageObj_New{Text|Image}Obj().
+ // Note that an object that came from a different annotation must not be
+ // passed here, since an object cannot belong to more than one annotation.
+ CPDF_Form* pForm = pAnnot->GetForm();
+ CPDF_PageObjectList* pObjList = pForm->GetPageObjectList();
+ auto it =
+ std::find_if(pObjList->begin(), pObjList->end(),
+ [pObj](const std::unique_ptr<CPDF_PageObject>& candidate) {
+ return candidate.get() == pObj;
+ });
+ if (it != pObjList->end())
+ return false;
+
+ // Append the object to the object list.
+ std::unique_ptr<CPDF_PageObject> pPageObjHolder(pObj);
+ pObjList->push_back(std::move(pPageObjHolder));
+
+ // Set the content stream data in the annotation's AP stream.
+ UpdateContentStream(pForm, pStream);
+ return true;
+}
+
+FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetObjectCount(FPDF_ANNOTATION annot) {
+ CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+ if (!pAnnot || !pAnnot->GetAnnotDict())
+ return 0;
+
+ if (!pAnnot->HasForm()) {
+ CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(
+ pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal);
+ if (!pStream)
+ return 0;
+
+ pAnnot->SetForm(pStream);
+ }
+ return pdfium::CollectionSize<int>(*pAnnot->GetForm()->GetPageObjectList());
+}
+
+FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
+FPDFAnnot_GetObject(FPDF_ANNOTATION annot, int index) {
+ CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+ if (!pAnnot || !pAnnot->GetAnnotDict() || index < 0)
+ return nullptr;
+
+ if (!pAnnot->HasForm()) {
+ CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(
+ pAnnot->GetAnnotDict(), CPDF_Annot::AppearanceMode::Normal);
+ if (!pStream)
+ return nullptr;
+
+ pAnnot->SetForm(pStream);
+ }
+
+ return pAnnot->GetForm()->GetPageObjectList()->GetPageObjectByIndex(index);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_RemoveObject(FPDF_ANNOTATION annot, int index) {
+ CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+ if (!pAnnot || !pAnnot->GetAnnotDict() || !pAnnot->HasForm() || index < 0)
+ return false;
+
+ // Check that the annotation type is supported by this method.
+ if (!FPDFAnnot_IsObjectSupportedSubtype(FPDFAnnot_GetSubtype(annot)))
+ return false;
+
+ // Check that the annotation already has an appearance stream, since an
+ // existing object is to be deleted.
+ CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(pAnnot->GetAnnotDict(),
+ CPDF_Annot::AppearanceMode::Normal);
+ if (!pStream)
+ return false;
+
+ CPDF_PageObjectList* pObjList = pAnnot->GetForm()->GetPageObjectList();
+ if (static_cast<size_t>(index) >= pObjList->size())
+ return false;
+
+ pObjList->erase(pObjList->begin() + index);
+ UpdateContentStream(pAnnot->GetForm(), pStream);
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetColor(FPDF_ANNOTATION annot,
+ FPDFANNOT_COLORTYPE type,
+ unsigned int R,
+ unsigned int G,
+ unsigned int B,
+ unsigned int A) {
+ if (!annot || R > 255 || G > 255 || B > 255 || A > 255)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ // For annotations with their appearance streams already defined, the path
+ // stream's own color definitions take priority over the annotation color
+ // definitions set by this method, hence this method will simply fail.
+ if (HasAPStream(pAnnotDict))
+ return false;
+
+ // Set the opacity of the annotation.
+ pAnnotDict->SetNewFor<CPDF_Number>("CA", A / 255.f);
+
+ // Set the color of the annotation.
+ ByteString key = type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C";
+ CPDF_Array* pColor = pAnnotDict->GetArrayFor(key);
+ if (pColor)
+ pColor->Clear();
+ else
+ pColor = pAnnotDict->SetNewFor<CPDF_Array>(key);
+
+ pColor->AddNew<CPDF_Number>(R / 255.f);
+ pColor->AddNew<CPDF_Number>(G / 255.f);
+ pColor->AddNew<CPDF_Number>(B / 255.f);
+
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetColor(FPDF_ANNOTATION annot,
+ FPDFANNOT_COLORTYPE type,
+ unsigned int* R,
+ unsigned int* G,
+ unsigned int* B,
+ unsigned int* A) {
+ if (!annot || !R || !G || !B || !A)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ // For annotations with their appearance streams already defined, the path
+ // stream's own color definitions take priority over the annotation color
+ // definitions retrieved by this method, hence this method will simply fail.
+ if (HasAPStream(pAnnotDict))
+ return false;
+
+ CPDF_Array* pColor = pAnnotDict->GetArrayFor(
+ type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C");
+ *A =
+ (pAnnotDict->KeyExist("CA") ? pAnnotDict->GetNumberFor("CA") : 1) * 255.f;
+ if (!pColor) {
+ // Use default color. The default colors must be consistent with the ones
+ // used to generate AP. See calls to GetColorStringWithDefault() in
+ // CPVT_GenerateAP::Generate*AP().
+ if (pAnnotDict->GetStringFor("Subtype") == "Highlight") {
+ *R = 255;
+ *G = 255;
+ *B = 0;
+ } else {
+ *R = 0;
+ *G = 0;
+ *B = 0;
+ }
+ return true;
+ }
+
+ CFX_Color color = CFX_Color::ParseColor(*pColor);
+ switch (color.nColorType) {
+ case CFX_Color::kRGB:
+ *R = color.fColor1 * 255.f;
+ *G = color.fColor2 * 255.f;
+ *B = color.fColor3 * 255.f;
+ break;
+ case CFX_Color::kGray:
+ *R = 255.f * color.fColor1;
+ *G = 255.f * color.fColor1;
+ *B = 255.f * color.fColor1;
+ break;
+ case CFX_Color::kCMYK:
+ *R = 255.f * (1 - color.fColor1) * (1 - color.fColor4);
+ *G = 255.f * (1 - color.fColor2) * (1 - color.fColor4);
+ *B = 255.f * (1 - color.fColor3) * (1 - color.fColor4);
+ break;
+ case CFX_Color::kTransparent:
+ *R = 0;
+ *G = 0;
+ *B = 0;
+ break;
+ }
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_HasAttachmentPoints(FPDF_ANNOTATION annot) {
+ if (!annot)
+ return false;
+
+ FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot);
+ return subtype == FPDF_ANNOT_LINK || subtype == FPDF_ANNOT_HIGHLIGHT ||
+ subtype == FPDF_ANNOT_UNDERLINE || subtype == FPDF_ANNOT_SQUIGGLY ||
+ subtype == FPDF_ANNOT_STRIKEOUT;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot,
+ const FS_QUADPOINTSF* quadPoints) {
+ if (!annot || !quadPoints || !FPDFAnnot_HasAttachmentPoints(annot))
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ // Update the "QuadPoints" entry in the annotation dictionary.
+ CPDF_Array* pQuadPoints = pAnnotDict->GetArrayFor("QuadPoints");
+ if (pQuadPoints)
+ pQuadPoints->Clear();
+ else
+ pQuadPoints = pAnnotDict->SetNewFor<CPDF_Array>("QuadPoints");
+
+ pQuadPoints->AddNew<CPDF_Number>(quadPoints->x1);
+ pQuadPoints->AddNew<CPDF_Number>(quadPoints->y1);
+ pQuadPoints->AddNew<CPDF_Number>(quadPoints->x2);
+ pQuadPoints->AddNew<CPDF_Number>(quadPoints->y2);
+ pQuadPoints->AddNew<CPDF_Number>(quadPoints->x3);
+ pQuadPoints->AddNew<CPDF_Number>(quadPoints->y3);
+ pQuadPoints->AddNew<CPDF_Number>(quadPoints->x4);
+ pQuadPoints->AddNew<CPDF_Number>(quadPoints->y4);
+
+ // If the annotation's appearance stream is defined, and the new quadpoints
+ // defines a bigger bounding box than the appearance stream currently
+ // specifies, then update the "BBox" entry in the AP dictionary too, since it
+ // comes from annotation dictionary's "QuadPoints" entry.
+ CPDF_Stream* pStream =
+ FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal);
+ if (pStream) {
+ CFX_FloatRect newRect = CPDF_Annot::RectFromQuadPoints(pAnnotDict);
+ if (newRect.Contains(pStream->GetDict()->GetRectFor("BBox")))
+ pStream->GetDict()->SetRectFor("BBox", newRect);
+ }
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot,
+ FS_QUADPOINTSF* quadPoints) {
+ if (!annot || !FPDFAnnot_HasAttachmentPoints(annot) || !quadPoints)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ CPDF_Array* pArray = pAnnotDict->GetArrayFor("QuadPoints");
+ if (!pArray)
+ return false;
+
+ quadPoints->x1 = pArray->GetNumberAt(0);
+ quadPoints->y1 = pArray->GetNumberAt(1);
+ quadPoints->x2 = pArray->GetNumberAt(2);
+ quadPoints->y2 = pArray->GetNumberAt(3);
+ quadPoints->x3 = pArray->GetNumberAt(4);
+ quadPoints->y3 = pArray->GetNumberAt(5);
+ quadPoints->x4 = pArray->GetNumberAt(6);
+ quadPoints->y4 = pArray->GetNumberAt(7);
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetRect(FPDF_ANNOTATION annot,
+ const FS_RECTF* rect) {
+ if (!annot || !rect)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ CFX_FloatRect newRect = CFXFloatRectFromFSRECTF(*rect);
+
+ // Update the "Rect" entry in the annotation dictionary.
+ pAnnotDict->SetRectFor("Rect", newRect);
+
+ // If the annotation's appearance stream is defined, the annotation is of a
+ // type that does not have quadpoints, and the new rectangle is bigger than
+ // the current bounding box, then update the "BBox" entry in the AP
+ // dictionary too, since its "BBox" entry comes from annotation dictionary's
+ // "Rect" entry.
+ if (FPDFAnnot_HasAttachmentPoints(annot))
+ return true;
+
+ CPDF_Stream* pStream =
+ FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal);
+ if (pStream && newRect.Contains(pStream->GetDict()->GetRectFor("BBox")))
+ pStream->GetDict()->SetRectFor("BBox", newRect);
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetRect(FPDF_ANNOTATION annot,
+ FS_RECTF* rect) {
+ if (!annot || !rect)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ FSRECTFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"), rect);
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_HasKey(FPDF_ANNOTATION annot,
+ FPDF_BYTESTRING key) {
+ if (!annot)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ return pAnnotDict->KeyExist(key);
+}
+
+FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV
+FPDFAnnot_GetValueType(FPDF_ANNOTATION annot, FPDF_BYTESTRING key) {
+ if (!FPDFAnnot_HasKey(annot, key))
+ return FPDF_OBJECT_UNKNOWN;
+
+ auto* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+ CPDF_Object* pObj = pAnnot->GetAnnotDict()->GetObjectFor(key);
+ return pObj ? pObj->GetType() : FPDF_OBJECT_UNKNOWN;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_SetStringValue(FPDF_ANNOTATION annot,
+ FPDF_BYTESTRING key,
+ FPDF_WIDESTRING value) {
+ if (!annot)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ pAnnotDict->SetNewFor<CPDF_String>(
+ key, CFXByteStringFromFPDFWideString(value), false);
+ return true;
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFAnnot_GetStringValue(FPDF_ANNOTATION annot,
+ FPDF_BYTESTRING key,
+ void* buffer,
+ unsigned long buflen) {
+ if (!annot)
+ return 0;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return 0;
+
+ return Utf16EncodeMaybeCopyAndReturnLength(pAnnotDict->GetUnicodeTextFor(key),
+ buffer, buflen);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_SetAP(FPDF_ANNOTATION annot,
+ FPDF_ANNOT_APPEARANCEMODE appearanceMode,
+ FPDF_WIDESTRING value) {
+ if (appearanceMode < 0 || appearanceMode >= FPDF_ANNOT_APPEARANCEMODE_COUNT)
+ return false;
+
+ if (!annot)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ constexpr const char* modeKeyForMode[] = {"N", "R", "D"};
+ static_assert(FX_ArraySize(modeKeyForMode) == FPDF_ANNOT_APPEARANCEMODE_COUNT,
+ "length of modeKeyForMode should be equal to "
+ "FPDF_ANNOT_APPEARANCEMODE_COUNT");
+ const char* modeKey = modeKeyForMode[appearanceMode];
+
+ CPDF_Dictionary* pApDict = pAnnotDict->GetDictFor("AP");
+
+ // If value is null, we're in remove mode. Otherwise, we're in add/update
+ // mode.
+ if (value) {
+ if (!pApDict)
+ pApDict = pAnnotDict->SetNewFor<CPDF_Dictionary>("AP");
+
+ ByteString newValue = CFXByteStringFromFPDFWideString(value);
+ auto pNewApStream = pdfium::MakeUnique<CPDF_Stream>();
+ pNewApStream->SetData(newValue.raw_str(), newValue.GetLength());
+ pApDict->SetFor(modeKey, std::move(pNewApStream));
+ } else {
+ if (pApDict) {
+ if (appearanceMode == FPDF_ANNOT_APPEARANCEMODE_NORMAL)
+ pAnnotDict->RemoveFor("AP");
+ else
+ pApDict->RemoveFor(modeKey);
+ }
+ }
+
+ return true;
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFAnnot_GetAP(FPDF_ANNOTATION annot,
+ FPDF_ANNOT_APPEARANCEMODE appearanceMode,
+ void* buffer,
+ unsigned long buflen) {
+ if (appearanceMode < 0 || appearanceMode >= FPDF_ANNOT_APPEARANCEMODE_COUNT)
+ return 0;
+
+ if (!annot)
+ return 0;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return 0;
+
+ CPDF_Annot::AppearanceMode mode =
+ static_cast<CPDF_Annot::AppearanceMode>(appearanceMode);
+
+ CPDF_Stream* pStream = FPDFDOC_GetAnnotAPNoFallback(pAnnotDict, mode);
+ return Utf16EncodeMaybeCopyAndReturnLength(
+ pStream ? pStream->GetUnicodeText() : L"", buffer, buflen);
+}
+
+FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
+FPDFAnnot_GetLinkedAnnot(FPDF_ANNOTATION annot, FPDF_BYTESTRING key) {
+ CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+ if (!pAnnot || !pAnnot->GetAnnotDict())
+ return nullptr;
+
+ CPDF_Dictionary* pLinkedDict = pAnnot->GetAnnotDict()->GetDictFor(key);
+ if (!pLinkedDict || pLinkedDict->GetStringFor("Type") != "Annot")
+ return nullptr;
+
+ auto pLinkedAnnot = pdfium::MakeUnique<CPDF_AnnotContext>(
+ pLinkedDict, pAnnot->GetPage(), nullptr);
+ return pLinkedAnnot.release();
+}
+
+FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_GetFlags(FPDF_ANNOTATION annot) {
+ if (!annot)
+ return FPDF_ANNOT_FLAG_NONE;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ return pAnnotDict ? pAnnotDict->GetIntegerFor("F") : FPDF_ANNOT_FLAG_NONE;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetFlags(FPDF_ANNOTATION annot,
+ int flags) {
+ if (!annot)
+ return false;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return false;
+
+ pAnnotDict->SetNewFor<CPDF_Number>("F", flags);
+ return true;
+}
+
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFAnnot_GetFormFieldFlags(FPDF_PAGE page, FPDF_ANNOTATION annot) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage || !annot)
+ return FPDF_FORMFLAG_NONE;
+
+ CPDF_Dictionary* pAnnotDict =
+ CPDFAnnotContextFromFPDFAnnotation(annot)->GetAnnotDict();
+ if (!pAnnotDict)
+ return FPDF_FORMFLAG_NONE;
+
+ CPDF_InterForm interform(pPage->m_pDocument.Get());
+ CPDF_FormField* pFormField = interform.GetFieldByDict(pAnnotDict);
+ return pFormField ? pFormField->GetFieldFlags() : FPDF_FORMFLAG_NONE;
+}
+
+FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
+FPDFAnnot_GetFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ double page_x,
+ double page_y) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!hHandle || !pPage)
+ return nullptr;
+
+ CPDF_InterForm interform(pPage->m_pDocument.Get());
+ int annot_index = -1;
+ CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint(
+ pPage, CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
+ &annot_index);
+ if (!pFormCtrl || annot_index == -1)
+ return nullptr;
+ return FPDFPage_GetAnnot(page, annot_index);
+}
diff --git a/fpdfsdk/fpdfannot_embeddertest.cpp b/fpdfsdk/fpdfannot_embeddertest.cpp
new file mode 100644
index 0000000..b38bd87
--- /dev/null
+++ b/fpdfsdk/fpdfannot_embeddertest.cpp
@@ -0,0 +1,1267 @@
+// 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.
+
+#include <cwchar>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "core/fxcrt/fx_system.h"
+#include "public/fpdf_annot.h"
+#include "public/fpdf_edit.h"
+#include "public/fpdfview.h"
+#include "testing/embedder_test.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+static constexpr char kContentsKey[] = "Contents";
+
+class FPDFAnnotEmbeddertest : public EmbedderTest {};
+
+std::wstring BufferToWString(const std::vector<char>& buf) {
+ return GetPlatformWString(reinterpret_cast<FPDF_WIDESTRING>(buf.data()));
+}
+
+std::string BufferToString(const std::vector<char>& buf) {
+ return GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(buf.data()));
+}
+
+TEST_F(FPDFAnnotEmbeddertest, RenderAnnotWithOnlyRolloverAP) {
+ // Open a file with one annotation and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // This annotation has a malformed appearance stream, which does not have its
+ // normal appearance defined, only its rollover appearance. In this case, its
+ // normal appearance should be generated, allowing the highlight annotation to
+ // still display.
+ FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle(), FPDF_ANNOT);
+ CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
+ FPDFBitmap_Destroy(bitmap);
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, ExtractHighlightLongContent) {
+ // Open a file with one annotation and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Check that there is a total of 1 annotation on its first page.
+ EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
+
+ // Check that the annotation is of type "highlight".
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
+
+ // Check that the annotation color is yellow.
+ unsigned int R;
+ unsigned int G;
+ unsigned int B;
+ unsigned int A;
+ EXPECT_TRUE(
+ FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
+ EXPECT_EQ(255u, R);
+ EXPECT_EQ(255u, G);
+ EXPECT_EQ(0u, B);
+ EXPECT_EQ(255u, A);
+
+ // Check that the author is correct.
+ static constexpr char kAuthorKey[] = "T";
+ EXPECT_EQ(FPDF_OBJECT_STRING, FPDFAnnot_GetValueType(annot, kAuthorKey));
+ unsigned long len = FPDFAnnot_GetStringValue(annot, kAuthorKey, nullptr, 0);
+ std::vector<char> buf(len);
+ EXPECT_EQ(28u, FPDFAnnot_GetStringValue(annot, kAuthorKey, buf.data(), len));
+ EXPECT_STREQ(L"Jae Hyun Park", BufferToWString(buf).c_str());
+
+ // Check that the content is correct.
+ EXPECT_EQ(FPDF_OBJECT_STRING, FPDFAnnot_GetValueType(annot, kContentsKey));
+ len = FPDFAnnot_GetStringValue(annot, kContentsKey, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(2690u,
+ FPDFAnnot_GetStringValue(annot, kContentsKey, buf.data(), len));
+ const wchar_t contents[] =
+ L"This is a note for that highlight annotation. Very long highlight "
+ "annotation. Long long long Long long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long longLong long longLong long longLong long longLong long "
+ "longLong long long. END";
+ EXPECT_STREQ(contents, BufferToWString(buf).c_str());
+
+ // Check that the quadpoints are correct.
+ FS_QUADPOINTSF quadpoints;
+ ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, &quadpoints));
+ EXPECT_EQ(115.802643f, quadpoints.x1);
+ EXPECT_EQ(718.913940f, quadpoints.y1);
+ EXPECT_EQ(157.211182f, quadpoints.x4);
+ EXPECT_EQ(706.264465f, quadpoints.y4);
+
+ FPDFPage_CloseAnnot(annot);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, ExtractInkMultiple) {
+ // Open a file with three annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Check that there is a total of 3 annotation on its first page.
+ EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
+
+ // Check that the third annotation is of type "ink".
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 2);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(FPDF_ANNOT_INK, FPDFAnnot_GetSubtype(annot));
+
+ // Check that the annotation color is blue with opacity.
+ unsigned int R;
+ unsigned int G;
+ unsigned int B;
+ unsigned int A;
+ EXPECT_TRUE(
+ FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
+ EXPECT_EQ(0u, R);
+ EXPECT_EQ(0u, G);
+ EXPECT_EQ(255u, B);
+ EXPECT_EQ(76u, A);
+
+ // Check that there is no content.
+ EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot, kContentsKey, nullptr, 0));
+
+ // Check that the rectange coordinates are correct.
+ // Note that upon rendering, the rectangle coordinates will be adjusted.
+ FS_RECTF rect;
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_EQ(351.820404f, rect.left);
+ EXPECT_EQ(583.830688f, rect.bottom);
+ EXPECT_EQ(475.336090f, rect.right);
+ EXPECT_EQ(681.535034f, rect.top);
+
+ FPDFPage_CloseAnnot(annot);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, AddIllegalSubtypeAnnotation) {
+ // Open a file with one annotation and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Add an annotation with an illegal subtype.
+ ASSERT_FALSE(FPDFPage_CreateAnnot(page, -1));
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, AddFirstTextAnnotation) {
+ // Open a file with no annotation and load its first page.
+ ASSERT_TRUE(OpenDocument("hello_world.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+ EXPECT_EQ(0, FPDFPage_GetAnnotCount(page));
+
+ // Add a text annotation to the page.
+ FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_TEXT);
+ ASSERT_TRUE(annot);
+
+ // Check that there is now 1 annotations on this page.
+ EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
+
+ // Check that the subtype of the annotation is correct.
+ EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot));
+ FPDFPage_CloseAnnot(annot);
+
+ annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(FPDF_ANNOT_TEXT, FPDFAnnot_GetSubtype(annot));
+
+ // Set the color of the annotation.
+ ASSERT_TRUE(
+ FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204));
+ // Check that the color has been set correctly.
+ unsigned int R;
+ unsigned int G;
+ unsigned int B;
+ unsigned int A;
+ EXPECT_TRUE(
+ FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
+ EXPECT_EQ(51u, R);
+ EXPECT_EQ(102u, G);
+ EXPECT_EQ(153u, B);
+ EXPECT_EQ(204u, A);
+
+ // Change the color of the annotation.
+ ASSERT_TRUE(
+ FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 204, 153, 102, 51));
+ // Check that the color has been set correctly.
+ EXPECT_TRUE(
+ FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A));
+ EXPECT_EQ(204u, R);
+ EXPECT_EQ(153u, G);
+ EXPECT_EQ(102u, B);
+ EXPECT_EQ(51u, A);
+
+ // Set the annotation rectangle.
+ FS_RECTF rect;
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_EQ(0.f, rect.left);
+ EXPECT_EQ(0.f, rect.right);
+ rect.left = 35;
+ rect.bottom = 150;
+ rect.right = 53;
+ rect.top = 165;
+ ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
+ // Check that the annotation rectangle has been set correctly.
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_EQ(35.f, rect.left);
+ EXPECT_EQ(150.f, rect.bottom);
+ EXPECT_EQ(53.f, rect.right);
+ EXPECT_EQ(165.f, rect.top);
+
+ // Set the content of the annotation.
+ static constexpr wchar_t contents[] = L"Hello! This is a customized content.";
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
+ GetFPDFWideString(contents);
+ ASSERT_TRUE(FPDFAnnot_SetStringValue(annot, kContentsKey, text.get()));
+ // Check that the content has been set correctly.
+ unsigned long len = FPDFAnnot_GetStringValue(annot, kContentsKey, nullptr, 0);
+ std::vector<char> buf(len);
+ EXPECT_EQ(74u,
+ FPDFAnnot_GetStringValue(annot, kContentsKey, buf.data(), len));
+ EXPECT_STREQ(contents, BufferToWString(buf).c_str());
+
+ FPDFPage_CloseAnnot(annot);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, AddAndSaveUnderlineAnnotation) {
+ // Open a file with one annotation and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Check that there is a total of one annotation on its first page, and verify
+ // its quadpoints.
+ EXPECT_EQ(1, FPDFPage_GetAnnotCount(page));
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+ FS_QUADPOINTSF quadpoints;
+ ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, &quadpoints));
+ EXPECT_EQ(115.802643f, quadpoints.x1);
+ EXPECT_EQ(718.913940f, quadpoints.y1);
+ EXPECT_EQ(157.211182f, quadpoints.x4);
+ EXPECT_EQ(706.264465f, quadpoints.y4);
+ FPDFPage_CloseAnnot(annot);
+
+ // Add an underline annotation to the page and set its quadpoints.
+ annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE);
+ ASSERT_TRUE(annot);
+ quadpoints.x1 = 140.802643f;
+ quadpoints.x3 = 140.802643f;
+ ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
+ FPDFPage_CloseAnnot(annot);
+
+ // Save the document, closing the page and document.
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+
+ // Open the saved document.
+ const char md5[] = "dba153419f67b7c0c0e3d22d3e8910d5";
+
+ OpenSavedDocument();
+ page = LoadSavedPage(0);
+ VerifySavedRendering(page, 612, 792, md5);
+
+ // Check that the saved document has 2 annotations on the first page
+ EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
+
+ // Check that the second annotation is an underline annotation and verify
+ // its quadpoints.
+ FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(page, 1);
+ ASSERT_TRUE(new_annot);
+ EXPECT_EQ(FPDF_ANNOT_UNDERLINE, FPDFAnnot_GetSubtype(new_annot));
+ FS_QUADPOINTSF new_quadpoints;
+ ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(new_annot, &new_quadpoints));
+ EXPECT_NEAR(quadpoints.x1, new_quadpoints.x1, 0.001f);
+ EXPECT_NEAR(quadpoints.y1, new_quadpoints.y1, 0.001f);
+ EXPECT_NEAR(quadpoints.x4, new_quadpoints.x4, 0.001f);
+ EXPECT_NEAR(quadpoints.y4, new_quadpoints.y4, 0.001f);
+
+ FPDFPage_CloseAnnot(new_annot);
+
+ CloseSavedPage(page);
+ CloseSavedDocument();
+}
+
+TEST_F(FPDFAnnotEmbeddertest, ModifyRectQuadpointsWithAP) {
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5_original[] = "63af8432fab95a67cdebb7cd0e514941";
+ const char md5_modified_highlight[] = "aec26075011349dec9bace891856b5f2";
+ const char md5_modified_square[] = "057f57a32be95975775e5ec513fdcb56";
+#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
+ const char md5_original[] = "0e27376094f11490f74c65f3dc3a42c5";
+ const char md5_modified_highlight[] = "66f3caef3a7d488a4fa1ad37fc06310e";
+ const char md5_modified_square[] = "a456dad0bc6801ee2d6408a4394af563";
+#else
+ const char md5_original[] = "0e27376094f11490f74c65f3dc3a42c5";
+ const char md5_modified_highlight[] = "66f3caef3a7d488a4fa1ad37fc06310e";
+ const char md5_modified_square[] = "a456dad0bc6801ee2d6408a4394af563";
+#endif
+
+ // Open a file with four annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+ EXPECT_EQ(4, FPDFPage_GetAnnotCount(page));
+
+ // Check that the original file renders correctly.
+ FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 612, 792, md5_original);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Retrieve the highlight annotation which has its AP stream already defined.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
+
+ // Check that color cannot be set when an AP stream is defined already.
+ EXPECT_FALSE(
+ FPDFAnnot_SetColor(annot, FPDFANNOT_COLORTYPE_Color, 51, 102, 153, 204));
+
+ // Verify its attachment points.
+ FS_QUADPOINTSF quadpoints;
+ ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, &quadpoints));
+ EXPECT_NEAR(72.0000f, quadpoints.x1, 0.001f);
+ EXPECT_NEAR(720.792f, quadpoints.y1, 0.001f);
+ EXPECT_NEAR(132.055f, quadpoints.x4, 0.001f);
+ EXPECT_NEAR(704.796f, quadpoints.y4, 0.001f);
+
+ // Check that updating the attachment points would succeed.
+ quadpoints.x1 -= 50.f;
+ quadpoints.x2 -= 50.f;
+ quadpoints.x3 -= 50.f;
+ quadpoints.x4 -= 50.f;
+ ASSERT_TRUE(FPDFAnnot_SetAttachmentPoints(annot, &quadpoints));
+ FS_QUADPOINTSF new_quadpoints;
+ ASSERT_TRUE(FPDFAnnot_GetAttachmentPoints(annot, &new_quadpoints));
+ EXPECT_EQ(quadpoints.x1, new_quadpoints.x1);
+ EXPECT_EQ(quadpoints.y1, new_quadpoints.y1);
+ EXPECT_EQ(quadpoints.x4, new_quadpoints.x4);
+ EXPECT_EQ(quadpoints.y4, new_quadpoints.y4);
+
+ // Check that updating quadpoints does not change the annotation's position.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 612, 792, md5_original);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Verify its annotation rectangle.
+ FS_RECTF rect;
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_NEAR(67.7299f, rect.left, 0.001f);
+ EXPECT_NEAR(704.296f, rect.bottom, 0.001f);
+ EXPECT_NEAR(136.325f, rect.right, 0.001f);
+ EXPECT_NEAR(721.292f, rect.top, 0.001f);
+
+ // Check that updating the rectangle would succeed.
+ rect.left -= 60.f;
+ rect.right -= 60.f;
+ ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
+ FS_RECTF new_rect;
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &new_rect));
+ EXPECT_EQ(rect.right, new_rect.right);
+ FPDFPage_CloseAnnot(annot);
+
+ // Check that updating the rectangle changes the annotation's position.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 612, 792, md5_modified_highlight);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Retrieve the square annotation which has its AP stream already defined.
+ annot = FPDFPage_GetAnnot(page, 2);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot));
+
+ // Check that updating the rectangle would succeed.
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ rect.left += 70.f;
+ rect.right += 70.f;
+ ASSERT_TRUE(FPDFAnnot_SetRect(annot, &rect));
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &new_rect));
+ EXPECT_EQ(rect.right, new_rect.right);
+
+ // Check that updating the rectangle changes the square annotation's position.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 612, 792, md5_modified_square);
+ FPDFBitmap_Destroy(bitmap);
+
+ FPDFPage_CloseAnnot(annot);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, RemoveAnnotation) {
+ // Open a file with 3 annotations on its first page.
+ ASSERT_TRUE(OpenDocument("annotation_ink_multiple.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+ EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
+
+ // Check that the annotations have the expected rectangle coordinates.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ FS_RECTF rect;
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_NEAR(86.1971f, rect.left, 0.001f);
+ FPDFPage_CloseAnnot(annot);
+
+ annot = FPDFPage_GetAnnot(page, 1);
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_NEAR(149.8127f, rect.left, 0.001f);
+ FPDFPage_CloseAnnot(annot);
+
+ annot = FPDFPage_GetAnnot(page, 2);
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_NEAR(351.8204f, rect.left, 0.001f);
+ FPDFPage_CloseAnnot(annot);
+
+ // Check that nothing happens when attempting to remove an annotation with an
+ // out-of-bound index.
+ EXPECT_FALSE(FPDFPage_RemoveAnnot(page, 4));
+ EXPECT_FALSE(FPDFPage_RemoveAnnot(page, -1));
+ EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
+
+ // Remove the second annotation.
+ EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 1));
+ EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
+ EXPECT_FALSE(FPDFPage_GetAnnot(page, 2));
+
+ // Save the document, closing the page and document.
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+
+ // TODO(npm): VerifySavedRendering changes annot rect dimensions by 1??
+ // Open the saved document.
+ std::string new_file = GetString();
+ FPDF_FILEACCESS file_access;
+ memset(&file_access, 0, sizeof(file_access));
+ file_access.m_FileLen = new_file.size();
+ file_access.m_GetBlock = GetBlockFromString;
+ file_access.m_Param = &new_file;
+ FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
+ ASSERT_TRUE(new_doc);
+ FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
+ ASSERT_TRUE(new_page);
+
+ // Check that the saved document has 2 annotations on the first page.
+ EXPECT_EQ(2, FPDFPage_GetAnnotCount(new_page));
+
+ // Check that the remaining 2 annotations are the original 1st and 3rd ones by
+ // verifying their rectangle coordinates.
+ annot = FPDFPage_GetAnnot(new_page, 0);
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_NEAR(86.1971f, rect.left, 0.001f);
+ FPDFPage_CloseAnnot(annot);
+
+ annot = FPDFPage_GetAnnot(new_page, 1);
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &rect));
+ EXPECT_NEAR(351.8204f, rect.left, 0.001f);
+ FPDFPage_CloseAnnot(annot);
+ FPDF_ClosePage(new_page);
+ FPDF_CloseDocument(new_doc);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, AddAndModifyPath) {
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
+ const char md5_modified_path[] = "cf3cea74bd46497520ff6c4d1ea228c8";
+ const char md5_two_paths[] = "e8994452fc4385337bae5522354e10ff";
+ const char md5_new_annot[] = "ee5372b31fede117fc83b9384598aa25";
+#else
+ const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e";
+ const char md5_modified_path[] = "3f77b88ce6048e08e636c9a03921b2e5";
+ const char md5_two_paths[] = "bffbf5ecd15862b9fe553c795400ff8e";
+ const char md5_new_annot[] = "e020534c7eeea76be537c70d6e359a40";
+#endif
+
+ // Open a file with two annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+ EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
+
+ // Check that the page renders correctly.
+ FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_original);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Retrieve the stamp annotation which has its AP stream already defined.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+
+ // Check that this annotation has one path object and retrieve it.
+ EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
+ FPDF_PAGEOBJECT path = FPDFAnnot_GetObject(annot, 1);
+ EXPECT_FALSE(path);
+ path = FPDFAnnot_GetObject(annot, 0);
+ EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
+ EXPECT_TRUE(path);
+
+ // Modify the color of the path object.
+ EXPECT_TRUE(FPDFPath_SetStrokeColor(path, 0, 0, 0, 255));
+ EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, path));
+
+ // Check that the page with the modified annotation renders correctly.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_modified_path);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Add a second path object to the same annotation.
+ FPDF_PAGEOBJECT dot = FPDFPageObj_CreateNewPath(7, 84);
+ EXPECT_TRUE(FPDFPath_BezierTo(dot, 9, 86, 10, 87, 11, 88));
+ EXPECT_TRUE(FPDFPath_SetStrokeColor(dot, 255, 0, 0, 100));
+ EXPECT_TRUE(FPDFPath_SetStrokeWidth(dot, 14));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(dot, 0, 1));
+ EXPECT_TRUE(FPDFAnnot_AppendObject(annot, dot));
+ EXPECT_EQ(2, FPDFAnnot_GetObjectCount(annot));
+
+ // Check that the page with an annotation with two paths renders correctly.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_two_paths);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Delete the newly added path object.
+ EXPECT_TRUE(FPDFAnnot_RemoveObject(annot, 1));
+ EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
+ FPDFPage_CloseAnnot(annot);
+
+ // Check that the page renders the same as before.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_modified_path);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Create another stamp annotation and set its annotation rectangle.
+ annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP);
+ ASSERT_TRUE(annot);
+ FS_RECTF rect;
+ rect.left = 200.f;
+ rect.bottom = 400.f;
+ rect.right = 500.f;
+ rect.top = 600.f;
+ EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect));
+
+ // Add a new path to the annotation.
+ FPDF_PAGEOBJECT check = FPDFPageObj_CreateNewPath(200, 500);
+ EXPECT_TRUE(FPDFPath_LineTo(check, 300, 400));
+ EXPECT_TRUE(FPDFPath_LineTo(check, 500, 600));
+ EXPECT_TRUE(FPDFPath_MoveTo(check, 350, 550));
+ EXPECT_TRUE(FPDFPath_LineTo(check, 450, 450));
+ EXPECT_TRUE(FPDFPath_SetStrokeColor(check, 0, 255, 255, 180));
+ EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
+ EXPECT_TRUE(FPDFAnnot_AppendObject(annot, check));
+ EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
+
+ // Check that the annotation's bounding box came from its rectangle.
+ FS_RECTF new_rect;
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &new_rect));
+ EXPECT_EQ(rect.left, new_rect.left);
+ EXPECT_EQ(rect.bottom, new_rect.bottom);
+ EXPECT_EQ(rect.right, new_rect.right);
+ EXPECT_EQ(rect.top, new_rect.top);
+
+ // Save the document, closing the page and document.
+ FPDFPage_CloseAnnot(annot);
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+
+ // Open the saved document.
+ OpenSavedDocument();
+ page = LoadSavedPage(0);
+ VerifySavedRendering(page, 595, 842, md5_new_annot);
+
+ // Check that the document has a correct count of annotations and objects.
+ EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
+ annot = FPDFPage_GetAnnot(page, 2);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
+
+ // Check that the new annotation's rectangle is as defined.
+ ASSERT_TRUE(FPDFAnnot_GetRect(annot, &new_rect));
+ EXPECT_EQ(rect.left, new_rect.left);
+ EXPECT_EQ(rect.bottom, new_rect.bottom);
+ EXPECT_EQ(rect.right, new_rect.right);
+ EXPECT_EQ(rect.top, new_rect.top);
+
+ FPDFPage_CloseAnnot(annot);
+ CloseSavedPage(page);
+ CloseSavedDocument();
+}
+
+TEST_F(FPDFAnnotEmbeddertest, ModifyAnnotationFlags) {
+ // Open a file with an annotation and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_highlight_rollover_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Check that the page renders correctly.
+ FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
+ FPDFBitmap_Destroy(bitmap);
+
+ // Retrieve the annotation.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+
+ // Check that the original flag values are as expected.
+ int flags = FPDFAnnot_GetFlags(annot);
+ EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
+ EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
+
+ // Set the HIDDEN flag.
+ flags |= FPDF_ANNOT_FLAG_HIDDEN;
+ EXPECT_TRUE(FPDFAnnot_SetFlags(annot, flags));
+ flags = FPDFAnnot_GetFlags(annot);
+ EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_HIDDEN);
+ EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
+
+ // Check that the page renders correctly without rendering the annotation.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 612, 792, "1940568c9ba33bac5d0b1ee9558c76b3");
+ FPDFBitmap_Destroy(bitmap);
+
+ // Unset the HIDDEN flag.
+ EXPECT_TRUE(FPDFAnnot_SetFlags(annot, FPDF_ANNOT_FLAG_NONE));
+ EXPECT_FALSE(FPDFAnnot_GetFlags(annot));
+ flags &= ~FPDF_ANNOT_FLAG_HIDDEN;
+ EXPECT_TRUE(FPDFAnnot_SetFlags(annot, flags));
+ flags = FPDFAnnot_GetFlags(annot);
+ EXPECT_FALSE(flags & FPDF_ANNOT_FLAG_HIDDEN);
+ EXPECT_TRUE(flags & FPDF_ANNOT_FLAG_PRINT);
+
+ // Check that the page renders correctly as before.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 612, 792, "dc98f06da047bd8aabfa99562d2cbd1e");
+ FPDFBitmap_Destroy(bitmap);
+
+ FPDFPage_CloseAnnot(annot);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, AddAndModifyImage) {
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
+ const char md5_new_image[] = "ff012f5697436dfcaec25b32d1333596";
+ const char md5_modified_image[] = "86cf8cb2755a7a2046a543e66d9c1e61";
+#else
+ const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e";
+ const char md5_new_image[] = "9ea8732dc9d579f68853f16892856208";
+ const char md5_modified_image[] = "74239d2a8c55c9de1dbb9cd8781895aa";
+#endif
+
+ // Open a file with two annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+ EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
+
+ // Check that the page renders correctly.
+ FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_original);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Create a stamp annotation and set its annotation rectangle.
+ FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP);
+ ASSERT_TRUE(annot);
+ FS_RECTF rect;
+ rect.left = 200.f;
+ rect.bottom = 600.f;
+ rect.right = 400.f;
+ rect.top = 800.f;
+ EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect));
+
+ // Add a solid-color translucent image object to the new annotation.
+ constexpr int kBitmapSize = 200;
+ FPDF_BITMAP image_bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 1);
+ FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize, 0xeeeecccc);
+ EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(image_bitmap));
+ EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(image_bitmap));
+ FPDF_PAGEOBJECT image_object = FPDFPageObj_NewImageObj(document());
+ ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
+ ASSERT_TRUE(FPDFImageObj_SetMatrix(image_object, kBitmapSize, 0, 0,
+ kBitmapSize, 0, 0));
+ FPDFPageObj_Transform(image_object, 1, 0, 0, 1, 200, 600);
+ EXPECT_TRUE(FPDFAnnot_AppendObject(annot, image_object));
+ FPDFPage_CloseAnnot(annot);
+
+ // Check that the page renders correctly with the new image object.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_new_image);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Retrieve the newly added stamp annotation and its image object.
+ annot = FPDFPage_GetAnnot(page, 2);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
+ image_object = FPDFAnnot_GetObject(annot, 0);
+ EXPECT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(image_object));
+
+ // Modify the image in the new annotation.
+ FPDFBitmap_FillRect(image_bitmap, 0, 0, kBitmapSize, kBitmapSize, 0xff000000);
+ ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, image_object, image_bitmap));
+ EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, image_object));
+ FPDFPage_CloseAnnot(annot);
+
+ // Save the document, closing the page and document.
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+ FPDFBitmap_Destroy(image_bitmap);
+
+ // Test that the saved document renders the modified image object correctly.
+ VerifySavedDocument(595, 842, md5_modified_image);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, AddAndModifyText) {
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5_original[] = "c35408717759562d1f8bf33d317483d2";
+ const char md5_new_text[] = "e5680ed048c2cfd9a1d27212cdf41286";
+ const char md5_modified_text[] = "79f5cfb0b07caaf936f65f6a7a57ce77";
+#else
+ const char md5_original[] = "964f89bbe8911e540a465cf1a64b7f7e";
+ const char md5_new_text[] = "00b14fa2dc1c90d1b0d034e1608efef5";
+ const char md5_modified_text[] = "076c8f24a09ddc0e49f7e758edead6f0";
+#endif
+
+ // Open a file with two annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+ EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
+
+ // Check that the page renders correctly.
+ FPDF_BITMAP bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_original);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Create a stamp annotation and set its annotation rectangle.
+ FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_STAMP);
+ ASSERT_TRUE(annot);
+ FS_RECTF rect;
+ rect.left = 200.f;
+ rect.bottom = 550.f;
+ rect.right = 450.f;
+ rect.top = 650.f;
+ EXPECT_TRUE(FPDFAnnot_SetRect(annot, &rect));
+
+ // Add a translucent text object to the new annotation.
+ FPDF_PAGEOBJECT text_object =
+ FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
+ EXPECT_TRUE(text_object);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
+ GetFPDFWideString(L"I'm a translucent text laying on other text.");
+ EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
+ EXPECT_TRUE(FPDFText_SetFillColor(text_object, 0, 0, 255, 150));
+ FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 600);
+ EXPECT_TRUE(FPDFAnnot_AppendObject(annot, text_object));
+ FPDFPage_CloseAnnot(annot);
+
+ // Check that the page renders correctly with the new text object.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_new_text);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Retrieve the newly added stamp annotation and its text object.
+ annot = FPDFPage_GetAnnot(page, 2);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(1, FPDFAnnot_GetObjectCount(annot));
+ text_object = FPDFAnnot_GetObject(annot, 0);
+ EXPECT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(text_object));
+
+ // Modify the text in the new annotation.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> new_text =
+ GetFPDFWideString(L"New text!");
+ EXPECT_TRUE(FPDFText_SetText(text_object, new_text.get()));
+ EXPECT_TRUE(FPDFAnnot_UpdateObject(annot, text_object));
+ FPDFPage_CloseAnnot(annot);
+
+ // Check that the page renders correctly with the modified text object.
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_modified_text);
+ FPDFBitmap_Destroy(bitmap);
+
+ // Remove the new annotation, and check that the page renders as before.
+ EXPECT_TRUE(FPDFPage_RemoveAnnot(page, 2));
+ bitmap = RenderPageWithFlags(page, form_handle_, FPDF_ANNOT);
+ CompareBitmap(bitmap, 595, 842, md5_original);
+ FPDFBitmap_Destroy(bitmap);
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, GetSetStringValue) {
+ // Open a file with four annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Retrieve the first annotation.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+
+ // Check that a non-existent key does not exist.
+ EXPECT_FALSE(FPDFAnnot_HasKey(annot, "none"));
+
+ // Check that the string value of a non-string dictionary entry is empty.
+ static constexpr char kApKey[] = "AP";
+ EXPECT_TRUE(FPDFAnnot_HasKey(annot, kApKey));
+ EXPECT_EQ(FPDF_OBJECT_REFERENCE, FPDFAnnot_GetValueType(annot, kApKey));
+ EXPECT_EQ(2u, FPDFAnnot_GetStringValue(annot, kApKey, nullptr, 0));
+
+ // Check that the string value of the hash is correct.
+ static constexpr char kHashKey[] = "AAPL:Hash";
+ EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot, kHashKey));
+ unsigned long len = FPDFAnnot_GetStringValue(annot, kHashKey, nullptr, 0);
+ std::vector<char> buf(len);
+ EXPECT_EQ(66u, FPDFAnnot_GetStringValue(annot, kHashKey, buf.data(), len));
+ EXPECT_STREQ(L"395fbcb98d558681742f30683a62a2ad",
+ BufferToWString(buf).c_str());
+
+ // Check that the string value of the modified date is correct.
+ static constexpr char kDateKey[] = "M";
+ EXPECT_EQ(FPDF_OBJECT_NAME, FPDFAnnot_GetValueType(annot, kHashKey));
+ len = FPDFAnnot_GetStringValue(annot, kDateKey, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(44u, FPDFAnnot_GetStringValue(annot, kDateKey, buf.data(), len));
+ EXPECT_STREQ(L"D:201706071721Z00'00'", BufferToWString(buf).c_str());
+
+ // Update the date entry for the annotation.
+ const wchar_t new_date[] = L"D:201706282359Z00'00'";
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
+ GetFPDFWideString(new_date);
+ EXPECT_TRUE(FPDFAnnot_SetStringValue(annot, kDateKey, text.get()));
+
+ // Save the document, closing the page and document.
+ FPDFPage_CloseAnnot(annot);
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+
+ // Open the saved annotation.
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5[] = "4d64e61c9c0f8c60ab3cc3234bb73b1c";
+#else
+ const char md5[] = "c96ee1f316d7f5a1b154de9f9d467f01";
+#endif
+ OpenSavedDocument();
+ page = LoadSavedPage(0);
+ VerifySavedRendering(page, 595, 842, md5);
+ FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(page, 0);
+
+ // Check that the string value of the modified date is the newly-set value.
+ EXPECT_EQ(FPDF_OBJECT_STRING, FPDFAnnot_GetValueType(new_annot, kDateKey));
+ len = FPDFAnnot_GetStringValue(new_annot, kDateKey, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(44u,
+ FPDFAnnot_GetStringValue(new_annot, kDateKey, buf.data(), len));
+ EXPECT_STREQ(new_date, BufferToWString(buf).c_str());
+
+ FPDFPage_CloseAnnot(new_annot);
+ CloseSavedPage(page);
+ CloseSavedDocument();
+}
+
+TEST_F(FPDFAnnotEmbeddertest, GetSetAP) {
+ // Open a file with four annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Retrieve the first annotation.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+
+ // Check that the string value of an AP returns the expected length.
+ unsigned long normal_len =
+ FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
+ EXPECT_EQ(73970u, normal_len);
+
+ // Check that the string value of an AP is not returned if the buffer is too
+ // small. The result buffer should be overwritten with an empty string.
+ std::vector<char> buf(normal_len - 1);
+ // Write L"z" in the buffer to verify it's not overwritten.
+ wcscpy(reinterpret_cast<wchar_t*>(buf.data()), L"z");
+ EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+ buf.data(), buf.size()));
+ std::string ap = BufferToString(buf);
+ EXPECT_STREQ("z", ap.c_str());
+
+ // Check that the string value of an AP is returned through a buffer that is
+ // the right size.
+ buf.clear();
+ buf.resize(normal_len);
+ EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+ buf.data(), buf.size()));
+ ap = BufferToString(buf);
+ EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J"));
+ EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q"));
+
+ // Check that the string value of an AP is returned through a buffer that is
+ // larger than necessary.
+ buf.clear();
+ buf.resize(normal_len + 1);
+ EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+ buf.data(), buf.size()));
+ ap = BufferToString(buf);
+ EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J"));
+ EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q"));
+
+ // Check that getting an AP for a mode that does not have an AP returns an
+ // empty string.
+ unsigned long rollover_len =
+ FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
+ EXPECT_EQ(2u, rollover_len);
+
+ buf.clear();
+ buf.resize(1000);
+ EXPECT_EQ(2u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
+ buf.data(), buf.size()));
+ EXPECT_STREQ("", BufferToString(buf).c_str());
+
+ // Check that setting the AP for an invalid appearance mode fails.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> apText =
+ GetFPDFWideString(L"new test ap");
+ EXPECT_FALSE(FPDFAnnot_SetAP(annot, -1, apText.get()));
+ EXPECT_FALSE(
+ FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_COUNT, apText.get()));
+ EXPECT_FALSE(FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_COUNT + 1,
+ apText.get()));
+
+ // Set the AP correctly now.
+ EXPECT_TRUE(
+ FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, apText.get()));
+
+ // Check that the new annotation value is equal to the value we just set.
+ rollover_len =
+ FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER, nullptr, 0);
+ EXPECT_EQ(24u, rollover_len);
+ buf.clear();
+ buf.resize(rollover_len);
+ EXPECT_EQ(24u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
+ buf.data(), buf.size()));
+ EXPECT_STREQ(L"new test ap", BufferToWString(buf).c_str());
+
+ // Check that the Normal AP was not touched when the Rollover AP was set.
+ buf.clear();
+ buf.resize(normal_len);
+ EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+ buf.data(), buf.size()));
+ ap = BufferToString(buf);
+ EXPECT_THAT(ap, testing::StartsWith("q Q q 7.442786 w 2 J"));
+ EXPECT_THAT(ap, testing::EndsWith("c 716.5381 327.7156 l S Q Q"));
+
+ // Save the modified document, then reopen it.
+ FPDFPage_CloseAnnot(annot);
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+
+ OpenSavedDocument();
+ page = LoadSavedPage(0);
+ FPDF_ANNOTATION new_annot = FPDFPage_GetAnnot(page, 0);
+
+ // Check that the new annotation value is equal to the value we set before
+ // saving.
+ rollover_len = FPDFAnnot_GetAP(new_annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
+ nullptr, 0);
+ EXPECT_EQ(24u, rollover_len);
+ buf.clear();
+ buf.resize(rollover_len);
+ EXPECT_EQ(24u, FPDFAnnot_GetAP(new_annot, FPDF_ANNOT_APPEARANCEMODE_ROLLOVER,
+ buf.data(), buf.size()));
+ EXPECT_STREQ(L"new test ap", BufferToWString(buf).c_str());
+
+ // Close saved document.
+ FPDFPage_CloseAnnot(new_annot);
+ CloseSavedPage(page);
+ CloseSavedDocument();
+}
+
+TEST_F(FPDFAnnotEmbeddertest, RemoveOptionalAP) {
+ // Open a file with four annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Retrieve the first annotation.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+
+ // Set Down AP. Normal AP is already set.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> apText =
+ GetFPDFWideString(L"new test ap");
+ EXPECT_TRUE(
+ FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, apText.get()));
+ EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+ nullptr, 0));
+ EXPECT_EQ(24u,
+ FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr, 0));
+
+ // Check that setting the Down AP to null removes the Down entry but keeps
+ // Normal intact.
+ EXPECT_TRUE(FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr));
+ EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+ nullptr, 0));
+ EXPECT_EQ(2u,
+ FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr, 0));
+
+ FPDFPage_CloseAnnot(annot);
+ FPDF_ClosePage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, RemoveRequiredAP) {
+ // Open a file with four annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Retrieve the first annotation.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+
+ // Set Down AP. Normal AP is already set.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> apText =
+ GetFPDFWideString(L"new test ap");
+ EXPECT_TRUE(
+ FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, apText.get()));
+ EXPECT_EQ(73970u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+ nullptr, 0));
+ EXPECT_EQ(24u,
+ FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr, 0));
+
+ // Check that setting the Normal AP to null removes the whole AP dictionary.
+ EXPECT_TRUE(
+ FPDFAnnot_SetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr));
+ EXPECT_EQ(
+ 2u, FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0));
+ EXPECT_EQ(2u,
+ FPDFAnnot_GetAP(annot, FPDF_ANNOT_APPEARANCEMODE_DOWN, nullptr, 0));
+
+ FPDFPage_CloseAnnot(annot);
+ FPDF_ClosePage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, ExtractLinkedAnnotations) {
+ // Open a file with annotations and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+ EXPECT_EQ(-1, FPDFPage_GetAnnotIndex(page, nullptr));
+
+ // Retrieve the highlight annotation which has its popup defined.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+ EXPECT_EQ(FPDF_ANNOT_HIGHLIGHT, FPDFAnnot_GetSubtype(annot));
+ EXPECT_EQ(0, FPDFPage_GetAnnotIndex(page, annot));
+ static constexpr char kPopupKey[] = "Popup";
+ ASSERT_TRUE(FPDFAnnot_HasKey(annot, kPopupKey));
+ ASSERT_EQ(FPDF_OBJECT_REFERENCE, FPDFAnnot_GetValueType(annot, kPopupKey));
+
+ // Retrieve and verify the popup of the highlight annotation.
+ FPDF_ANNOTATION popup = FPDFAnnot_GetLinkedAnnot(annot, kPopupKey);
+ ASSERT_TRUE(popup);
+ EXPECT_EQ(FPDF_ANNOT_POPUP, FPDFAnnot_GetSubtype(popup));
+ EXPECT_EQ(1, FPDFPage_GetAnnotIndex(page, popup));
+ FS_RECTF rect;
+ ASSERT_TRUE(FPDFAnnot_GetRect(popup, &rect));
+ EXPECT_NEAR(612.0f, rect.left, 0.001f);
+ EXPECT_NEAR(578.792, rect.bottom, 0.001f);
+
+ // Attempting to retrieve |annot|'s "IRT"-linked annotation would fail, since
+ // "IRT" is not a key in |annot|'s dictionary.
+ static constexpr char kIRTKey[] = "IRT";
+ ASSERT_FALSE(FPDFAnnot_HasKey(annot, kIRTKey));
+ EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot, kIRTKey));
+
+ // Attempting to retrieve |annot|'s parent dictionary as an annotation would
+ // fail, since its parent is not an annotation.
+ static constexpr char kPKey[] = "P";
+ ASSERT_TRUE(FPDFAnnot_HasKey(annot, kPKey));
+ EXPECT_EQ(FPDF_OBJECT_REFERENCE, FPDFAnnot_GetValueType(annot, kPKey));
+ EXPECT_FALSE(FPDFAnnot_GetLinkedAnnot(annot, kPKey));
+
+ FPDFPage_CloseAnnot(popup);
+ FPDFPage_CloseAnnot(annot);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, GetFormFieldFlagsTextField) {
+ // Open file with form text fields.
+ ASSERT_TRUE(OpenDocument("text_form_multiple.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Retrieve the first annotation: user-editable text field.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+
+ // Check that the flag values are as expected.
+ int flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
+ FPDFPage_CloseAnnot(annot);
+
+ // Retrieve the second annotation: read-only text field.
+ annot = FPDFPage_GetAnnot(page, 1);
+ ASSERT_TRUE(annot);
+
+ // Check that the flag values are as expected.
+ flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
+ FPDFPage_CloseAnnot(annot);
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, GetFormFieldFlagsComboBox) {
+ // Open file with form text fields.
+ ASSERT_TRUE(OpenDocument("combobox_form.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Retrieve the first annotation: user-editable combobox.
+ FPDF_ANNOTATION annot = FPDFPage_GetAnnot(page, 0);
+ ASSERT_TRUE(annot);
+
+ // Check that the flag values are as expected.
+ int flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
+ FPDFPage_CloseAnnot(annot);
+
+ // Retrieve the second annotation: regular combobox.
+ annot = FPDFPage_GetAnnot(page, 1);
+ ASSERT_TRUE(annot);
+
+ // Check that the flag values are as expected.
+ flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
+ FPDFPage_CloseAnnot(annot);
+
+ // Retrieve the third annotation: read-only combobox.
+ annot = FPDFPage_GetAnnot(page, 2);
+ ASSERT_TRUE(annot);
+
+ // Check that the flag values are as expected.
+ flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
+ FPDFPage_CloseAnnot(annot);
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotNull) {
+ // Open file with form text fields.
+ EXPECT_TRUE(OpenDocument("text_form.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ // Attempt to get an annotation where no annotation exists on page.
+ FPDF_ANNOTATION annot =
+ FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 0, 0);
+ EXPECT_FALSE(annot);
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotAndCheckFlagsTextField) {
+ // Open file with form text fields.
+ EXPECT_TRUE(OpenDocument("text_form_multiple.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ // Retrieve user-editable text field annotation.
+ FPDF_ANNOTATION annot =
+ FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 118);
+ ASSERT_TRUE(annot);
+
+ // Check that interactive form annotation flag values are as expected.
+ int flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
+ FPDFPage_CloseAnnot(annot);
+
+ // Retrieve read-only text field annotation.
+ annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 105, 202);
+ ASSERT_TRUE(annot);
+
+ // Check that interactive form annotation flag values are as expected.
+ flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
+ FPDFPage_CloseAnnot(annot);
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFAnnotEmbeddertest, GetFormAnnotAndCheckFlagsComboBox) {
+ // Open file with form comboboxes.
+ EXPECT_TRUE(OpenDocument("combobox_form.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ // Retrieve user-editable combobox annotation.
+ FPDF_ANNOTATION annot =
+ FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 63);
+ ASSERT_TRUE(annot);
+
+ // Check that interactive form annotation flag values are as expected.
+ int flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
+ FPDFPage_CloseAnnot(annot);
+
+ // Retrieve regular combobox annotation.
+ annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 113);
+ ASSERT_TRUE(annot);
+
+ // Check that interactive form annotation flag values are as expected.
+ flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_READONLY);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
+ FPDFPage_CloseAnnot(annot);
+
+ // Retrieve read-only combobox annotation.
+ annot = FPDFAnnot_GetFormFieldAtPoint(form_handle(), page, 102, 213);
+ ASSERT_TRUE(annot);
+
+ // Check that interactive form annotation flag values are as expected.
+ flags = FPDFAnnot_GetFormFieldFlags(page, annot);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_READONLY);
+ EXPECT_TRUE(flags & FPDF_FORMFLAG_CHOICE_COMBO);
+ EXPECT_FALSE(flags & FPDF_FORMFLAG_CHOICE_EDIT);
+ FPDFPage_CloseAnnot(annot);
+
+ UnloadPage(page);
+}
diff --git a/fpdfsdk/fpdfattachment.cpp b/fpdfsdk/fpdfattachment.cpp
new file mode 100644
index 0000000..eb83534
--- /dev/null
+++ b/fpdfsdk/fpdfattachment.cpp
@@ -0,0 +1,271 @@
+// 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.
+
+#include "public/fpdf_attachment.h"
+
+#include <memory>
+#include <utility>
+
+#include "core/fdrm/crypto/fx_crypt.h"
+#include "core/fpdfapi/parser/cpdf_array.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_string.h"
+#include "core/fpdfapi/parser/fpdf_parser_decode.h"
+#include "core/fpdfdoc/cpdf_filespec.h"
+#include "core/fpdfdoc/cpdf_nametree.h"
+#include "core/fxcrt/cfx_datetime.h"
+#include "core/fxcrt/fx_extension.h"
+#include "fpdfsdk/fsdk_define.h"
+
+namespace {
+
+constexpr char kChecksumKey[] = "CheckSum";
+
+ByteString CFXByteStringHexDecode(const ByteString& bsHex) {
+ uint8_t* result = nullptr;
+ uint32_t size = 0;
+ HexDecode(bsHex.raw_str(), bsHex.GetLength(), &result, &size);
+ ByteString bsDecoded(result, size);
+ FX_Free(result);
+ return bsDecoded;
+}
+
+ByteString GenerateMD5Base16(const void* contents, const unsigned long len) {
+ uint8_t digest[16];
+ CRYPT_MD5Generate(reinterpret_cast<const uint8_t*>(contents), len, digest);
+ char buf[32];
+ for (int i = 0; i < 16; ++i)
+ FXSYS_IntToTwoHexChars(digest[i], &buf[i * 2]);
+
+ return ByteString(buf, 32);
+}
+
+} // namespace
+
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFDoc_GetAttachmentCount(FPDF_DOCUMENT document) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc)
+ return 0;
+
+ return CPDF_NameTree(pDoc, "EmbeddedFiles").GetCount();
+}
+
+FPDF_EXPORT FPDF_ATTACHMENT FPDF_CALLCONV
+FPDFDoc_AddAttachment(FPDF_DOCUMENT document, FPDF_WIDESTRING name) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ WideString wsName =
+ WideString::FromUTF16LE(name, WideString::WStringLength(name));
+ if (!pDoc || wsName.IsEmpty())
+ return nullptr;
+
+ CPDF_Dictionary* pRoot = pDoc->GetRoot();
+ if (!pRoot)
+ return nullptr;
+
+ // Retrieve the document's Names dictionary; create it if missing.
+ CPDF_Dictionary* pNames = pRoot->GetDictFor("Names");
+ if (!pNames) {
+ pNames = pDoc->NewIndirect<CPDF_Dictionary>();
+ pRoot->SetNewFor<CPDF_Reference>("Names", pDoc, pNames->GetObjNum());
+ }
+
+ // Create the EmbeddedFiles dictionary if missing.
+ if (!pNames->GetDictFor("EmbeddedFiles")) {
+ CPDF_Dictionary* pFiles = pDoc->NewIndirect<CPDF_Dictionary>();
+ pFiles->SetNewFor<CPDF_Array>("Names");
+ pNames->SetNewFor<CPDF_Reference>("EmbeddedFiles", pDoc,
+ pFiles->GetObjNum());
+ }
+
+ // Set up the basic entries in the filespec dictionary.
+ CPDF_Dictionary* pFile = pDoc->NewIndirect<CPDF_Dictionary>();
+ pFile->SetNewFor<CPDF_Name>("Type", "Filespec");
+ pFile->SetNewFor<CPDF_String>("UF", wsName);
+ pFile->SetNewFor<CPDF_String>("F", wsName);
+
+ // Add the new attachment name and filespec into the document's EmbeddedFiles.
+ CPDF_NameTree nameTree(pDoc, "EmbeddedFiles");
+ if (!nameTree.AddValueAndName(
+ pdfium::MakeUnique<CPDF_Reference>(pDoc, pFile->GetObjNum()),
+ wsName)) {
+ return nullptr;
+ }
+
+ return pFile;
+}
+
+FPDF_EXPORT FPDF_ATTACHMENT FPDF_CALLCONV
+FPDFDoc_GetAttachment(FPDF_DOCUMENT document, int index) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc || index < 0)
+ return nullptr;
+
+ CPDF_NameTree nameTree(pDoc, "EmbeddedFiles");
+ if (static_cast<size_t>(index) >= nameTree.GetCount())
+ return nullptr;
+
+ WideString csName;
+ return nameTree.LookupValueAndName(index, &csName);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFDoc_DeleteAttachment(FPDF_DOCUMENT document, int index) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc || index < 0)
+ return false;
+
+ CPDF_NameTree nameTree(pDoc, "EmbeddedFiles");
+ if (static_cast<size_t>(index) >= nameTree.GetCount())
+ return false;
+
+ return nameTree.DeleteValueAndName(index);
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFAttachment_GetName(FPDF_ATTACHMENT attachment,
+ void* buffer,
+ unsigned long buflen) {
+ CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
+ if (!pFile)
+ return 0;
+
+ return Utf16EncodeMaybeCopyAndReturnLength(CPDF_FileSpec(pFile).GetFileName(),
+ buffer, buflen);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAttachment_HasKey(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key) {
+ CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
+ if (!pFile)
+ return 0;
+
+ CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict();
+ return pParamsDict ? pParamsDict->KeyExist(key) : 0;
+}
+
+FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV
+FPDFAttachment_GetValueType(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key) {
+ if (!FPDFAttachment_HasKey(attachment, key))
+ return FPDF_OBJECT_UNKNOWN;
+
+ CPDF_FileSpec spec(CPDFObjectFromFPDFAttachment(attachment));
+ CPDF_Object* pObj = spec.GetParamsDict()->GetObjectFor(key);
+ return pObj ? pObj->GetType() : FPDF_OBJECT_UNKNOWN;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAttachment_SetStringValue(FPDF_ATTACHMENT attachment,
+ FPDF_BYTESTRING key,
+ FPDF_WIDESTRING value) {
+ CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
+ if (!pFile)
+ return false;
+
+ CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict();
+ if (!pParamsDict)
+ return false;
+
+ ByteString bsKey = key;
+ ByteString bsValue = CFXByteStringFromFPDFWideString(value);
+ bool bEncodedAsHex = bsKey == kChecksumKey;
+ if (bEncodedAsHex)
+ bsValue = CFXByteStringHexDecode(bsValue);
+
+ pParamsDict->SetNewFor<CPDF_String>(bsKey, bsValue, bEncodedAsHex);
+ return true;
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFAttachment_GetStringValue(FPDF_ATTACHMENT attachment,
+ FPDF_BYTESTRING key,
+ void* buffer,
+ unsigned long buflen) {
+ CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
+ if (!pFile)
+ return 0;
+
+ CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict();
+ if (!pParamsDict)
+ return 0;
+
+ ByteString bsKey = key;
+ WideString value = pParamsDict->GetUnicodeTextFor(bsKey);
+ if (bsKey == kChecksumKey && !value.IsEmpty()) {
+ CPDF_String* stringValue = pParamsDict->GetObjectFor(bsKey)->AsString();
+ if (stringValue->IsHex()) {
+ ByteString encoded = PDF_EncodeString(stringValue->GetString(), true);
+ value = CPDF_String(nullptr, encoded, false).GetUnicodeText();
+ }
+ }
+
+ return Utf16EncodeMaybeCopyAndReturnLength(value, buffer, buflen);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAttachment_SetFile(FPDF_ATTACHMENT attachment,
+ FPDF_DOCUMENT document,
+ const void* contents,
+ const unsigned long len) {
+ CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pFile || !pFile->IsDictionary() || !pDoc || len > INT_MAX)
+ return false;
+
+ // An empty content must have a zero length.
+ if (!contents && len != 0)
+ return false;
+
+ // Create a dictionary for the new embedded file stream.
+ auto pFileStreamDict = pdfium::MakeUnique<CPDF_Dictionary>();
+ CPDF_Dictionary* pParamsDict =
+ pFileStreamDict->SetNewFor<CPDF_Dictionary>("Params");
+
+ // Set the size of the new file in the dictionary.
+ pFileStreamDict->SetNewFor<CPDF_Number>("DL", static_cast<int>(len));
+ pParamsDict->SetNewFor<CPDF_Number>("Size", static_cast<int>(len));
+
+ // Set the creation date of the new attachment in the dictionary.
+ CFX_DateTime dateTime = CFX_DateTime::Now();
+ pParamsDict->SetNewFor<CPDF_String>(
+ "CreationDate",
+ ByteString::Format("D:%d%02d%02d%02d%02d%02d", dateTime.GetYear(),
+ dateTime.GetMonth(), dateTime.GetDay(),
+ dateTime.GetHour(), dateTime.GetMinute(),
+ dateTime.GetSecond()),
+ false);
+
+ // Set the checksum of the new attachment in the dictionary.
+ pParamsDict->SetNewFor<CPDF_String>(
+ kChecksumKey, CFXByteStringHexDecode(GenerateMD5Base16(contents, len)),
+ true);
+
+ // Create the file stream and have the filespec dictionary link to it.
+ std::unique_ptr<uint8_t, FxFreeDeleter> stream(FX_Alloc(uint8_t, len));
+ memcpy(stream.get(), contents, len);
+ CPDF_Stream* pFileStream = pDoc->NewIndirect<CPDF_Stream>(
+ std::move(stream), len, std::move(pFileStreamDict));
+ CPDF_Dictionary* pEFDict =
+ pFile->AsDictionary()->SetNewFor<CPDF_Dictionary>("EF");
+ pEFDict->SetNewFor<CPDF_Reference>("F", pDoc, pFileStream->GetObjNum());
+ return true;
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFAttachment_GetFile(FPDF_ATTACHMENT attachment,
+ void* buffer,
+ unsigned long buflen) {
+ CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
+ if (!pFile)
+ return 0;
+
+ CPDF_Stream* pFileStream = CPDF_FileSpec(pFile).GetFileStream();
+ if (!pFileStream)
+ return 0;
+
+ return DecodeStreamMaybeCopyAndReturnLength(pFileStream, buffer, buflen);
+}
diff --git a/fpdfsdk/fpdfattachment_embeddertest.cpp b/fpdfsdk/fpdfattachment_embeddertest.cpp
new file mode 100644
index 0000000..dd9b5ae
--- /dev/null
+++ b/fpdfsdk/fpdfattachment_embeddertest.cpp
@@ -0,0 +1,260 @@
+// 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.
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "public/fpdf_attachment.h"
+#include "public/fpdfview.h"
+#include "testing/embedder_test.h"
+
+static constexpr char kDateKey[] = "CreationDate";
+static constexpr char kChecksumKey[] = "CheckSum";
+
+class FPDFAttachmentEmbeddertest : public EmbedderTest {};
+
+TEST_F(FPDFAttachmentEmbeddertest, ExtractAttachments) {
+ // Open a file with two attachments.
+ ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
+ EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
+
+ // Retrieve the first attachment.
+ FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
+ ASSERT_TRUE(attachment);
+
+ // Check that the name of the first attachment is correct.
+ unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
+ std::vector<char> buf(len);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
+ EXPECT_STREQ(L"1.txt",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+
+ // Check that the content of the first attachment is correct.
+ len = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ ASSERT_EQ(4u, FPDFAttachment_GetFile(attachment, buf.data(), len));
+ EXPECT_EQ(std::string("test"), std::string(buf.data(), 4));
+
+ // Check that a non-existent key does not exist.
+ EXPECT_FALSE(FPDFAttachment_HasKey(attachment, "none"));
+
+ // Check that the string value of a non-string dictionary entry is empty.
+ static constexpr char kSizeKey[] = "Size";
+ EXPECT_EQ(FPDF_OBJECT_NUMBER,
+ FPDFAttachment_GetValueType(attachment, kSizeKey));
+ EXPECT_EQ(2u,
+ FPDFAttachment_GetStringValue(attachment, kSizeKey, nullptr, 0));
+
+ // Check that the creation date of the first attachment is correct.
+ len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
+ len));
+ EXPECT_STREQ(L"D:20170712214438-07'00'",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+
+ // Retrieve the second attachment.
+ attachment = FPDFDoc_GetAttachment(document(), 1);
+ ASSERT_TRUE(attachment);
+
+ // Retrieve the second attachment file.
+ len = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(5869u, FPDFAttachment_GetFile(attachment, buf.data(), len));
+
+ // Check that the calculated checksum of the file data matches expectation.
+ const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18";
+ const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>";
+ const std::string generated_checksum =
+ GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len);
+ EXPECT_EQ(kCheckSum, generated_checksum);
+
+ // Check that the stored checksum matches expectation.
+ len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
+ buf.data(), len));
+ EXPECT_EQ(kCheckSumW,
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
+}
+
+TEST_F(FPDFAttachmentEmbeddertest, AddAttachments) {
+ // Open a file with two attachments.
+ ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
+ EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
+
+ // Check that adding an attachment with an empty name would fail.
+ EXPECT_FALSE(FPDFDoc_AddAttachment(document(), nullptr));
+
+ // Add an attachment to the beginning of the embedded file list.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> file_name =
+ GetFPDFWideString(L"0.txt");
+ FPDF_ATTACHMENT attachment =
+ FPDFDoc_AddAttachment(document(), file_name.get());
+
+ // Check that writing to a file with nullptr but non-zero bytes would fail.
+ EXPECT_FALSE(FPDFAttachment_SetFile(attachment, document(), nullptr, 10));
+
+ // Set the new attachment's file.
+ constexpr char kContents1[] = "Hello!";
+ EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents1,
+ strlen(kContents1)));
+
+ // Verify the name of the new attachment (i.e. the first attachment).
+ attachment = FPDFDoc_GetAttachment(document(), 0);
+ ASSERT_TRUE(attachment);
+ unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
+ std::vector<char> buf(len);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
+ EXPECT_STREQ(L"0.txt",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+
+ // Verify the content of the new attachment (i.e. the first attachment).
+ len = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len));
+ EXPECT_EQ(std::string(kContents1), std::string(buf.data(), 6));
+
+ // Add an attachment to the end of the embedded file list and set its file.
+ file_name = GetFPDFWideString(L"z.txt");
+ attachment = FPDFDoc_AddAttachment(document(), file_name.get());
+ constexpr char kContents2[] = "World!";
+ EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2,
+ strlen(kContents2)));
+ EXPECT_EQ(4, FPDFDoc_GetAttachmentCount(document()));
+
+ // Verify the name of the new attachment (i.e. the fourth attachment).
+ attachment = FPDFDoc_GetAttachment(document(), 3);
+ ASSERT_TRUE(attachment);
+ len = FPDFAttachment_GetName(attachment, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
+ EXPECT_STREQ(L"z.txt",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+
+ // Verify the content of the new attachment (i.e. the fourth attachment).
+ len = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len));
+ EXPECT_EQ(std::string(kContents2), std::string(buf.data(), 6));
+}
+
+TEST_F(FPDFAttachmentEmbeddertest, AddAttachmentsWithParams) {
+ // Open a file with two attachments.
+ ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
+ EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
+
+ // Add an attachment to the embedded file list.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> file_name =
+ GetFPDFWideString(L"5.txt");
+ FPDF_ATTACHMENT attachment =
+ FPDFDoc_AddAttachment(document(), file_name.get());
+ constexpr char kContents[] = "Hello World!";
+ EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents,
+ strlen(kContents)));
+
+ // Set the date to be an arbitrary value.
+ constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'";
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> ws_date =
+ GetFPDFWideString(kDateW);
+ EXPECT_TRUE(
+ FPDFAttachment_SetStringValue(attachment, kDateKey, ws_date.get()));
+
+ // Set the checksum to be an arbitrary value.
+ constexpr wchar_t kCheckSumW[] = L"<ABCDEF01234567899876543210FEDCBA>";
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> ws_checksum =
+ GetFPDFWideString(kCheckSumW);
+ EXPECT_TRUE(FPDFAttachment_SetStringValue(attachment, kChecksumKey,
+ ws_checksum.get()));
+
+ // Verify the name of the new attachment (i.e. the second attachment).
+ attachment = FPDFDoc_GetAttachment(document(), 1);
+ ASSERT_TRUE(attachment);
+ unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
+ std::vector<char> buf(len);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
+ EXPECT_STREQ(L"5.txt",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+
+ // Verify the content of the new attachment.
+ len = FPDFAttachment_GetFile(attachment, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, buf.data(), len));
+ EXPECT_EQ(std::string(kContents), std::string(buf.data(), 12));
+
+ // Verify the creation date of the new attachment.
+ len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
+ len));
+ EXPECT_STREQ(kDateW,
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+
+ // Verify the checksum of the new attachment.
+ len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
+ buf.data(), len));
+ EXPECT_STREQ(kCheckSumW,
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+
+ // Overwrite the existing file with empty content, and check that the checksum
+ // gets updated to the correct value.
+ EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0));
+ EXPECT_EQ(0u, FPDFAttachment_GetFile(attachment, nullptr, 0));
+ len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
+ buf.data(), len));
+ EXPECT_EQ(L"<D41D8CD98F00B204E9800998ECF8427E>",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
+}
+
+TEST_F(FPDFAttachmentEmbeddertest, DeleteAttachment) {
+ // Open a file with two attachments.
+ ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
+ EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
+
+ // Verify the name of the first attachment.
+ FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
+ unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
+ std::vector<char> buf(len);
+ EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
+ EXPECT_STREQ(L"1.txt",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+
+ // Delete the first attachment.
+ EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0));
+ EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
+
+ // Verify the name of the new first attachment.
+ attachment = FPDFDoc_GetAttachment(document(), 0);
+ len = FPDFAttachment_GetName(attachment, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), len));
+ EXPECT_STREQ(L"attached.pdf",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+ .c_str());
+}
diff --git a/fpdfsdk/fpdfcatalog.cpp b/fpdfsdk/fpdfcatalog.cpp
new file mode 100644
index 0000000..493e5ae
--- /dev/null
+++ b/fpdfsdk/fpdfcatalog.cpp
@@ -0,0 +1,22 @@
+// 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.
+
+#include "public/fpdf_catalog.h"
+
+#include "core/fpdfapi/parser/cpdf_document.h"
+#include "fpdfsdk/fsdk_define.h"
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFCatalog_IsTagged(FPDF_DOCUMENT document) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc)
+ return false;
+
+ const CPDF_Dictionary* pCatalog = pDoc->GetRoot();
+ if (!pCatalog)
+ return false;
+
+ const CPDF_Dictionary* pMarkInfo = pCatalog->GetDictFor("MarkInfo");
+ return pMarkInfo && pMarkInfo->GetIntegerFor("Marked") != 0;
+}
diff --git a/fpdfsdk/fpdfcatalog_unittest.cpp b/fpdfsdk/fpdfcatalog_unittest.cpp
new file mode 100644
index 0000000..13c0634
--- /dev/null
+++ b/fpdfsdk/fpdfcatalog_unittest.cpp
@@ -0,0 +1,95 @@
+// 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.
+
+#include "public/fpdf_catalog.h"
+
+#include "core/fpdfapi/cpdf_modulemgr.h"
+#include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fpdfapi/parser/cpdf_number.h"
+#include "core/fpdfapi/parser/cpdf_parser.h"
+#include "core/fpdfapi/parser/cpdf_string.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/test_support.h"
+
+#ifdef PDF_ENABLE_XFA
+#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
+#endif // PDF_ENABLE_XFA
+
+class CPDF_TestDocument : public CPDF_Document {
+ public:
+ CPDF_TestDocument() : CPDF_Document(nullptr) {}
+
+ void SetRoot(CPDF_Dictionary* root) {
+ m_pRootDict = root;
+ GetRoot();
+ }
+};
+
+#ifdef PDF_ENABLE_XFA
+class CPDF_TestXFAContext : public CPDFXFA_Context {
+ public:
+ CPDF_TestXFAContext()
+ : CPDFXFA_Context(pdfium::MakeUnique<CPDF_TestDocument>()) {}
+
+ void SetRoot(CPDF_Dictionary* root) {
+ reinterpret_cast<CPDF_TestDocument*>(GetPDFDoc())->SetRoot(root);
+ }
+
+ CPDF_IndirectObjectHolder* GetHolder() { return GetPDFDoc(); }
+};
+using CPDF_TestPdfDocument = CPDF_TestXFAContext;
+#else // PDF_ENABLE_XFA
+using CPDF_TestPdfDocument = CPDF_TestDocument;
+#endif // PDF_ENABLE_XFA
+
+class PDFCatalogTest : public testing::Test {
+ public:
+ void SetUp() override {
+ CPDF_ModuleMgr::Get()->Init();
+
+ m_pDoc = pdfium::MakeUnique<CPDF_TestPdfDocument>();
+
+ // Setup the root directory.
+ m_pRootObj = pdfium::MakeUnique<CPDF_Dictionary>();
+ }
+
+ void TearDown() override {
+ m_pDoc.reset();
+ CPDF_ModuleMgr::Destroy();
+ }
+
+ protected:
+ std::unique_ptr<CPDF_TestPdfDocument> m_pDoc;
+ std::unique_ptr<CPDF_Dictionary> m_pRootObj;
+};
+
+TEST_F(PDFCatalogTest, IsTagged) {
+ // Null doc
+ EXPECT_FALSE(FPDFCatalog_IsTagged(nullptr));
+
+ // No root
+ m_pDoc->SetRoot(nullptr);
+ EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get()));
+
+ // Empty root
+ m_pDoc->SetRoot(m_pRootObj.get());
+ EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get()));
+
+ // Root with other key
+ m_pRootObj->SetNewFor<CPDF_String>("OTHER_KEY", "other value", false);
+ EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get()));
+
+ // Root with empty MarkInfo
+ CPDF_Dictionary* markInfoDict =
+ m_pRootObj->SetNewFor<CPDF_Dictionary>("MarkInfo");
+ EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get()));
+
+ // MarkInfo present but Marked is 0
+ markInfoDict->SetNewFor<CPDF_Number>("Marked", 0);
+ EXPECT_FALSE(FPDFCatalog_IsTagged(m_pDoc.get()));
+
+ // MarkInfo present and Marked is 1, PDF is considered tagged.
+ markInfoDict->SetNewFor<CPDF_Number>("Marked", 1);
+ EXPECT_TRUE(FPDFCatalog_IsTagged(m_pDoc.get()));
+}
diff --git a/fpdfsdk/fpdfdoc.cpp b/fpdfsdk/fpdfdoc.cpp
index f7d94c2..47ecf42 100644
--- a/fpdfsdk/fpdfdoc.cpp
+++ b/fpdfsdk/fpdfdoc.cpp
@@ -24,7 +24,7 @@
CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree,
CPDF_Bookmark bookmark,
- const CFX_WideString& title,
+ const WideString& title,
std::set<CPDF_Dictionary*>* visited) {
// Return if already checked to avoid circular calling.
if (pdfium::ContainsKey(*visited, bookmark.GetDict()))
@@ -53,26 +53,16 @@
if (!page)
return nullptr;
- CPDF_Document* pDoc = page->m_pDocument;
+ CPDF_Document* pDoc = page->m_pDocument.Get();
std::unique_ptr<CPDF_LinkList>* pHolder = pDoc->LinksContext();
if (!pHolder->get())
*pHolder = pdfium::MakeUnique<CPDF_LinkList>();
return pHolder->get();
}
-unsigned long Utf16EncodeMaybeCopyAndReturnLength(const CFX_WideString& text,
- void* buffer,
- unsigned long buflen) {
- CFX_ByteString encodedText = text.UTF16LE_Encode();
- unsigned long len = encodedText.GetLength();
- if (buffer && len <= buflen)
- FXSYS_memcpy(buffer, encodedText.c_str(), len);
- return len;
-}
-
} // namespace
-DLLEXPORT FPDF_BOOKMARK STDCALL
+FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
@@ -83,7 +73,7 @@
return tree.GetFirstChild(bookmark).GetDict();
}
-DLLEXPORT FPDF_BOOKMARK STDCALL
+FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict) {
if (!pDict)
return nullptr;
@@ -96,32 +86,31 @@
return tree.GetNextSibling(bookmark).GetDict();
}
-DLLEXPORT unsigned long STDCALL FPDFBookmark_GetTitle(FPDF_BOOKMARK pDict,
- void* buffer,
- unsigned long buflen) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFBookmark_GetTitle(FPDF_BOOKMARK pDict, void* buffer, unsigned long buflen) {
if (!pDict)
return 0;
CPDF_Bookmark bookmark(ToDictionary(static_cast<CPDF_Object*>(pDict)));
- CFX_WideString title = bookmark.GetTitle();
+ WideString title = bookmark.GetTitle();
return Utf16EncodeMaybeCopyAndReturnLength(title, buffer, buflen);
}
-DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document,
- FPDF_WIDESTRING title) {
+FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
+FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title) {
if (!title || title[0] == 0)
return nullptr;
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
return nullptr;
CPDF_BookmarkTree tree(pDoc);
- FX_STRSIZE len = CFX_WideString::WStringLength(title);
- CFX_WideString encodedTitle = CFX_WideString::FromUTF16LE(title, len);
+ size_t len = WideString::WStringLength(title);
+ WideString encodedTitle = WideString::FromUTF16LE(title, len);
std::set<CPDF_Dictionary*> visited;
return FindBookmark(tree, CPDF_Bookmark(), encodedTitle, &visited).GetDict();
}
-DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document,
- FPDF_BOOKMARK pDict) {
+FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFBookmark_GetDest(FPDF_DOCUMENT document,
+ FPDF_BOOKMARK pDict) {
if (!pDict)
return nullptr;
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
@@ -139,14 +128,15 @@
return action.GetDest(pDoc).GetObject();
}
-DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK pDict) {
+FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV
+FPDFBookmark_GetAction(FPDF_BOOKMARK pDict) {
if (!pDict)
return nullptr;
CPDF_Bookmark bookmark(ToDictionary(static_cast<CPDF_Object*>(pDict)));
return bookmark.GetAction().GetDict();
}
-DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION pDict) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAction_GetType(FPDF_ACTION pDict) {
if (!pDict)
return PDFACTION_UNSUPPORTED;
@@ -166,8 +156,8 @@
}
}
-DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document,
- FPDF_ACTION pDict) {
+FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFAction_GetDest(FPDF_DOCUMENT document,
+ FPDF_ACTION pDict) {
if (!pDict)
return nullptr;
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
@@ -177,40 +167,40 @@
return action.GetDest(pDoc).GetObject();
}
-DLLEXPORT unsigned long STDCALL FPDFAction_GetFilePath(FPDF_ACTION pDict,
- void* buffer,
- unsigned long buflen) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFAction_GetFilePath(FPDF_ACTION pDict, void* buffer, unsigned long buflen) {
unsigned long type = FPDFAction_GetType(pDict);
if (type != PDFACTION_REMOTEGOTO && type != PDFACTION_LAUNCH)
return 0;
CPDF_Action action(ToDictionary(static_cast<CPDF_Object*>(pDict)));
- CFX_ByteString path = action.GetFilePath().UTF8Encode();
+ ByteString path = action.GetFilePath().UTF8Encode();
unsigned long len = path.GetLength() + 1;
if (buffer && len <= buflen)
- FXSYS_memcpy(buffer, path.c_str(), len);
+ memcpy(buffer, path.c_str(), len);
return len;
}
-DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document,
- FPDF_ACTION pDict,
- void* buffer,
- unsigned long buflen) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFAction_GetURIPath(FPDF_DOCUMENT document,
+ FPDF_ACTION pDict,
+ void* buffer,
+ unsigned long buflen) {
if (!pDict)
return 0;
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
return 0;
CPDF_Action action(ToDictionary(static_cast<CPDF_Object*>(pDict)));
- CFX_ByteString path = action.GetURI(pDoc);
+ ByteString path = action.GetURI(pDoc);
unsigned long len = path.GetLength() + 1;
if (buffer && len <= buflen)
- FXSYS_memcpy(buffer, path.c_str(), len);
+ memcpy(buffer, path.c_str(), len);
return len;
}
-DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document,
- FPDF_DEST pDict) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST pDict) {
if (!pDict)
return 0;
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
@@ -220,18 +210,36 @@
return dest.GetPageIndex(pDoc);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFDest_GetLocationInPage(FPDF_DEST pDict,
- FPDF_BOOL* hasXVal,
- FPDF_BOOL* hasYVal,
- FPDF_BOOL* hasZoomVal,
- FS_FLOAT* x,
- FS_FLOAT* y,
- FS_FLOAT* zoom) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFDest_GetView(FPDF_DEST pDict,
+ unsigned long* pNumParams,
+ FS_FLOAT* pParams) {
+ if (!pDict) {
+ *pNumParams = 0;
+ return 0;
+ }
+
+ CPDF_Dest dest(static_cast<CPDF_Array*>(pDict));
+ unsigned long nParams = dest.GetNumParams();
+ ASSERT(nParams <= 4);
+ *pNumParams = nParams;
+ for (unsigned long i = 0; i < nParams; ++i)
+ pParams[i] = dest.GetParam(i);
+ return dest.GetZoomMode();
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFDest_GetLocationInPage(FPDF_DEST pDict,
+ FPDF_BOOL* hasXVal,
+ FPDF_BOOL* hasYVal,
+ FPDF_BOOL* hasZoomVal,
+ FS_FLOAT* x,
+ FS_FLOAT* y,
+ FS_FLOAT* zoom) {
if (!pDict)
return false;
- std::unique_ptr<CPDF_Dest> dest(
- new CPDF_Dest(static_cast<CPDF_Object*>(pDict)));
+ auto dest = pdfium::MakeUnique<CPDF_Dest>(static_cast<CPDF_Object*>(pDict));
// FPDF_BOOL is an int, GetXYZ expects bools.
bool bHasX;
@@ -246,9 +254,9 @@
return true;
}
-DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page,
- double x,
- double y) {
+FPDF_EXPORT FPDF_LINK FPDF_CALLCONV FPDFLink_GetLinkAtPoint(FPDF_PAGE page,
+ double x,
+ double y) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return nullptr;
@@ -258,15 +266,15 @@
return nullptr;
return pLinkList
- ->GetLinkAtPoint(
- pPage, CFX_PointF(static_cast<FX_FLOAT>(x), static_cast<FX_FLOAT>(y)),
- nullptr)
+ ->GetLinkAtPoint(pPage,
+ CFX_PointF(static_cast<float>(x), static_cast<float>(y)),
+ nullptr)
.GetDict();
}
-DLLEXPORT int STDCALL FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page,
- double x,
- double y) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page,
+ double x,
+ double y) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return -1;
@@ -277,13 +285,13 @@
int z_order = -1;
pLinkList->GetLinkAtPoint(
- pPage, CFX_PointF(static_cast<FX_FLOAT>(x), static_cast<FX_FLOAT>(y)),
+ pPage, CFX_PointF(static_cast<float>(x), static_cast<float>(y)),
&z_order);
return z_order;
}
-DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document,
- FPDF_LINK pDict) {
+FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFLink_GetDest(FPDF_DOCUMENT document,
+ FPDF_LINK pDict) {
if (!pDict)
return nullptr;
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
@@ -300,7 +308,7 @@
return action.GetDest(pDoc).GetObject();
}
-DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK pDict) {
+FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV FPDFLink_GetAction(FPDF_LINK pDict) {
if (!pDict)
return nullptr;
@@ -308,9 +316,9 @@
return link.GetAction().GetDict();
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page,
- int* startPos,
- FPDF_LINK* linkAnnot) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_Enumerate(FPDF_PAGE page,
+ int* startPos,
+ FPDF_LINK* linkAnnot) {
if (!startPos || !linkAnnot)
return false;
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
@@ -333,21 +341,17 @@
return false;
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot,
- FS_RECTF* rect) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot,
+ FS_RECTF* rect) {
if (!linkAnnot || !rect)
return false;
CPDF_Dictionary* pAnnotDict =
ToDictionary(static_cast<CPDF_Object*>(linkAnnot));
- CFX_FloatRect rt = pAnnotDict->GetRectFor("Rect");
- rect->left = rt.left;
- rect->bottom = rt.bottom;
- rect->right = rt.right;
- rect->top = rt.top;
+ FSRECTFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"), rect);
return true;
}
-DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot) {
if (!linkAnnot)
return 0;
CPDF_Dictionary* pAnnotDict =
@@ -358,9 +362,10 @@
return static_cast<int>(pArray->GetCount() / 8);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot,
- int quadIndex,
- FS_QUADPOINTSF* quadPoints) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot,
+ int quadIndex,
+ FS_QUADPOINTSF* quadPoints) {
if (!linkAnnot || !quadPoints)
return false;
CPDF_Dictionary* pAnnotDict =
@@ -386,33 +391,35 @@
return true;
}
-DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT document,
- FPDF_BYTESTRING tag,
- void* buffer,
- unsigned long buflen) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetMetaText(FPDF_DOCUMENT document,
+ FPDF_BYTESTRING tag,
+ void* buffer,
+ unsigned long buflen) {
if (!tag)
return 0;
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
return 0;
- CPDF_Dictionary* pInfo = pDoc->GetInfo();
+ pDoc->LoadDocumentInfo();
+ const CPDF_Dictionary* pInfo = pDoc->GetInfo();
if (!pInfo)
return 0;
- CFX_WideString text = pInfo->GetUnicodeTextFor(tag);
+ WideString text = pInfo->GetUnicodeTextFor(tag);
return Utf16EncodeMaybeCopyAndReturnLength(text, buffer, buflen);
}
-DLLEXPORT unsigned long STDCALL FPDF_GetPageLabel(FPDF_DOCUMENT document,
- int page_index,
- void* buffer,
- unsigned long buflen) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDF_GetPageLabel(FPDF_DOCUMENT document,
+ int page_index,
+ void* buffer,
+ unsigned long buflen) {
if (page_index < 0)
return 0;
// CPDF_PageLabel can deal with NULL |document|.
CPDF_PageLabel label(CPDFDocumentFromFPDFDocument(document));
- CFX_WideString str;
- if (!label.GetLabel(page_index, &str))
- return 0;
- return Utf16EncodeMaybeCopyAndReturnLength(str, buffer, buflen);
+ Optional<WideString> str = label.GetLabel(page_index);
+ return str.has_value()
+ ? Utf16EncodeMaybeCopyAndReturnLength(str.value(), buffer, buflen)
+ : 0;
}
diff --git a/fpdfsdk/fpdfdoc_embeddertest.cpp b/fpdfsdk/fpdfdoc_embeddertest.cpp
index 3666687..d346330 100644
--- a/fpdfsdk/fpdfdoc_embeddertest.cpp
+++ b/fpdfsdk/fpdfdoc_embeddertest.cpp
@@ -10,7 +10,6 @@
#include "public/fpdf_edit.h"
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
-#include "testing/fx_string_testhelpers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
@@ -43,6 +42,65 @@
EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), dest));
}
+TEST_F(FPDFDocEmbeddertest, DestGetView) {
+ EXPECT_TRUE(OpenDocument("named_dests.pdf"));
+
+ unsigned long numParams;
+ FS_FLOAT params[4];
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_UNKNOWN_MODE),
+ FPDFDest_GetView(nullptr, &numParams, params));
+ EXPECT_EQ(0U, numParams);
+ EXPECT_FLOAT_EQ(42.4242f, params[0]);
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
+ EXPECT_TRUE(dest);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
+ FPDFDest_GetView(dest, &numParams, params));
+ EXPECT_EQ(3U, numParams);
+ EXPECT_FLOAT_EQ(0, params[0]);
+ EXPECT_FLOAT_EQ(0, params[1]);
+ EXPECT_FLOAT_EQ(1, params[2]);
+ EXPECT_FLOAT_EQ(42.4242f, params[3]);
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ dest = FPDF_GetNamedDestByName(document(), "Next");
+ EXPECT_TRUE(dest);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_FIT),
+ FPDFDest_GetView(dest, &numParams, params));
+ EXPECT_EQ(0U, numParams);
+ EXPECT_FLOAT_EQ(42.4242f, params[0]);
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
+ EXPECT_TRUE(dest);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
+ FPDFDest_GetView(dest, &numParams, params));
+ EXPECT_EQ(3U, numParams);
+ EXPECT_FLOAT_EQ(200, params[0]);
+ EXPECT_FLOAT_EQ(400, params[1]);
+ EXPECT_FLOAT_EQ(800, params[2]);
+ EXPECT_FLOAT_EQ(42.4242f, params[3]);
+
+ numParams = 42;
+ std::fill_n(params, 4, 42.4242f);
+ dest = FPDF_GetNamedDestByName(document(), "LastAlternate");
+ EXPECT_TRUE(dest);
+ EXPECT_EQ(static_cast<unsigned long>(PDFDEST_VIEW_XYZ),
+ FPDFDest_GetView(dest, &numParams, params));
+ EXPECT_EQ(3U, numParams);
+ EXPECT_FLOAT_EQ(0, params[0]);
+ EXPECT_FLOAT_EQ(0, params[1]);
+ EXPECT_FLOAT_EQ(-200, params[2]);
+ EXPECT_FLOAT_EQ(42.4242f, params[3]);
+}
+
TEST_F(FPDFDocEmbeddertest, DestGetLocationInPage) {
EXPECT_TRUE(OpenDocument("named_dests.pdf"));
@@ -126,16 +184,14 @@
FPDF_BOOKMARK child = FPDFBookmark_GetFirstChild(document(), nullptr);
EXPECT_TRUE(child);
EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(L"A Good Beginning"),
- CFX_WideString::FromUTF16LE(buf, 16));
+ EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16));
EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), child));
FPDF_BOOKMARK sibling = FPDFBookmark_GetNextSibling(document(), child);
EXPECT_TRUE(sibling);
EXPECT_EQ(28u, FPDFBookmark_GetTitle(sibling, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(L"A Good Ending"),
- CFX_WideString::FromUTF16LE(buf, 13));
+ EXPECT_EQ(WideString(L"A Good Ending"), WideString::FromUTF16LE(buf, 13));
EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(document(), sibling));
}
@@ -153,8 +209,7 @@
// Check that the string matches.
unsigned short buf[128];
EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(L"A Good Beginning"),
- CFX_WideString::FromUTF16LE(buf, 16));
+ EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16));
// Check that it is them same as the one returned by GetFirstChild.
EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr));
@@ -183,6 +238,71 @@
EXPECT_EQ(0, FPDF_GetPageCount(document()));
}
+TEST_F(FPDFDocEmbeddertest, GetMetaText) {
+ ASSERT_TRUE(OpenDocument("bug_601362.pdf"));
+
+ // Invalid document / tag results in 0.
+ unsigned short buf[128];
+ EXPECT_EQ(0u, FPDF_GetMetaText(document(), nullptr, buf, sizeof(buf)));
+ EXPECT_EQ(0u, FPDF_GetMetaText(nullptr, "", buf, sizeof(buf)));
+
+ // Tags that do not eixst results in an empty wide string.
+ EXPECT_EQ(2u, FPDF_GetMetaText(document(), "", buf, sizeof(buf)));
+ EXPECT_EQ(2u, FPDF_GetMetaText(document(), "foo", buf, sizeof(buf)));
+ ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Title", buf, sizeof(buf)));
+ ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Author", buf, sizeof(buf)));
+ ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Subject", buf, sizeof(buf)));
+ ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Keywords", buf, sizeof(buf)));
+ ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Producer", buf, sizeof(buf)));
+
+ constexpr wchar_t kExpectedCreator[] = L"Microsoft Word";
+ ASSERT_EQ(30u, FPDF_GetMetaText(document(), "Creator", buf, sizeof(buf)));
+ EXPECT_EQ(WideString(kExpectedCreator),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedCreator)));
+
+ constexpr wchar_t kExpectedCreationDate[] = L"D:20160411190039+00'00'";
+ ASSERT_EQ(48u,
+ FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf)));
+ EXPECT_EQ(WideString(kExpectedCreationDate),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedCreationDate)));
+
+ constexpr wchar_t kExpectedModDate[] = L"D:20160411190039+00'00'";
+ ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
+ EXPECT_EQ(WideString(kExpectedModDate),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
+}
+
+TEST_F(FPDFDocEmbeddertest, GetMetaTextSameObjectNumber) {
+ ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
+
+ // The PDF has been edited. It has two %%EOF markers, and 2 objects numbered
+ // (1 0). Both objects are /Info dictionaries, but contain different data.
+ // Make sure ModDate is the date of the last modification.
+ unsigned short buf[128];
+ constexpr wchar_t kExpectedModDate[] = L"D:20170612232940-04'00'";
+ ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
+ EXPECT_EQ(WideString(kExpectedModDate),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
+}
+
+TEST_F(FPDFDocEmbeddertest, GetMetaTextInAttachmentFile) {
+ ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
+
+ // Make sure this is the date from the PDF itself and not the attached PDF.
+ unsigned short buf[128];
+ constexpr wchar_t kExpectedModDate[] = L"D:20170712214448-07'00'";
+ ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
+ EXPECT_EQ(WideString(kExpectedModDate),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
+}
+
+TEST_F(FPDFDocEmbeddertest, GetMetaTextFromNewDocument) {
+ FPDF_DOCUMENT empty_doc = FPDF_CreateNewDocument();
+ unsigned short buf[128];
+ EXPECT_EQ(2u, FPDF_GetMetaText(empty_doc, "Title", buf, sizeof(buf)));
+ FPDF_CloseDocument(empty_doc);
+}
+
TEST_F(FPDFDocEmbeddertest, NoPageLabels) {
EXPECT_TRUE(OpenDocument("about_blank.pdf"));
EXPECT_EQ(1, FPDF_GetPageCount(document()));
@@ -194,44 +314,48 @@
EXPECT_TRUE(OpenDocument("page_labels.pdf"));
EXPECT_EQ(7, FPDF_GetPageCount(document()));
+ // We do not request labels, when use FPDFAvail_IsXXXAvail.
+ // Flush all data, to allow read labels.
+ SetWholeFileAvailable();
+
unsigned short buf[128];
EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -2, buf, sizeof(buf)));
EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -1, buf, sizeof(buf)));
- const FX_WCHAR kExpectedPageLabel0[] = L"i";
+ const wchar_t kExpectedPageLabel0[] = L"i";
ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 0, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(kExpectedPageLabel0),
- CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel0)));
+ EXPECT_EQ(WideString(kExpectedPageLabel0),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel0)));
- const FX_WCHAR kExpectedPageLabel1[] = L"ii";
+ const wchar_t kExpectedPageLabel1[] = L"ii";
ASSERT_EQ(6u, FPDF_GetPageLabel(document(), 1, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(kExpectedPageLabel1),
- CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel1)));
+ EXPECT_EQ(WideString(kExpectedPageLabel1),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel1)));
- const FX_WCHAR kExpectedPageLabel2[] = L"1";
+ const wchar_t kExpectedPageLabel2[] = L"1";
ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 2, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(kExpectedPageLabel2),
- CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel2)));
+ EXPECT_EQ(WideString(kExpectedPageLabel2),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel2)));
- const FX_WCHAR kExpectedPageLabel3[] = L"2";
+ const wchar_t kExpectedPageLabel3[] = L"2";
ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 3, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(kExpectedPageLabel3),
- CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel3)));
+ EXPECT_EQ(WideString(kExpectedPageLabel3),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel3)));
- const FX_WCHAR kExpectedPageLabel4[] = L"zzA";
+ const wchar_t kExpectedPageLabel4[] = L"zzA";
ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 4, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(kExpectedPageLabel4),
- CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel4)));
+ EXPECT_EQ(WideString(kExpectedPageLabel4),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel4)));
- const FX_WCHAR kExpectedPageLabel5[] = L"zzB";
+ const wchar_t kExpectedPageLabel5[] = L"zzB";
ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 5, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(kExpectedPageLabel5),
- CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel5)));
+ EXPECT_EQ(WideString(kExpectedPageLabel5),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel5)));
- const FX_WCHAR kExpectedPageLabel6[] = L"";
+ const wchar_t kExpectedPageLabel6[] = L"";
ASSERT_EQ(2u, FPDF_GetPageLabel(document(), 6, buf, sizeof(buf)));
- EXPECT_EQ(CFX_WideString(kExpectedPageLabel6),
- CFX_WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel6)));
+ EXPECT_EQ(WideString(kExpectedPageLabel6),
+ WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel6)));
ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 7, buf, sizeof(buf)));
ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 8, buf, sizeof(buf)));
diff --git a/fpdfsdk/fpdfdoc_unittest.cpp b/fpdfsdk/fpdfdoc_unittest.cpp
index c63d6c2..b52cccf 100644
--- a/fpdfsdk/fpdfdoc_unittest.cpp
+++ b/fpdfsdk/fpdfdoc_unittest.cpp
@@ -58,10 +58,7 @@
};
void SetUp() override {
- // We don't need page module or render module, but
- // initialize them to keep the code sane.
- CPDF_ModuleMgr* module_mgr = CPDF_ModuleMgr::Get();
- module_mgr->InitPageModule();
+ CPDF_ModuleMgr::Get()->Init();
m_pDoc = pdfium::MakeUnique<CPDF_TestPdfDocument>();
m_pIndirectObjs = m_pDoc->GetHolder();
@@ -90,7 +87,7 @@
protected:
std::unique_ptr<CPDF_TestPdfDocument> m_pDoc;
- CPDF_IndirectObjectHolder* m_pIndirectObjs;
+ UnownedPtr<CPDF_IndirectObjectHolder> m_pIndirectObjs;
std::unique_ptr<CPDF_Dictionary> m_pRootObj;
};
@@ -119,25 +116,25 @@
auto bookmarks = CreateDictObjs(3);
bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1");
- bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
+ bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs.Get(),
bookmarks[0].num);
- bookmarks[1].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs,
+ bookmarks[1].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs.Get(),
bookmarks[2].num);
bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2");
- bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
+ bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs.Get(),
bookmarks[0].num);
- bookmarks[2].obj->SetNewFor<CPDF_Reference>("Prev", m_pIndirectObjs,
+ bookmarks[2].obj->SetNewFor<CPDF_Reference>("Prev", m_pIndirectObjs.Get(),
bookmarks[1].num);
bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines");
bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2);
- bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
+ bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs.Get(),
bookmarks[1].num);
- bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs,
+ bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs.Get(),
bookmarks[2].num);
- m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs,
+ m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs.Get(),
bookmarks[0].num);
// Title with no match.
@@ -162,25 +159,25 @@
auto bookmarks = CreateDictObjs(3);
bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1");
- bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
+ bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs.Get(),
bookmarks[0].num);
- bookmarks[1].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
+ bookmarks[1].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs.Get(),
bookmarks[2].num);
bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2");
- bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
+ bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs.Get(),
bookmarks[1].num);
- bookmarks[2].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
+ bookmarks[2].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs.Get(),
bookmarks[1].num);
bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines");
bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2);
- bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
+ bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs.Get(),
bookmarks[1].num);
- bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs,
+ bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs.Get(),
bookmarks[2].num);
- m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs,
+ m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs.Get(),
bookmarks[0].num);
// Title with no match.
@@ -197,31 +194,31 @@
auto bookmarks = CreateDictObjs(4);
bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1");
- bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
+ bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs.Get(),
bookmarks[0].num);
- bookmarks[1].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs,
+ bookmarks[1].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs.Get(),
bookmarks[2].num);
bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2");
- bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
+ bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs.Get(),
bookmarks[0].num);
- bookmarks[2].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs,
+ bookmarks[2].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs.Get(),
bookmarks[3].num);
bookmarks[3].obj->SetNewFor<CPDF_String>("Title", L"Chapter 3");
- bookmarks[3].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
+ bookmarks[3].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs.Get(),
bookmarks[0].num);
- bookmarks[3].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs,
+ bookmarks[3].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs.Get(),
bookmarks[1].num);
bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines");
bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2);
- bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
+ bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs.Get(),
bookmarks[1].num);
- bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs,
+ bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs.Get(),
bookmarks[2].num);
- m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs,
+ m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs.Get(),
bookmarks[0].num);
// Title with no match.
diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp
index 53554a1..ee2fc7e 100644
--- a/fpdfsdk/fpdfedit_embeddertest.cpp
+++ b/fpdfsdk/fpdfedit_embeddertest.cpp
@@ -4,14 +4,19 @@
#include <memory>
#include <string>
+#include <utility>
+#include <vector>
#include "core/fpdfapi/font/cpdf_font.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
+#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fxcrt/fx_system.h"
#include "fpdfsdk/fsdk_define.h"
+#include "public/cpp/fpdf_deleters.h"
+#include "public/fpdf_annot.h"
#include "public/fpdf_edit.h"
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
@@ -19,7 +24,113 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
-class FPDFEditEmbeddertest : public EmbedderTest, public TestSaver {};
+class FPDFEditEmbeddertest : public EmbedderTest {
+ protected:
+ FPDF_DOCUMENT CreateNewDocument() {
+ document_ = FPDF_CreateNewDocument();
+ cpdf_doc_ = CPDFDocumentFromFPDFDocument(document_);
+ return document_;
+ }
+
+ void CheckFontDescriptor(CPDF_Dictionary* font_dict,
+ int font_type,
+ bool bold,
+ bool italic,
+ uint32_t size,
+ const uint8_t* data) {
+ CPDF_Dictionary* font_desc = font_dict->GetDictFor("FontDescriptor");
+ ASSERT_TRUE(font_desc);
+ EXPECT_EQ("FontDescriptor", font_desc->GetStringFor("Type"));
+ EXPECT_EQ(font_dict->GetStringFor("BaseFont"),
+ font_desc->GetStringFor("FontName"));
+
+ // Check that the font descriptor has the required keys according to spec
+ // 1.7 Table 5.19
+ ASSERT_TRUE(font_desc->KeyExist("Flags"));
+
+ int font_flags = font_desc->GetIntegerFor("Flags");
+ EXPECT_EQ(bold, FontStyleIsBold(font_flags));
+ EXPECT_EQ(italic, FontStyleIsItalic(font_flags));
+ EXPECT_TRUE(FontStyleIsNonSymbolic(font_flags));
+ ASSERT_TRUE(font_desc->KeyExist("FontBBox"));
+
+ CPDF_Array* fontBBox = font_desc->GetArrayFor("FontBBox");
+ ASSERT_TRUE(fontBBox);
+ EXPECT_EQ(4U, fontBBox->GetCount());
+ // Check that the coordinates are in the preferred order according to spec
+ // 1.7 Section 3.8.4
+ EXPECT_TRUE(fontBBox->GetIntegerAt(0) < fontBBox->GetIntegerAt(2));
+ EXPECT_TRUE(fontBBox->GetIntegerAt(1) < fontBBox->GetIntegerAt(3));
+
+ EXPECT_TRUE(font_desc->KeyExist("ItalicAngle"));
+ EXPECT_TRUE(font_desc->KeyExist("Ascent"));
+ EXPECT_TRUE(font_desc->KeyExist("Descent"));
+ EXPECT_TRUE(font_desc->KeyExist("CapHeight"));
+ EXPECT_TRUE(font_desc->KeyExist("StemV"));
+ ByteString present("FontFile");
+ ByteString absent("FontFile2");
+ if (font_type == FPDF_FONT_TRUETYPE)
+ std::swap(present, absent);
+ EXPECT_TRUE(font_desc->KeyExist(present));
+ EXPECT_FALSE(font_desc->KeyExist(absent));
+
+ // Check that the font stream is the one that was provided
+ CPDF_Stream* font_stream = font_desc->GetStreamFor(present);
+ ASSERT_EQ(size, font_stream->GetRawSize());
+ if (font_type == FPDF_FONT_TRUETYPE) {
+ ASSERT_EQ(static_cast<int>(size),
+ font_stream->GetDict()->GetIntegerFor("Length1"));
+ }
+ uint8_t* stream_data = font_stream->GetRawData();
+ for (size_t j = 0; j < size; j++)
+ EXPECT_EQ(data[j], stream_data[j]) << " at byte " << j;
+ }
+
+ void CheckCompositeFontWidths(CPDF_Array* widths_array,
+ CPDF_Font* typed_font) {
+ // Check that W array is in a format that conforms to PDF spec 1.7 section
+ // "Glyph Metrics in CIDFonts" (these checks are not
+ // implementation-specific).
+ EXPECT_GT(widths_array->GetCount(), 1U);
+ int num_cids_checked = 0;
+ int cur_cid = 0;
+ for (size_t idx = 0; idx < widths_array->GetCount(); idx++) {
+ int cid = widths_array->GetNumberAt(idx);
+ EXPECT_GE(cid, cur_cid);
+ ASSERT_FALSE(++idx == widths_array->GetCount());
+ CPDF_Object* next = widths_array->GetObjectAt(idx);
+ if (next->IsArray()) {
+ // We are in the c [w1 w2 ...] case
+ CPDF_Array* arr = next->AsArray();
+ int cnt = static_cast<int>(arr->GetCount());
+ size_t inner_idx = 0;
+ for (cur_cid = cid; cur_cid < cid + cnt; cur_cid++) {
+ int width = arr->GetNumberAt(inner_idx++);
+ EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid)) << " at cid "
+ << cur_cid;
+ }
+ num_cids_checked += cnt;
+ continue;
+ }
+ // Otherwise, are in the c_first c_last w case.
+ ASSERT_TRUE(next->IsNumber());
+ int last_cid = next->AsNumber()->GetInteger();
+ ASSERT_FALSE(++idx == widths_array->GetCount());
+ int width = widths_array->GetNumberAt(idx);
+ for (cur_cid = cid; cur_cid <= last_cid; cur_cid++) {
+ EXPECT_EQ(width, typed_font->GetCharWidthF(cur_cid)) << " at cid "
+ << cur_cid;
+ }
+ num_cids_checked += last_cid - cid + 1;
+ }
+ // Make sure we have a good amount of cids described
+ EXPECT_GT(num_cids_checked, 900);
+ }
+ CPDF_Document* cpdf_doc() { return cpdf_doc_; }
+
+ private:
+ CPDF_Document* cpdf_doc_;
+};
namespace {
@@ -36,15 +147,13 @@
"<</CreationDate\\(D:.*\\)/Creator\\(PDFium\\)>>\r\n"
"endobj\r\n"
"4 0 obj\r\n"
- "<</Contents 5 0 R /MediaBox\\[ 0 0 640 480\\]"
- "/Parent 2 0 R /Resources<<>>/Rotate 0/Type/Page"
+ "<</MediaBox\\[ 0 0 640 480\\]/Parent 2 0 R "
+ "/Resources<</ExtGState<</FXE1 5 0 R >>>>"
+ "/Rotate 0/Type/Page"
">>\r\n"
"endobj\r\n"
"5 0 obj\r\n"
- "<</Filter/FlateDecode/Length 8>>stream\r\n"
- // Character '_' is matching '\0' (see comment below).
- "x\x9C\x3____\x1\r\n"
- "endstream\r\n"
+ "<</BM/Normal/CA 1/ca 1>>\r\n"
"endobj\r\n"
"xref\r\n"
"0 6\r\n"
@@ -53,47 +162,28 @@
"0000000066 00000 n\r\n"
"0000000122 00000 n\r\n"
"0000000192 00000 n\r\n"
- "0000000301 00000 n\r\n"
+ "0000000311 00000 n\r\n"
"trailer\r\n"
"<<\r\n"
"/Root 1 0 R\r\n"
"/Info 3 0 R\r\n"
"/Size 6/ID\\[<.*><.*>\\]>>\r\n"
"startxref\r\n"
- "379\r\n"
+ "354\r\n"
"%%EOF\r\n";
-int GetBlockFromString(void* param,
- unsigned long pos,
- unsigned char* buf,
- unsigned long size) {
- std::string* new_file = static_cast<std::string*>(param);
- if (!new_file || pos + size < pos)
- return 0;
-
- unsigned long file_size = new_file->size();
- if (pos + size > file_size)
- return 0;
-
- memcpy(buf, new_file->data() + pos, size);
- return 1;
-}
-
} // namespace
TEST_F(FPDFEditEmbeddertest, EmptyCreation) {
EXPECT_TRUE(CreateEmptyDocument());
FPDF_PAGE page = FPDFPage_New(document(), 0, 640.0, 480.0);
EXPECT_NE(nullptr, page);
+ // The FPDFPage_GenerateContent call should do nothing.
EXPECT_TRUE(FPDFPage_GenerateContent(page));
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
- // The MatchesRegexp doesn't support embedded NUL ('\0') characters. They are
- // replaced by '_' for the purpose of the test.
- std::string result = GetString();
- std::replace(result.begin(), result.end(), '\0', '_');
- EXPECT_THAT(result, testing::MatchesRegex(
- std::string(kExpectedPDF, sizeof(kExpectedPDF))));
+ EXPECT_THAT(GetString(), testing::MatchesRegex(std::string(
+ kExpectedPDF, sizeof(kExpectedPDF))));
FPDF_ClosePage(page);
}
@@ -119,7 +209,7 @@
// Add the bitmap to an image object and add the image object to the output
// page.
- FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImgeObj(temp_doc);
+ FPDF_PAGEOBJECT temp_img = FPDFPageObj_NewImageObj(temp_doc);
EXPECT_TRUE(FPDFImageObj_SetBitmap(&temp_page, 1, temp_img, orig_bitmap));
EXPECT_TRUE(FPDFImageObj_SetMatrix(temp_img, 612, 0, 0, 792, 0, 0));
FPDFPage_InsertObject(temp_page, temp_img);
@@ -132,33 +222,13 @@
// Get the generated content. Make sure it is at least as big as the original
// PDF.
- std::string new_file = GetString();
- EXPECT_GT(new_file.size(), 923U);
-
- // Read |new_file| in, and verify its rendered bitmap.
- {
- FPDF_FILEACCESS file_access;
- memset(&file_access, 0, sizeof(file_access));
- file_access.m_FileLen = new_file.size();
- file_access.m_GetBlock = GetBlockFromString;
- file_access.m_Param = &new_file;
-
- FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
- EXPECT_EQ(1, FPDF_GetPageCount(document_));
- FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
- EXPECT_NE(nullptr, new_page);
- FPDF_BITMAP new_bitmap = RenderPage(new_page);
- CompareBitmap(new_bitmap, 612, 792, kAllBlackMd5sum);
- FPDF_ClosePage(new_page);
- FPDF_CloseDocument(new_doc);
- FPDFBitmap_Destroy(new_bitmap);
- }
+ EXPECT_GT(GetString().size(), 923U);
+ VerifySavedDocument(612, 792, kAllBlackMd5sum);
}
TEST_F(FPDFEditEmbeddertest, AddPaths) {
// Start with a blank page
- FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
- FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792);
+ FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
// We will first add a red rectangle
FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
@@ -171,7 +241,6 @@
EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255));
EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
FPDFPage_InsertObject(page, red_rect);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
FPDF_BITMAP page_bitmap = RenderPage(page);
CompareBitmap(page_bitmap, 612, 792, "66d02eaa6181e2c069ce2ea99beda497");
FPDFBitmap_Destroy(page_bitmap);
@@ -179,9 +248,60 @@
// Now add to that a green rectangle with some medium alpha
FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(100, 100, 40, 40);
EXPECT_TRUE(FPDFPath_SetFillColor(green_rect, 0, 255, 0, 128));
+
+ // Make sure the type of the rectangle is a path.
+ EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(green_rect));
+
+ // Make sure we get back the same color we set previously.
+ unsigned int R;
+ unsigned int G;
+ unsigned int B;
+ unsigned int A;
+ EXPECT_TRUE(FPDFPath_GetFillColor(green_rect, &R, &G, &B, &A));
+ EXPECT_EQ(0U, R);
+ EXPECT_EQ(255U, G);
+ EXPECT_EQ(0U, B);
+ EXPECT_EQ(128U, A);
+
+ // Make sure the path has 5 points (1 FXPT_TYPE::MoveTo and 4
+ // FXPT_TYPE::LineTo).
+ ASSERT_EQ(5, FPDFPath_CountSegments(green_rect));
+ // Verify actual coordinates.
+ FPDF_PATHSEGMENT segment = FPDFPath_GetPathSegment(green_rect, 0);
+ float x;
+ float y;
+ EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
+ EXPECT_EQ(100, x);
+ EXPECT_EQ(100, y);
+ EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
+ EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
+ segment = FPDFPath_GetPathSegment(green_rect, 1);
+ EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
+ EXPECT_EQ(100, x);
+ EXPECT_EQ(140, y);
+ EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
+ EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
+ segment = FPDFPath_GetPathSegment(green_rect, 2);
+ EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
+ EXPECT_EQ(140, x);
+ EXPECT_EQ(140, y);
+ EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
+ EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
+ segment = FPDFPath_GetPathSegment(green_rect, 3);
+ EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
+ EXPECT_EQ(140, x);
+ EXPECT_EQ(100, y);
+ EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
+ EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
+ segment = FPDFPath_GetPathSegment(green_rect, 4);
+ EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
+ EXPECT_EQ(100, x);
+ EXPECT_EQ(100, y);
+ EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
+ EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
+
EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_WINDING, 0));
FPDFPage_InsertObject(page, green_rect);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
page_bitmap = RenderPage(page);
CompareBitmap(page_bitmap, 612, 792, "7b0b87604594e773add528fae567a558");
FPDFBitmap_Destroy(page_bitmap);
@@ -193,8 +313,33 @@
EXPECT_TRUE(FPDFPath_LineTo(black_path, 400, 200));
EXPECT_TRUE(FPDFPath_LineTo(black_path, 300, 100));
EXPECT_TRUE(FPDFPath_Close(black_path));
+
+ // Make sure the path has 3 points (1 FXPT_TYPE::MoveTo and 2
+ // FXPT_TYPE::LineTo).
+ ASSERT_EQ(3, FPDFPath_CountSegments(black_path));
+ // Verify actual coordinates.
+ segment = FPDFPath_GetPathSegment(black_path, 0);
+ EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
+ EXPECT_EQ(400, x);
+ EXPECT_EQ(100, y);
+ EXPECT_EQ(FPDF_SEGMENT_MOVETO, FPDFPathSegment_GetType(segment));
+ EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
+ segment = FPDFPath_GetPathSegment(black_path, 1);
+ EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
+ EXPECT_EQ(400, x);
+ EXPECT_EQ(200, y);
+ EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
+ EXPECT_FALSE(FPDFPathSegment_GetClose(segment));
+ segment = FPDFPath_GetPathSegment(black_path, 2);
+ EXPECT_TRUE(FPDFPathSegment_GetPoint(segment, &x, &y));
+ EXPECT_EQ(300, x);
+ EXPECT_EQ(100, y);
+ EXPECT_EQ(FPDF_SEGMENT_LINETO, FPDFPathSegment_GetType(segment));
+ EXPECT_TRUE(FPDFPathSegment_GetClose(segment));
+ // Make sure out of bounds index access fails properly.
+ EXPECT_EQ(nullptr, FPDFPath_GetPathSegment(black_path, 3));
+
FPDFPage_InsertObject(page, black_path);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
page_bitmap = RenderPage(page);
CompareBitmap(page_bitmap, 612, 792, "eadc8020a14dfcf091da2688733d8806");
FPDFBitmap_Destroy(page_bitmap);
@@ -210,33 +355,45 @@
EXPECT_TRUE(FPDFPath_BezierTo(blue_path, 375, 330, 390, 360, 400, 400));
EXPECT_TRUE(FPDFPath_Close(blue_path));
FPDFPage_InsertObject(page, blue_path);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
page_bitmap = RenderPage(page);
- CompareBitmap(page_bitmap, 612, 792, "9823e1a21bd9b72b6a442ba4f12af946");
+ const char last_md5[] = "9823e1a21bd9b72b6a442ba4f12af946";
+ CompareBitmap(page_bitmap, 612, 792, last_md5);
FPDFBitmap_Destroy(page_bitmap);
// Now save the result, closing the page and document
- EXPECT_TRUE(FPDF_SaveAsCopy(doc, this, 0));
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
FPDF_ClosePage(page);
- FPDF_CloseDocument(doc);
- std::string new_file = GetString();
// Render the saved result
- FPDF_FILEACCESS file_access;
- memset(&file_access, 0, sizeof(file_access));
- file_access.m_FileLen = new_file.size();
- file_access.m_GetBlock = GetBlockFromString;
- file_access.m_Param = &new_file;
- FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
- ASSERT_NE(nullptr, new_doc);
- EXPECT_EQ(1, FPDF_GetPageCount(new_doc));
- FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
- ASSERT_NE(nullptr, new_page);
- FPDF_BITMAP new_bitmap = RenderPage(new_page);
- CompareBitmap(new_bitmap, 612, 792, "9823e1a21bd9b72b6a442ba4f12af946");
- FPDFBitmap_Destroy(new_bitmap);
- FPDF_ClosePage(new_page);
- FPDF_CloseDocument(new_doc);
+ VerifySavedDocument(612, 792, last_md5);
+}
+
+TEST_F(FPDFEditEmbeddertest, PathsPoints) {
+ CreateNewDocument();
+ FPDF_PAGEOBJECT img = FPDFPageObj_NewImageObj(document_);
+ // This should fail gracefully, even if img is not a path.
+ ASSERT_EQ(-1, FPDFPath_CountSegments(img));
+
+ // This should fail gracefully, even if path is NULL.
+ ASSERT_EQ(-1, FPDFPath_CountSegments(nullptr));
+
+ // FPDFPath_GetPathSegment() with a non-path.
+ ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(img, 0));
+ // FPDFPath_GetPathSegment() with a NULL path.
+ ASSERT_EQ(nullptr, FPDFPath_GetPathSegment(nullptr, 0));
+ float x;
+ float y;
+ // FPDFPathSegment_GetPoint() with a NULL segment.
+ EXPECT_FALSE(FPDFPathSegment_GetPoint(nullptr, &x, &y));
+
+ // FPDFPathSegment_GetType() with a NULL segment.
+ ASSERT_EQ(FPDF_SEGMENT_UNKNOWN, FPDFPathSegment_GetType(nullptr));
+
+ // FPDFPathSegment_GetClose() with a NULL segment.
+ EXPECT_FALSE(FPDFPathSegment_GetClose(nullptr));
+
+ FPDFPageObj_Destroy(img);
}
TEST_F(FPDFEditEmbeddertest, PathOnTopOfText) {
@@ -250,7 +407,6 @@
EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255));
EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
FPDFPage_InsertObject(page, red_rect);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
// Add a transparent triangle on top of other part of the text.
FPDF_PAGEOBJECT black_path = FPDFPageObj_CreateNewPath(20, 50);
@@ -260,24 +416,81 @@
EXPECT_TRUE(FPDFPath_LineTo(black_path, 40, 10));
EXPECT_TRUE(FPDFPath_Close(black_path));
FPDFPage_InsertObject(page, black_path);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
// Render and check the result. Text is slightly different on Mac.
FPDF_BITMAP bitmap = RenderPage(page);
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
- const char md5[] = "2f7c0deee10a9490538e195af64beb67";
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5[] = "f9e6fa74230f234286bfcada9f7606d8";
#else
- const char md5[] = "17c942c76ff229200f2c98073bb60d85";
+ const char md5[] = "aa71b09b93b55f467f1290e5111babee";
#endif
CompareBitmap(bitmap, 200, 200, md5);
FPDFBitmap_Destroy(bitmap);
UnloadPage(page);
}
+TEST_F(FPDFEditEmbeddertest, EditOverExistingContent) {
+ // Load document with existing content
+ EXPECT_TRUE(OpenDocument("bug_717.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_NE(nullptr, page);
+
+ // Add a transparent rectangle on top of the existing content
+ FPDF_PAGEOBJECT red_rect2 = FPDFPageObj_CreateNewRect(90, 700, 25, 50);
+ EXPECT_TRUE(FPDFPath_SetFillColor(red_rect2, 255, 0, 0, 100));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect2, FPDF_FILLMODE_ALTERNATE, 0));
+ FPDFPage_InsertObject(page, red_rect2);
+
+ // Add an opaque rectangle on top of the existing content
+ FPDF_PAGEOBJECT red_rect = FPDFPageObj_CreateNewRect(115, 700, 25, 50);
+ EXPECT_TRUE(FPDFPath_SetFillColor(red_rect, 255, 0, 0, 255));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(red_rect, FPDF_FILLMODE_ALTERNATE, 0));
+ FPDFPage_InsertObject(page, red_rect);
+
+ FPDF_BITMAP bitmap = RenderPage(page);
+ CompareBitmap(bitmap, 612, 792, "ad04e5bd0f471a9a564fb034bd0fb073");
+ FPDFBitmap_Destroy(bitmap);
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+
+ // Now save the result, closing the page and document
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ UnloadPage(page);
+
+ OpenSavedDocument();
+ page = LoadSavedPage(0);
+ VerifySavedRendering(page, 612, 792, "ad04e5bd0f471a9a564fb034bd0fb073");
+
+ ClearString();
+ // Add another opaque rectangle on top of the existing content
+ FPDF_PAGEOBJECT green_rect = FPDFPageObj_CreateNewRect(150, 700, 25, 50);
+ EXPECT_TRUE(FPDFPath_SetFillColor(green_rect, 0, 255, 0, 255));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect, FPDF_FILLMODE_ALTERNATE, 0));
+ FPDFPage_InsertObject(page, green_rect);
+
+ // Add another transparent rectangle on top of existing content
+ FPDF_PAGEOBJECT green_rect2 = FPDFPageObj_CreateNewRect(175, 700, 25, 50);
+ EXPECT_TRUE(FPDFPath_SetFillColor(green_rect2, 0, 255, 0, 100));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(green_rect2, FPDF_FILLMODE_ALTERNATE, 0));
+ FPDFPage_InsertObject(page, green_rect2);
+ FPDF_BITMAP new_bitmap = RenderPageWithFlags(page, m_SavedForm, 0);
+ const char last_md5[] = "4b5b00f824620f8c9b8801ebb98e1cdd";
+ CompareBitmap(new_bitmap, 612, 792, last_md5);
+ FPDFBitmap_Destroy(new_bitmap);
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+
+ // Now save the result, closing the page and document
+ EXPECT_TRUE(FPDF_SaveAsCopy(m_SavedDocument, this, 0));
+
+ CloseSavedPage(page);
+ CloseSavedDocument();
+
+ // Render the saved result
+ VerifySavedDocument(612, 792, last_md5);
+}
+
TEST_F(FPDFEditEmbeddertest, AddStrokedPaths) {
// Start with a blank page
- FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
- FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792);
+ FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
// Add a large stroked rectangle (fill color should not affect it).
FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(20, 20, 200, 400);
@@ -286,7 +499,6 @@
EXPECT_TRUE(FPDFPath_SetStrokeWidth(rect, 15.0f));
EXPECT_TRUE(FPDFPath_SetDrawMode(rect, 0, 1));
FPDFPage_InsertObject(page, rect);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
FPDF_BITMAP page_bitmap = RenderPage(page);
CompareBitmap(page_bitmap, 612, 792, "64bd31f862a89e0a9e505a5af6efd506");
FPDFBitmap_Destroy(page_bitmap);
@@ -301,7 +513,6 @@
EXPECT_TRUE(FPDFPath_SetStrokeWidth(check, 8.35f));
EXPECT_TRUE(FPDFPath_SetDrawMode(check, 0, 1));
FPDFPage_InsertObject(page, check);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
page_bitmap = RenderPage(page);
CompareBitmap(page_bitmap, 612, 792, "4b6f3b9d25c4e194821217d5016c3724");
FPDFBitmap_Destroy(page_bitmap);
@@ -317,64 +528,70 @@
EXPECT_TRUE(FPDFPath_SetStrokeWidth(path, 10.5f));
EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 1));
FPDFPage_InsertObject(page, path);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
page_bitmap = RenderPage(page);
CompareBitmap(page_bitmap, 612, 792, "ff3e6a22326754944cc6e56609acd73b");
FPDFBitmap_Destroy(page_bitmap);
FPDF_ClosePage(page);
- FPDF_CloseDocument(doc);
}
TEST_F(FPDFEditEmbeddertest, AddStandardFontText) {
// Start with a blank page
- FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
- FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792);
+ FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
// Add some text to the page
- FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(doc, "Arial", 12.0f);
- EXPECT_TRUE(text1);
- EXPECT_TRUE(FPDFText_SetText(text1, "I'm at the bottom of the page"));
- FPDFPageObj_Transform(text1, 1, 0, 0, 1, 20, 20);
- FPDFPage_InsertObject(page, text1);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ FPDF_PAGEOBJECT text_object1 =
+ FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
+ EXPECT_TRUE(text_object1);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text1 =
+ GetFPDFWideString(L"I'm at the bottom of the page");
+ EXPECT_TRUE(FPDFText_SetText(text_object1, text1.get()));
+ FPDFPageObj_Transform(text_object1, 1, 0, 0, 1, 20, 20);
+ FPDFPage_InsertObject(page, text_object1);
FPDF_BITMAP page_bitmap = RenderPage(page);
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
- const char md5[] = "e19c90395d73cb9f37a6c3b0e8b18a9e";
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5[] = "a4dddc1a3930fa694bbff9789dab4161";
#else
- const char md5[] = "7c3a36ba7cec01688a16a14bfed9ecfc";
+ const char md5[] = "eacaa24573b8ce997b3882595f096f00";
#endif
CompareBitmap(page_bitmap, 612, 792, md5);
FPDFBitmap_Destroy(page_bitmap);
// Try another font
- FPDF_PAGEOBJECT text2 =
- FPDFPageObj_NewTextObj(doc, "TimesNewRomanBold", 15.0f);
- EXPECT_TRUE(text2);
- EXPECT_TRUE(FPDFText_SetText(text2, "Hi, I'm Bold. Times New Roman Bold."));
- FPDFPageObj_Transform(text2, 1, 0, 0, 1, 100, 600);
- FPDFPage_InsertObject(page, text2);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ FPDF_PAGEOBJECT text_object2 =
+ FPDFPageObj_NewTextObj(document(), "TimesNewRomanBold", 15.0f);
+ EXPECT_TRUE(text_object2);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text2 =
+ GetFPDFWideString(L"Hi, I'm Bold. Times New Roman Bold.");
+ EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
+ FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 600);
+ FPDFPage_InsertObject(page, text_object2);
page_bitmap = RenderPage(page);
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
- const char md5_2[] = "8e1c43dca6be68d364dbc283f5521041";
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5_2[] = "a5c4ace4c6f27644094813fe1441a21c";
+#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
+ const char md5_2[] = "2587eac9a787e97a37636d54d11bd28d";
#else
- const char md5_2[] = "e0e0873e3a2634a6394a431a51ce90ff";
+ const char md5_2[] = "76fcc7d08aa15445efd2e2ceb7c6cc3b";
#endif
CompareBitmap(page_bitmap, 612, 792, md5_2);
FPDFBitmap_Destroy(page_bitmap);
// And some randomly transformed text
- FPDF_PAGEOBJECT text3 = FPDFPageObj_NewTextObj(doc, "Courier-Bold", 20.0f);
- EXPECT_TRUE(text3);
- EXPECT_TRUE(FPDFText_SetText(text3, "Can you read me? <:)>"));
- FPDFPageObj_Transform(text3, 1, 1.5, 2, 0.5, 200, 200);
- FPDFPage_InsertObject(page, text3);
- EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ FPDF_PAGEOBJECT text_object3 =
+ FPDFPageObj_NewTextObj(document(), "Courier-Bold", 20.0f);
+ EXPECT_TRUE(text_object3);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text3 =
+ GetFPDFWideString(L"Can you read me? <:)>");
+ EXPECT_TRUE(FPDFText_SetText(text_object3, text3.get()));
+ FPDFPageObj_Transform(text_object3, 1, 1.5, 2, 0.5, 200, 200);
+ FPDFPage_InsertObject(page, text_object3);
page_bitmap = RenderPage(page);
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
- const char md5_3[] = "c6e5df448428793c7e4b0c820bd8c85e";
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5_3[] = "40b3ef04f915ff4c4208948001763544";
+#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
+ const char md5_3[] = "7cb61ec112cf400b489360d443ffc9d2";
#else
- const char md5_3[] = "903ee10b6a9f0be51ecad0a1a0eeb171";
+ const char md5_3[] = "b8a21668f1dab625af7c072e07fcefc4";
#endif
CompareBitmap(page_bitmap, 612, 792, md5_3);
FPDFBitmap_Destroy(page_bitmap);
@@ -382,13 +599,65 @@
// TODO(npm): Why are there issues with text rotated by 90 degrees?
// TODO(npm): FPDF_SaveAsCopy not giving the desired result after this.
FPDF_ClosePage(page);
- FPDF_CloseDocument(doc);
+}
+
+TEST_F(FPDFEditEmbeddertest, GraphicsData) {
+ // New page
+ std::unique_ptr<void, FPDFPageDeleter> page(
+ FPDFPage_New(CreateNewDocument(), 0, 612, 792));
+
+ // Create a rect with nontrivial graphics
+ FPDF_PAGEOBJECT rect1 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
+ FPDFPageObj_SetBlendMode(rect1, "Color");
+ FPDFPage_InsertObject(page.get(), rect1);
+ EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
+
+ // Check that the ExtGState was created
+ CPDF_Page* the_page = CPDFPageFromFPDFPage(page.get());
+ CPDF_Dictionary* graphics_dict =
+ the_page->m_pResources->GetDictFor("ExtGState");
+ ASSERT_TRUE(graphics_dict);
+ EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
+
+ // Add a text object causing no change to the graphics dictionary
+ FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
+ // Only alpha, the last component, matters for the graphics dictionary. And
+ // the default value is 255.
+ EXPECT_TRUE(FPDFText_SetFillColor(text1, 100, 100, 100, 255));
+ FPDFPage_InsertObject(page.get(), text1);
+ EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
+ EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
+
+ // Add a text object increasing the size of the graphics dictionary
+ FPDF_PAGEOBJECT text2 =
+ FPDFPageObj_NewTextObj(document(), "Times-Roman", 12.0f);
+ FPDFPage_InsertObject(page.get(), text2);
+ FPDFPageObj_SetBlendMode(text2, "Darken");
+ EXPECT_TRUE(FPDFText_SetFillColor(text2, 0, 0, 255, 150));
+ EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
+ EXPECT_EQ(3, static_cast<int>(graphics_dict->GetCount()));
+
+ // Add a path that should reuse graphics
+ FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
+ FPDFPageObj_SetBlendMode(path, "Darken");
+ EXPECT_TRUE(FPDFPath_SetFillColor(path, 200, 200, 100, 150));
+ FPDFPage_InsertObject(page.get(), path);
+ EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
+ EXPECT_EQ(3, static_cast<int>(graphics_dict->GetCount()));
+
+ // Add a rect increasing the size of the graphics dictionary
+ FPDF_PAGEOBJECT rect2 = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
+ FPDFPageObj_SetBlendMode(rect2, "Darken");
+ EXPECT_TRUE(FPDFPath_SetFillColor(rect2, 0, 0, 255, 150));
+ EXPECT_TRUE(FPDFPath_SetStrokeColor(rect2, 0, 0, 0, 200));
+ FPDFPage_InsertObject(page.get(), rect2);
+ EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
+ EXPECT_EQ(4, static_cast<int>(graphics_dict->GetCount()));
}
TEST_F(FPDFEditEmbeddertest, DoubleGenerating) {
// Start with a blank page
- FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
- FPDF_PAGE page = FPDFPage_New(doc, 0, 612, 792);
+ FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
// Add a red rectangle with some non-default alpha
FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 100, 100);
@@ -402,7 +671,7 @@
CPDF_Dictionary* graphics_dict =
the_page->m_pResources->GetDictFor("ExtGState");
ASSERT_TRUE(graphics_dict);
- EXPECT_EQ(1, static_cast<int>(graphics_dict->GetCount()));
+ EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
// Check the bitmap
FPDF_BITMAP page_bitmap = RenderPage(page);
@@ -412,7 +681,7 @@
// Never mind, my new favorite color is blue, increase alpha
EXPECT_TRUE(FPDFPath_SetFillColor(rect, 0, 0, 255, 180));
EXPECT_TRUE(FPDFPage_GenerateContent(page));
- EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
+ EXPECT_EQ(3, static_cast<int>(graphics_dict->GetCount()));
// Check that bitmap displays changed content
page_bitmap = RenderPage(page);
@@ -421,16 +690,19 @@
// And now generate, without changes
EXPECT_TRUE(FPDFPage_GenerateContent(page));
- EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
+ EXPECT_EQ(3, static_cast<int>(graphics_dict->GetCount()));
page_bitmap = RenderPage(page);
CompareBitmap(page_bitmap, 612, 792, "2e51656f5073b0bee611d9cd086aa09c");
FPDFBitmap_Destroy(page_bitmap);
// Add some text to the page
- FPDF_PAGEOBJECT text = FPDFPageObj_NewTextObj(doc, "Arial", 12.0f);
- EXPECT_TRUE(FPDFText_SetText(text, "Something something #text# something"));
- FPDFPageObj_Transform(text, 1, 0, 0, 1, 300, 300);
- FPDFPage_InsertObject(page, text);
+ FPDF_PAGEOBJECT text_object =
+ FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
+ GetFPDFWideString(L"Something something #text# something");
+ EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
+ FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 300, 300);
+ FPDFPage_InsertObject(page, text_object);
EXPECT_TRUE(FPDFPage_GenerateContent(page));
CPDF_Dictionary* font_dict = the_page->m_pResources->GetDictFor("Font");
ASSERT_TRUE(font_dict);
@@ -438,68 +710,530 @@
// Generate yet again, check dicts are reasonably sized
EXPECT_TRUE(FPDFPage_GenerateContent(page));
- EXPECT_EQ(2, static_cast<int>(graphics_dict->GetCount()));
+ EXPECT_EQ(3, static_cast<int>(graphics_dict->GetCount()));
EXPECT_EQ(1, static_cast<int>(font_dict->GetCount()));
FPDF_ClosePage(page);
- FPDF_CloseDocument(doc);
}
-TEST_F(FPDFEditEmbeddertest, Type1Font) {
- // Create a new document
- FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
- CPDF_Document* document = reinterpret_cast<CPDF_Document*>(doc);
+TEST_F(FPDFEditEmbeddertest, LoadSimpleType1Font) {
+ CreateNewDocument();
+ // TODO(npm): use other fonts after disallowing loading any font as any type
+ const CPDF_Font* stock_font =
+ CPDF_Font::GetStockFont(cpdf_doc(), "Times-Bold");
+ const uint8_t* data = stock_font->GetFont()->GetFontData();
+ const uint32_t size = stock_font->GetFont()->GetSize();
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TYPE1, false));
+ ASSERT_TRUE(font.get());
+ CPDF_Font* typed_font = static_cast<CPDF_Font*>(font.get());
+ EXPECT_TRUE(typed_font->IsType1Font());
- // Get Times New Roman Bold as a Type 1 font
- CPDF_Font* times_bold = CPDF_Font::GetStockFont(document, "Times-Bold");
- uint8_t* data = times_bold->m_Font.GetFontData();
- uint32_t size = times_bold->m_Font.GetSize();
- FPDF_FONT font = FPDFText_LoadType1Font(doc, data, size);
- ASSERT_TRUE(font);
- CPDF_Font* type1_font = reinterpret_cast<CPDF_Font*>(font);
- EXPECT_TRUE(type1_font->IsType1Font());
-
- // Check that the font dictionary has the required keys according to the spec
- CPDF_Dictionary* font_dict = type1_font->GetFontDict();
+ CPDF_Dictionary* font_dict = typed_font->GetFontDict();
EXPECT_EQ("Font", font_dict->GetStringFor("Type"));
EXPECT_EQ("Type1", font_dict->GetStringFor("Subtype"));
EXPECT_EQ("Times New Roman Bold", font_dict->GetStringFor("BaseFont"));
ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
ASSERT_TRUE(font_dict->KeyExist("LastChar"));
EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
- EXPECT_EQ(65532, font_dict->GetIntegerFor("LastChar"));
- ASSERT_TRUE(font_dict->KeyExist("Widths"));
+ EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
+
CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
- EXPECT_EQ(65501U, widths_array->GetCount());
+ ASSERT_TRUE(widths_array);
+ ASSERT_EQ(224U, widths_array->GetCount());
EXPECT_EQ(250, widths_array->GetNumberAt(0));
- EXPECT_EQ(0, widths_array->GetNumberAt(8172));
- EXPECT_EQ(1000, widths_array->GetNumberAt(65500));
- ASSERT_TRUE(font_dict->KeyExist("FontDescriptor"));
- CPDF_Dictionary* font_desc = font_dict->GetDictFor("FontDescriptor");
- EXPECT_EQ("FontDescriptor", font_desc->GetStringFor("Type"));
- EXPECT_EQ(font_dict->GetStringFor("BaseFont"),
- font_desc->GetStringFor("FontName"));
+ EXPECT_EQ(569, widths_array->GetNumberAt(11));
+ EXPECT_EQ(500, widths_array->GetNumberAt(223));
+ CheckFontDescriptor(font_dict, FPDF_FONT_TYPE1, true, false, size, data);
+}
- // Check that the font descriptor has the required keys according to the spec
- ASSERT_TRUE(font_desc->KeyExist("Flags"));
- int font_flags = font_desc->GetIntegerFor("Flags");
- EXPECT_TRUE(font_flags & FXFONT_BOLD);
- EXPECT_TRUE(font_flags & FXFONT_NONSYMBOLIC);
- ASSERT_TRUE(font_desc->KeyExist("FontBBox"));
- EXPECT_EQ(4U, font_desc->GetArrayFor("FontBBox")->GetCount());
- EXPECT_TRUE(font_desc->KeyExist("ItalicAngle"));
- EXPECT_TRUE(font_desc->KeyExist("Ascent"));
- EXPECT_TRUE(font_desc->KeyExist("Descent"));
- EXPECT_TRUE(font_desc->KeyExist("CapHeight"));
- EXPECT_TRUE(font_desc->KeyExist("StemV"));
- ASSERT_TRUE(font_desc->KeyExist("FontFile"));
+TEST_F(FPDFEditEmbeddertest, LoadSimpleTrueTypeFont) {
+ CreateNewDocument();
+ const CPDF_Font* stock_font = CPDF_Font::GetStockFont(cpdf_doc(), "Courier");
+ const uint8_t* data = stock_font->GetFont()->GetFontData();
+ const uint32_t size = stock_font->GetFont()->GetSize();
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, false));
+ ASSERT_TRUE(font.get());
+ CPDF_Font* typed_font = static_cast<CPDF_Font*>(font.get());
+ EXPECT_TRUE(typed_font->IsTrueTypeFont());
- // Check that the font stream is the one that was provided
- CPDF_Stream* font_stream = font_desc->GetStreamFor("FontFile");
- ASSERT_EQ(size, font_stream->GetRawSize());
- uint8_t* stream_data = font_stream->GetRawData();
- for (size_t i = 0; i < size; i++)
- EXPECT_EQ(data[i], stream_data[i]);
+ CPDF_Dictionary* font_dict = typed_font->GetFontDict();
+ EXPECT_EQ("Font", font_dict->GetStringFor("Type"));
+ EXPECT_EQ("TrueType", font_dict->GetStringFor("Subtype"));
+ EXPECT_EQ("Courier New", font_dict->GetStringFor("BaseFont"));
+ ASSERT_TRUE(font_dict->KeyExist("FirstChar"));
+ ASSERT_TRUE(font_dict->KeyExist("LastChar"));
+ EXPECT_EQ(32, font_dict->GetIntegerFor("FirstChar"));
+ EXPECT_EQ(255, font_dict->GetIntegerFor("LastChar"));
- // Close document
- FPDF_CloseDocument(doc);
+ CPDF_Array* widths_array = font_dict->GetArrayFor("Widths");
+ ASSERT_TRUE(widths_array);
+ ASSERT_EQ(224U, widths_array->GetCount());
+ EXPECT_EQ(600, widths_array->GetNumberAt(33));
+ EXPECT_EQ(600, widths_array->GetNumberAt(74));
+ EXPECT_EQ(600, widths_array->GetNumberAt(223));
+ CheckFontDescriptor(font_dict, FPDF_FONT_TRUETYPE, false, false, size, data);
+}
+
+TEST_F(FPDFEditEmbeddertest, LoadCIDType0Font) {
+ CreateNewDocument();
+ const CPDF_Font* stock_font =
+ CPDF_Font::GetStockFont(cpdf_doc(), "Times-Roman");
+ const uint8_t* data = stock_font->GetFont()->GetFontData();
+ const uint32_t size = stock_font->GetFont()->GetSize();
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TYPE1, 1));
+ ASSERT_TRUE(font.get());
+ CPDF_Font* typed_font = static_cast<CPDF_Font*>(font.get());
+ EXPECT_TRUE(typed_font->IsCIDFont());
+
+ // Check font dictionary entries
+ CPDF_Dictionary* font_dict = typed_font->GetFontDict();
+ EXPECT_EQ("Font", font_dict->GetStringFor("Type"));
+ EXPECT_EQ("Type0", font_dict->GetStringFor("Subtype"));
+ EXPECT_EQ("Times New Roman-Identity-H", font_dict->GetStringFor("BaseFont"));
+ EXPECT_EQ("Identity-H", font_dict->GetStringFor("Encoding"));
+ CPDF_Array* descendant_array = font_dict->GetArrayFor("DescendantFonts");
+ ASSERT_TRUE(descendant_array);
+ EXPECT_EQ(1U, descendant_array->GetCount());
+
+ // Check the CIDFontDict
+ CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
+ EXPECT_EQ("Font", cidfont_dict->GetStringFor("Type"));
+ EXPECT_EQ("CIDFontType0", cidfont_dict->GetStringFor("Subtype"));
+ EXPECT_EQ("Times New Roman", cidfont_dict->GetStringFor("BaseFont"));
+ CPDF_Dictionary* cidinfo_dict = cidfont_dict->GetDictFor("CIDSystemInfo");
+ ASSERT_TRUE(cidinfo_dict);
+ EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry"));
+ EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering"));
+ EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
+ CheckFontDescriptor(cidfont_dict, FPDF_FONT_TYPE1, false, false, size, data);
+
+ // Check widths
+ CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
+ ASSERT_TRUE(widths_array);
+ EXPECT_GT(widths_array->GetCount(), 1U);
+ CheckCompositeFontWidths(widths_array, typed_font);
+}
+
+TEST_F(FPDFEditEmbeddertest, LoadCIDType2Font) {
+ CreateNewDocument();
+ const CPDF_Font* stock_font =
+ CPDF_Font::GetStockFont(cpdf_doc(), "Helvetica-Oblique");
+ const uint8_t* data = stock_font->GetFont()->GetFontData();
+ const uint32_t size = stock_font->GetFont()->GetSize();
+
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 1));
+ ASSERT_TRUE(font.get());
+ CPDF_Font* typed_font = static_cast<CPDF_Font*>(font.get());
+ EXPECT_TRUE(typed_font->IsCIDFont());
+
+ // Check font dictionary entries
+ CPDF_Dictionary* font_dict = typed_font->GetFontDict();
+ EXPECT_EQ("Font", font_dict->GetStringFor("Type"));
+ EXPECT_EQ("Type0", font_dict->GetStringFor("Subtype"));
+ EXPECT_EQ("Arial Italic", font_dict->GetStringFor("BaseFont"));
+ EXPECT_EQ("Identity-H", font_dict->GetStringFor("Encoding"));
+ CPDF_Array* descendant_array = font_dict->GetArrayFor("DescendantFonts");
+ ASSERT_TRUE(descendant_array);
+ EXPECT_EQ(1U, descendant_array->GetCount());
+
+ // Check the CIDFontDict
+ CPDF_Dictionary* cidfont_dict = descendant_array->GetDictAt(0);
+ EXPECT_EQ("Font", cidfont_dict->GetStringFor("Type"));
+ EXPECT_EQ("CIDFontType2", cidfont_dict->GetStringFor("Subtype"));
+ EXPECT_EQ("Arial Italic", cidfont_dict->GetStringFor("BaseFont"));
+ CPDF_Dictionary* cidinfo_dict = cidfont_dict->GetDictFor("CIDSystemInfo");
+ ASSERT_TRUE(cidinfo_dict);
+ EXPECT_EQ("Adobe", cidinfo_dict->GetStringFor("Registry"));
+ EXPECT_EQ("Identity", cidinfo_dict->GetStringFor("Ordering"));
+ EXPECT_EQ(0, cidinfo_dict->GetNumberFor("Supplement"));
+ CheckFontDescriptor(cidfont_dict, FPDF_FONT_TRUETYPE, false, true, size,
+ data);
+
+ // Check widths
+ CPDF_Array* widths_array = cidfont_dict->GetArrayFor("W");
+ ASSERT_TRUE(widths_array);
+ CheckCompositeFontWidths(widths_array, typed_font);
+}
+
+TEST_F(FPDFEditEmbeddertest, NormalizeNegativeRotation) {
+ // Load document with a -90 degree rotation
+ EXPECT_TRUE(OpenDocument("bug_713197.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_NE(nullptr, page);
+
+ EXPECT_EQ(3, FPDFPage_GetRotation(page));
+ UnloadPage(page);
+}
+
+TEST_F(FPDFEditEmbeddertest, AddTrueTypeFontText) {
+ // Start with a blank page
+ FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
+ {
+ const CPDF_Font* stock_font = CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
+ const uint8_t* data = stock_font->GetFont()->GetFontData();
+ const uint32_t size = stock_font->GetFont()->GetSize();
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 0));
+ ASSERT_TRUE(font.get());
+
+ // Add some text to the page
+ FPDF_PAGEOBJECT text_object =
+ FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
+ EXPECT_TRUE(text_object);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
+ GetFPDFWideString(L"I am testing my loaded font, WEE.");
+ EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
+ FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
+ FPDFPage_InsertObject(page, text_object);
+ FPDF_BITMAP page_bitmap = RenderPage(page);
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5[] = "17d2b6cd574cf66170b09c8927529a94";
+#else
+ const char md5[] = "70592859010ffbf532a2237b8118bcc4";
+#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ CompareBitmap(page_bitmap, 612, 792, md5);
+ FPDFBitmap_Destroy(page_bitmap);
+
+ // Add some more text, same font
+ FPDF_PAGEOBJECT text_object2 =
+ FPDFPageObj_CreateTextObj(document(), font.get(), 15.0f);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text2 =
+ GetFPDFWideString(L"Bigger font size");
+ EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
+ FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 200, 200);
+ FPDFPage_InsertObject(page, text_object2);
+ }
+ FPDF_BITMAP page_bitmap2 = RenderPage(page);
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5_2[] = "8eded4193ff1f0f77b8b600a825e97ea";
+#else
+ const char md5_2[] = "c1d10cce1761c4a998a16b2562030568";
+#endif // _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ CompareBitmap(page_bitmap2, 612, 792, md5_2);
+ FPDFBitmap_Destroy(page_bitmap2);
+
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+
+ VerifySavedDocument(612, 792, md5_2);
+}
+
+TEST_F(FPDFEditEmbeddertest, TransformAnnot) {
+ // Open a file with one annotation and load its first page.
+ ASSERT_TRUE(OpenDocument("annotation_highlight_long_content.pdf"));
+ FPDF_PAGE page = FPDF_LoadPage(document(), 0);
+ ASSERT_TRUE(page);
+
+ // Add an underline annotation to the page without specifying its rectangle.
+ FPDF_ANNOTATION annot = FPDFPage_CreateAnnot(page, FPDF_ANNOT_UNDERLINE);
+ ASSERT_TRUE(annot);
+
+ // FPDFPage_TransformAnnots() should run without errors when modifying
+ // annotation rectangles.
+ FPDFPage_TransformAnnots(page, 1, 2, 3, 4, 5, 6);
+
+ FPDFPage_CloseAnnot(annot);
+ UnloadPage(page);
+}
+
+// TODO(npm): Add tests using Japanese fonts in other OS.
+#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_
+TEST_F(FPDFEditEmbeddertest, AddCIDFontText) {
+ // Start with a blank page
+ FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
+ CFX_Font CIDfont;
+ {
+ // First, get the data from the font
+ CIDfont.LoadSubst("IPAGothic", 1, 0, 400, 0, 932, 0);
+ EXPECT_EQ("IPAGothic", CIDfont.GetFaceName());
+ const uint8_t* data = CIDfont.GetFontData();
+ const uint32_t size = CIDfont.GetSize();
+
+ // Load the data into a FPDF_Font.
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 1));
+ ASSERT_TRUE(font.get());
+
+ // Add some text to the page
+ FPDF_PAGEOBJECT text_object =
+ FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
+ ASSERT_TRUE(text_object);
+ std::wstring wstr = L"ABCDEFGhijklmnop.";
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
+ GetFPDFWideString(wstr);
+ EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
+ FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 200, 200);
+ FPDFPage_InsertObject(page, text_object);
+
+ // And add some Japanese characters
+ FPDF_PAGEOBJECT text_object2 =
+ FPDFPageObj_CreateTextObj(document(), font.get(), 18.0f);
+ ASSERT_TRUE(text_object2);
+ std::wstring wstr2 =
+ L"\u3053\u3093\u306B\u3061\u306f\u4e16\u754C\u3002\u3053\u3053\u306B1"
+ L"\u756A";
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text2 =
+ GetFPDFWideString(wstr2);
+ EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
+ FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 500);
+ FPDFPage_InsertObject(page, text_object2);
+ }
+
+ // Check that the text renders properly.
+ FPDF_BITMAP page_bitmap = RenderPage(page);
+ const char md5[] = "c68cd79aa72bf83a7b25271370d46b21";
+ CompareBitmap(page_bitmap, 612, 792, md5);
+ FPDFBitmap_Destroy(page_bitmap);
+
+ // Save the document, close the page.
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+
+ VerifySavedDocument(612, 792, md5);
+}
+#endif // _FX_PLATFORM_ == _FX_PLATFORM_LINUX_
+
+TEST_F(FPDFEditEmbeddertest, SaveAndRender) {
+ const char md5[] = "3c20472b0552c0c22b88ab1ed8c6202b";
+ {
+ EXPECT_TRUE(OpenDocument("bug_779.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_NE(nullptr, page);
+
+ // Now add a more complex blue path.
+ FPDF_PAGEOBJECT green_path = FPDFPageObj_CreateNewPath(20, 20);
+ EXPECT_TRUE(FPDFPath_SetFillColor(green_path, 0, 255, 0, 200));
+ // TODO(npm): stroking will cause the MD5s to differ.
+ EXPECT_TRUE(FPDFPath_SetDrawMode(green_path, FPDF_FILLMODE_WINDING, 0));
+ EXPECT_TRUE(FPDFPath_LineTo(green_path, 20, 63));
+ EXPECT_TRUE(FPDFPath_BezierTo(green_path, 55, 55, 78, 78, 90, 90));
+ EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 133));
+ EXPECT_TRUE(FPDFPath_LineTo(green_path, 133, 33));
+ EXPECT_TRUE(FPDFPath_BezierTo(green_path, 38, 33, 39, 36, 40, 40));
+ EXPECT_TRUE(FPDFPath_Close(green_path));
+ FPDFPage_InsertObject(page, green_path);
+ FPDF_BITMAP page_bitmap = RenderPage(page);
+ CompareBitmap(page_bitmap, 612, 792, md5);
+ FPDFBitmap_Destroy(page_bitmap);
+
+ // Now save the result, closing the page and document
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ UnloadPage(page);
+ }
+
+ VerifySavedDocument(612, 792, md5);
+}
+
+TEST_F(FPDFEditEmbeddertest, ExtractImageBitmap) {
+ ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+ ASSERT_EQ(39, FPDFPage_CountObjects(page));
+
+ FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
+ EXPECT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ EXPECT_FALSE(FPDFImageObj_GetBitmap(obj));
+
+ obj = FPDFPage_GetObject(page, 33);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ FPDF_BITMAP bitmap = FPDFImageObj_GetBitmap(obj);
+ EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
+ CompareBitmap(bitmap, 109, 88, "d65e98d968d196abf13f78aec655ffae");
+ FPDFBitmap_Destroy(bitmap);
+
+ obj = FPDFPage_GetObject(page, 34);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ bitmap = FPDFImageObj_GetBitmap(obj);
+ EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
+ CompareBitmap(bitmap, 103, 75, "1287711c84dbef767c435d11697661d6");
+ FPDFBitmap_Destroy(bitmap);
+
+ obj = FPDFPage_GetObject(page, 35);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ bitmap = FPDFImageObj_GetBitmap(obj);
+ EXPECT_EQ(FPDFBitmap_Gray, FPDFBitmap_GetFormat(bitmap));
+ CompareBitmap(bitmap, 92, 68, "9c6d76cb1e37ef8514f9455d759391f3");
+ FPDFBitmap_Destroy(bitmap);
+
+ obj = FPDFPage_GetObject(page, 36);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ bitmap = FPDFImageObj_GetBitmap(obj);
+ EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
+ CompareBitmap(bitmap, 79, 60, "15cb6a49a2e354ed0e9f45dd34e3da1a");
+ FPDFBitmap_Destroy(bitmap);
+
+ obj = FPDFPage_GetObject(page, 37);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ bitmap = FPDFImageObj_GetBitmap(obj);
+ EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
+ CompareBitmap(bitmap, 126, 106, "be5a64ba7890d2657522af6524118534");
+ FPDFBitmap_Destroy(bitmap);
+
+ obj = FPDFPage_GetObject(page, 38);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ bitmap = FPDFImageObj_GetBitmap(obj);
+ EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap));
+ CompareBitmap(bitmap, 194, 119, "f9e24207ee1bc0db6c543d33a5f12ec5");
+ FPDFBitmap_Destroy(bitmap);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFEditEmbeddertest, GetImageData) {
+ EXPECT_TRUE(OpenDocument("embedded_images.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+ ASSERT_EQ(39, FPDFPage_CountObjects(page));
+
+ // Retrieve an image object with flate-encoded data stream.
+ FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 33);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+
+ // Check that the raw image data has the correct length and hash value.
+ unsigned long len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
+ std::vector<char> buf(len);
+ EXPECT_EQ(4091u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
+ EXPECT_EQ("f73802327d2e88e890f653961bcda81a",
+ GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
+
+ // Check that the decoded image data has the correct length and hash value.
+ len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(28776u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
+ EXPECT_EQ("cb3637934bb3b95a6e4ae1ea9eb9e56e",
+ GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
+
+ // Retrieve an image obejct with DCTDecode-encoded data stream.
+ obj = FPDFPage_GetObject(page, 37);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+
+ // Check that the raw image data has the correct length and hash value.
+ len = FPDFImageObj_GetImageDataRaw(obj, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(4370u, FPDFImageObj_GetImageDataRaw(obj, buf.data(), len));
+ EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
+ GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
+
+ // Check that the decoded image data has the correct length and hash value,
+ // which should be the same as those of the raw data, since this image is
+ // encoded by a single DCTDecode filter and decoding is a noop.
+ len = FPDFImageObj_GetImageDataDecoded(obj, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ EXPECT_EQ(4370u, FPDFImageObj_GetImageDataDecoded(obj, buf.data(), len));
+ EXPECT_EQ("6aae1f3710335023a9e12191be66b64b",
+ GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len));
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFEditEmbeddertest, DestroyPageObject) {
+ FPDF_PAGEOBJECT rect = FPDFPageObj_CreateNewRect(10, 10, 20, 20);
+ ASSERT_TRUE(rect);
+
+ // There should be no memory leaks with a call to FPDFPageObj_Destroy().
+ FPDFPageObj_Destroy(rect);
+}
+
+TEST_F(FPDFEditEmbeddertest, GetImageFilters) {
+ EXPECT_TRUE(OpenDocument("embedded_images.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ // Verify that retrieving the filter of a non-image object would fail.
+ FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 32);
+ ASSERT_NE(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ ASSERT_EQ(0, FPDFImageObj_GetImageFilterCount(obj));
+ EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0));
+
+ // Verify the returned filter string for an image object with a single filter.
+ obj = FPDFPage_GetObject(page, 33);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ ASSERT_EQ(1, FPDFImageObj_GetImageFilterCount(obj));
+ unsigned long len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
+ std::vector<char> buf(len);
+ static constexpr char kFlateDecode[] = "FlateDecode";
+ EXPECT_EQ(sizeof(kFlateDecode),
+ FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
+ EXPECT_STREQ(kFlateDecode, buf.data());
+ EXPECT_EQ(0u, FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0));
+
+ // Verify all the filters for an image object with a list of filters.
+ obj = FPDFPage_GetObject(page, 38);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ ASSERT_EQ(2, FPDFImageObj_GetImageFilterCount(obj));
+ len = FPDFImageObj_GetImageFilter(obj, 0, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ static constexpr char kASCIIHexDecode[] = "ASCIIHexDecode";
+ EXPECT_EQ(sizeof(kASCIIHexDecode),
+ FPDFImageObj_GetImageFilter(obj, 0, buf.data(), len));
+ EXPECT_STREQ(kASCIIHexDecode, buf.data());
+
+ len = FPDFImageObj_GetImageFilter(obj, 1, nullptr, 0);
+ buf.clear();
+ buf.resize(len);
+ static constexpr char kDCTDecode[] = "DCTDecode";
+ EXPECT_EQ(sizeof(kDCTDecode),
+ FPDFImageObj_GetImageFilter(obj, 1, buf.data(), len));
+ EXPECT_STREQ(kDCTDecode, buf.data());
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFEditEmbeddertest, GetImageMetadata) {
+ ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+
+ // Check that getting the metadata of a null object would fail.
+ FPDF_IMAGEOBJ_METADATA metadata;
+ EXPECT_FALSE(FPDFImageObj_GetImageMetadata(nullptr, page, &metadata));
+
+ // Check that receiving the metadata with a null metadata object would fail.
+ FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 35);
+ EXPECT_FALSE(FPDFImageObj_GetImageMetadata(obj, page, nullptr));
+
+ // Check that when retrieving an image object's metadata without passing in
+ // |page|, all values are correct, with the last two being default values.
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, nullptr, &metadata));
+ EXPECT_EQ(7, metadata.marked_content_id);
+ EXPECT_EQ(92u, metadata.width);
+ EXPECT_EQ(68u, metadata.height);
+ EXPECT_NEAR(96.000000, metadata.horizontal_dpi, 0.001);
+ EXPECT_NEAR(96.000000, metadata.vertical_dpi, 0.001);
+ EXPECT_EQ(0u, metadata.bits_per_pixel);
+ EXPECT_EQ(FPDF_COLORSPACE_UNKNOWN, metadata.colorspace);
+
+ // Verify the metadata of a bitmap image with indexed colorspace.
+ ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
+ EXPECT_EQ(7, metadata.marked_content_id);
+ EXPECT_EQ(92u, metadata.width);
+ EXPECT_EQ(68u, metadata.height);
+ EXPECT_NEAR(96.000000, metadata.horizontal_dpi, 0.001);
+ EXPECT_NEAR(96.000000, metadata.vertical_dpi, 0.001);
+ EXPECT_EQ(1u, metadata.bits_per_pixel);
+ EXPECT_EQ(FPDF_COLORSPACE_INDEXED, metadata.colorspace);
+
+ // Verify the metadata of an image with RGB colorspace.
+ obj = FPDFPage_GetObject(page, 37);
+ ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
+ ASSERT_TRUE(FPDFImageObj_GetImageMetadata(obj, page, &metadata));
+ EXPECT_EQ(9, metadata.marked_content_id);
+ EXPECT_EQ(126u, metadata.width);
+ EXPECT_EQ(106u, metadata.height);
+ EXPECT_NEAR(162.173752, metadata.horizontal_dpi, 0.001);
+ EXPECT_NEAR(162.555878, metadata.vertical_dpi, 0.001);
+ EXPECT_EQ(24u, metadata.bits_per_pixel);
+ EXPECT_EQ(FPDF_COLORSPACE_DEVICERGB, metadata.colorspace);
+
+ UnloadPage(page);
}
diff --git a/fpdfsdk/fpdfeditimg.cpp b/fpdfsdk/fpdfeditimg.cpp
index 56875e2..0d7ba56 100644
--- a/fpdfsdk/fpdfeditimg.cpp
+++ b/fpdfsdk/fpdfeditimg.cpp
@@ -9,97 +9,296 @@
#include "core/fpdfapi/cpdf_modulemgr.h"
#include "core/fpdfapi/page/cpdf_image.h"
#include "core/fpdfapi/page/cpdf_imageobject.h"
+#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/page/cpdf_pageobject.h"
+#include "core/fpdfapi/parser/cpdf_array.h"
+#include "core/fpdfapi/parser/cpdf_name.h"
+#include "core/fpdfapi/render/cpdf_dibsource.h"
#include "fpdfsdk/fsdk_define.h"
#include "third_party/base/ptr_util.h"
-DLLEXPORT FPDF_PAGEOBJECT STDCALL
-FPDFPageObj_NewImgeObj(FPDF_DOCUMENT document) {
- CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
- if (!pDoc)
- return nullptr;
+namespace {
- CPDF_ImageObject* pImageObj = new CPDF_ImageObject;
- pImageObj->SetOwnedImage(pdfium::MakeUnique<CPDF_Image>(pDoc));
- return pImageObj;
-}
+// These checks ensure the consistency of colorspace values across core/ and
+// public/.
+static_assert(PDFCS_DEVICEGRAY == FPDF_COLORSPACE_DEVICEGRAY,
+ "PDFCS_DEVICEGRAY value mismatch");
+static_assert(PDFCS_DEVICERGB == FPDF_COLORSPACE_DEVICERGB,
+ "PDFCS_DEVICERGB value mismatch");
+static_assert(PDFCS_DEVICECMYK == FPDF_COLORSPACE_DEVICECMYK,
+ "PDFCS_DEVICECMYK value mismatch");
+static_assert(PDFCS_CALGRAY == FPDF_COLORSPACE_CALGRAY,
+ "PDFCS_CALGRAY value mismatch");
+static_assert(PDFCS_CALRGB == FPDF_COLORSPACE_CALRGB,
+ "PDFCS_CALRGB value mismatch");
+static_assert(PDFCS_LAB == FPDF_COLORSPACE_LAB, "PDFCS_LAB value mismatch");
+static_assert(PDFCS_ICCBASED == FPDF_COLORSPACE_ICCBASED,
+ "PDFCS_ICCBASED value mismatch");
+static_assert(PDFCS_SEPARATION == FPDF_COLORSPACE_SEPARATION,
+ "PDFCS_SEPARATION value mismatch");
+static_assert(PDFCS_DEVICEN == FPDF_COLORSPACE_DEVICEN,
+ "PDFCS_DEVICEN value mismatch");
+static_assert(PDFCS_INDEXED == FPDF_COLORSPACE_INDEXED,
+ "PDFCS_INDEXED value mismatch");
+static_assert(PDFCS_PATTERN == FPDF_COLORSPACE_PATTERN,
+ "PDFCS_PATTERN value mismatch");
-FPDF_BOOL FPDFImageObj_LoadJpegHelper(FPDF_PAGE* pages,
- int nCount,
- FPDF_PAGEOBJECT image_object,
- FPDF_FILEACCESS* fileAccess,
- bool inlineJpeg) {
- if (!image_object || !fileAccess || !pages)
+bool LoadJpegHelper(FPDF_PAGE* pages,
+ int nCount,
+ FPDF_PAGEOBJECT image_object,
+ FPDF_FILEACCESS* fileAccess,
+ bool inlineJpeg) {
+ if (!image_object || !fileAccess)
return false;
- CFX_RetainPtr<IFX_SeekableReadStream> pFile =
- MakeSeekableReadStream(fileAccess);
- CPDF_ImageObject* pImgObj = reinterpret_cast<CPDF_ImageObject*>(image_object);
- for (int index = 0; index < nCount; index++) {
- CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
- if (pPage)
- pImgObj->GetImage()->ResetCache(pPage, nullptr);
+ RetainPtr<IFX_SeekableReadStream> pFile = MakeSeekableReadStream(fileAccess);
+ CPDF_ImageObject* pImgObj = static_cast<CPDF_ImageObject*>(image_object);
+
+ if (pages) {
+ for (int index = 0; index < nCount; index++) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
+ if (pPage)
+ pImgObj->GetImage()->ResetCache(pPage, nullptr);
+ }
}
if (inlineJpeg)
pImgObj->GetImage()->SetJpegImageInline(pFile);
else
pImgObj->GetImage()->SetJpegImage(pFile);
-
+ pImgObj->SetDirty(true);
return true;
}
-DLLEXPORT FPDF_BOOL STDCALL
+} // namespace
+
+FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
+FPDFPageObj_NewImageObj(FPDF_DOCUMENT document) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc)
+ return nullptr;
+
+ auto pImageObj = pdfium::MakeUnique<CPDF_ImageObject>();
+ pImageObj->SetImage(pdfium::MakeRetain<CPDF_Image>(pDoc));
+ return pImageObj.release();
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages,
int nCount,
FPDF_PAGEOBJECT image_object,
FPDF_FILEACCESS* fileAccess) {
- return FPDFImageObj_LoadJpegHelper(pages, nCount, image_object, fileAccess,
- false);
+ return LoadJpegHelper(pages, nCount, image_object, fileAccess, false);
}
-DLLEXPORT FPDF_BOOL STDCALL
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages,
int nCount,
FPDF_PAGEOBJECT image_object,
FPDF_FILEACCESS* fileAccess) {
- return FPDFImageObj_LoadJpegHelper(pages, nCount, image_object, fileAccess,
- true);
+ return LoadJpegHelper(pages, nCount, image_object, fileAccess, true);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object,
- double a,
- double b,
- double c,
- double d,
- double e,
- double f) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object,
+ double a,
+ double b,
+ double c,
+ double d,
+ double e,
+ double f) {
if (!image_object)
return false;
- CPDF_ImageObject* pImgObj = reinterpret_cast<CPDF_ImageObject*>(image_object);
- pImgObj->set_matrix(
- CFX_Matrix(static_cast<FX_FLOAT>(a), static_cast<FX_FLOAT>(b),
- static_cast<FX_FLOAT>(c), static_cast<FX_FLOAT>(d),
- static_cast<FX_FLOAT>(e), static_cast<FX_FLOAT>(f)));
+ CPDF_ImageObject* pImgObj = static_cast<CPDF_ImageObject*>(image_object);
+ pImgObj->set_matrix(CFX_Matrix(static_cast<float>(a), static_cast<float>(b),
+ static_cast<float>(c), static_cast<float>(d),
+ static_cast<float>(e), static_cast<float>(f)));
pImgObj->CalcBoundingBox();
+ pImgObj->SetDirty(true);
return true;
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFImageObj_SetBitmap(FPDF_PAGE* pages,
- int nCount,
- FPDF_PAGEOBJECT image_object,
- FPDF_BITMAP bitmap) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFImageObj_SetBitmap(FPDF_PAGE* pages,
+ int nCount,
+ FPDF_PAGEOBJECT image_object,
+ FPDF_BITMAP bitmap) {
if (!image_object || !bitmap || !pages)
return false;
- CPDF_ImageObject* pImgObj = reinterpret_cast<CPDF_ImageObject*>(image_object);
+ CPDF_ImageObject* pImgObj = static_cast<CPDF_ImageObject*>(image_object);
for (int index = 0; index < nCount; index++) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
if (pPage)
pImgObj->GetImage()->ResetCache(pPage, nullptr);
}
- pImgObj->GetImage()->SetImage(reinterpret_cast<CFX_DIBitmap*>(bitmap));
+ RetainPtr<CFX_DIBitmap> holder(CFXBitmapFromFPDFBitmap(bitmap));
+ pImgObj->GetImage()->SetImage(holder);
pImgObj->CalcBoundingBox();
+ pImgObj->SetDirty(true);
+ return true;
+}
+
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
+FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object) {
+ CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
+ if (!pObj || !pObj->IsImage())
+ return nullptr;
+
+ RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
+ if (!pImg)
+ return nullptr;
+
+ RetainPtr<CFX_DIBSource> pSource = pImg->LoadDIBSource();
+ if (!pSource)
+ return nullptr;
+
+ RetainPtr<CFX_DIBitmap> pBitmap;
+ // If the source image has a representation of 1 bit per pixel, then convert
+ // it to a grayscale bitmap having 1 byte per pixel, since bitmaps have no
+ // concept of bits. Otherwise, convert the source image to a bitmap directly,
+ // retaining its color representation.
+ if (pSource->GetBPP() == 1)
+ pBitmap = pSource->CloneConvert(FXDIB_8bppRgb);
+ else
+ pBitmap = pSource->Clone(nullptr);
+
+ return pBitmap.Leak();
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object,
+ void* buffer,
+ unsigned long buflen) {
+ CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
+ if (!pObj || !pObj->IsImage())
+ return 0;
+
+ RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
+ if (!pImg)
+ return 0;
+
+ CPDF_Stream* pImgStream = pImg->GetStream();
+ if (!pImgStream)
+ return 0;
+
+ return DecodeStreamMaybeCopyAndReturnLength(pImgStream, buffer, buflen);
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object,
+ void* buffer,
+ unsigned long buflen) {
+ CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
+ if (!pObj || !pObj->IsImage())
+ return 0;
+
+ RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
+ if (!pImg)
+ return 0;
+
+ CPDF_Stream* pImgStream = pImg->GetStream();
+ if (!pImgStream)
+ return 0;
+
+ uint32_t len = pImgStream->GetRawSize();
+ if (buffer && buflen >= len)
+ memcpy(buffer, pImgStream->GetRawData(), len);
+
+ return len;
+}
+
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object) {
+ CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
+ if (!pObj || !pObj->IsImage())
+ return 0;
+
+ RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
+ if (!pImg)
+ return 0;
+
+ CPDF_Dictionary* pDict = pImg->GetDict();
+ CPDF_Object* pFilter = pDict ? pDict->GetDirectObjectFor("Filter") : nullptr;
+ if (!pFilter)
+ return 0;
+
+ if (pFilter->IsArray())
+ return pFilter->AsArray()->GetCount();
+ if (pFilter->IsName())
+ return 1;
+
+ return 0;
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object,
+ int index,
+ void* buffer,
+ unsigned long buflen) {
+ if (index < 0 || index >= FPDFImageObj_GetImageFilterCount(image_object))
+ return 0;
+
+ CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
+ CPDF_Object* pFilter =
+ pObj->AsImage()->GetImage()->GetDict()->GetDirectObjectFor("Filter");
+ ByteString bsFilter;
+ if (pFilter->IsName())
+ bsFilter = pFilter->AsName()->GetString();
+ else
+ bsFilter = pFilter->AsArray()->GetStringAt(index);
+
+ unsigned long len = bsFilter.GetLength() + 1;
+ if (buffer && len <= buflen)
+ memcpy(buffer, bsFilter.c_str(), len);
+ return len;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object,
+ FPDF_PAGE page,
+ FPDF_IMAGEOBJ_METADATA* metadata) {
+ CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
+ if (!pObj || !pObj->IsImage() || !metadata)
+ return false;
+
+ RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
+ if (!pImg)
+ return false;
+
+ metadata->marked_content_id = pObj->m_ContentMark.GetMarkedContentID();
+
+ const int nPixelWidth = pImg->GetPixelWidth();
+ const int nPixelHeight = pImg->GetPixelHeight();
+ metadata->width = nPixelWidth;
+ metadata->height = nPixelHeight;
+
+ const float nWidth = pObj->m_Right - pObj->m_Left;
+ const float nHeight = pObj->m_Top - pObj->m_Bottom;
+ constexpr int nPointsPerInch = 72;
+ if (nWidth != 0 && nHeight != 0) {
+ metadata->horizontal_dpi = nPixelWidth / nWidth * nPointsPerInch;
+ metadata->vertical_dpi = nPixelHeight / nHeight * nPointsPerInch;
+ }
+
+ metadata->bits_per_pixel = 0;
+ metadata->colorspace = FPDF_COLORSPACE_UNKNOWN;
+
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage || !pPage->m_pDocument.Get() || !pImg->GetStream())
+ return true;
+
+ auto pSource = pdfium::MakeRetain<CPDF_DIBSource>();
+ if (!pSource->StartLoadDIBSource(pPage->m_pDocument.Get(), pImg->GetStream(),
+ false, nullptr,
+ pPage->m_pPageResources.Get())) {
+ return true;
+ }
+
+ metadata->bits_per_pixel = pSource->GetBPP();
+ if (pSource->GetColorSpace())
+ metadata->colorspace = pSource->GetColorSpace()->GetFamily();
+
return true;
}
diff --git a/fpdfsdk/fpdfeditimg_unittest.cpp b/fpdfsdk/fpdfeditimg_unittest.cpp
index ae4af25..fcc081a 100644
--- a/fpdfsdk/fpdfeditimg_unittest.cpp
+++ b/fpdfsdk/fpdfeditimg_unittest.cpp
@@ -8,10 +8,7 @@
#include "testing/gtest/include/gtest/gtest.h"
class PDFEditTest : public testing::Test {
- void SetUp() override {
- CPDF_ModuleMgr* module_mgr = CPDF_ModuleMgr::Get();
- module_mgr->InitPageModule();
- }
+ void SetUp() override { CPDF_ModuleMgr::Get()->Init(); }
void TearDown() override { CPDF_ModuleMgr::Destroy(); }
};
@@ -19,40 +16,40 @@
TEST_F(PDFEditTest, InsertObjectWithInvalidPage) {
FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
FPDF_PAGE page = FPDFPage_New(doc, 0, 100, 100);
- EXPECT_EQ(0, FPDFPage_CountObject(page));
+ EXPECT_EQ(0, FPDFPage_CountObjects(page));
FPDFPage_InsertObject(nullptr, nullptr);
- EXPECT_EQ(0, FPDFPage_CountObject(page));
+ EXPECT_EQ(0, FPDFPage_CountObjects(page));
FPDFPage_InsertObject(page, nullptr);
- EXPECT_EQ(0, FPDFPage_CountObject(page));
+ EXPECT_EQ(0, FPDFPage_CountObjects(page));
- FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImgeObj(doc);
+ FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImageObj(doc);
FPDFPage_InsertObject(nullptr, page_image);
- EXPECT_EQ(0, FPDFPage_CountObject(page));
+ EXPECT_EQ(0, FPDFPage_CountObjects(page));
FPDF_ClosePage(page);
FPDF_CloseDocument(doc);
}
-TEST_F(PDFEditTest, NewImgeObj) {
+TEST_F(PDFEditTest, NewImageObj) {
FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
FPDF_PAGE page = FPDFPage_New(doc, 0, 100, 100);
- EXPECT_EQ(0, FPDFPage_CountObject(page));
+ EXPECT_EQ(0, FPDFPage_CountObjects(page));
- FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImgeObj(doc);
+ FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImageObj(doc);
FPDFPage_InsertObject(page, page_image);
- EXPECT_EQ(1, FPDFPage_CountObject(page));
+ EXPECT_EQ(1, FPDFPage_CountObjects(page));
EXPECT_TRUE(FPDFPage_GenerateContent(page));
FPDF_ClosePage(page);
FPDF_CloseDocument(doc);
}
-TEST_F(PDFEditTest, NewImgeObjGenerateContent) {
+TEST_F(PDFEditTest, NewImageObjGenerateContent) {
FPDF_DOCUMENT doc = FPDF_CreateNewDocument();
FPDF_PAGE page = FPDFPage_New(doc, 0, 100, 100);
- EXPECT_EQ(0, FPDFPage_CountObject(page));
+ EXPECT_EQ(0, FPDFPage_CountObjects(page));
constexpr int kBitmapSize = 50;
FPDF_BITMAP bitmap = FPDFBitmap_Create(kBitmapSize, kBitmapSize, 0);
@@ -60,12 +57,12 @@
EXPECT_EQ(kBitmapSize, FPDFBitmap_GetWidth(bitmap));
EXPECT_EQ(kBitmapSize, FPDFBitmap_GetHeight(bitmap));
- FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImgeObj(doc);
+ FPDF_PAGEOBJECT page_image = FPDFPageObj_NewImageObj(doc);
ASSERT_TRUE(FPDFImageObj_SetBitmap(&page, 0, page_image, bitmap));
ASSERT_TRUE(
FPDFImageObj_SetMatrix(page_image, kBitmapSize, 0, 0, kBitmapSize, 0, 0));
FPDFPage_InsertObject(page, page_image);
- EXPECT_EQ(1, FPDFPage_CountObject(page));
+ EXPECT_EQ(1, FPDFPage_CountObjects(page));
EXPECT_TRUE(FPDFPage_GenerateContent(page));
FPDFBitmap_Destroy(bitmap);
diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp
index 63740ba..a032bf6 100644
--- a/fpdfsdk/fpdfeditpage.cpp
+++ b/fpdfsdk/fpdfeditpage.cpp
@@ -26,6 +26,7 @@
#include "core/fpdfdoc/cpdf_annotlist.h"
#include "fpdfsdk/fsdk_define.h"
#include "public/fpdf_formfill.h"
+#include "third_party/base/logging.h"
#include "third_party/base/stl_util.h"
#ifdef PDF_ENABLE_XFA
@@ -33,7 +34,7 @@
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
#endif // PDF_ENABLE_XFA
-#if _FX_OS_ == _FX_ANDROID_
+#if _FX_OS_ == _FX_OS_ANDROID_
#include <time.h>
#else
#include <ctime>
@@ -60,107 +61,7 @@
return pObject && !pObject->GetString().Compare("Page");
}
-} // namespace
-
-DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_CreateNewDocument() {
- CPDF_Document* pDoc = new CPDF_Document(nullptr);
- pDoc->CreateNewDoc();
- time_t currentTime;
-
- CFX_ByteString DateStr;
-
- if (FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) {
- if (-1 != time(¤tTime)) {
- tm* pTM = localtime(¤tTime);
- if (pTM) {
- DateStr.Format("D:%04d%02d%02d%02d%02d%02d", pTM->tm_year + 1900,
- pTM->tm_mon + 1, pTM->tm_mday, pTM->tm_hour, pTM->tm_min,
- pTM->tm_sec);
- }
- }
- }
-
- CPDF_Dictionary* pInfoDict = nullptr;
- pInfoDict = pDoc->GetInfo();
- if (pInfoDict) {
- if (FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
- pInfoDict->SetNewFor<CPDF_String>("CreationDate", DateStr, false);
- pInfoDict->SetNewFor<CPDF_String>("Creator", L"PDFium");
- }
-
- return FPDFDocumentFromCPDFDocument(pDoc);
-}
-
-DLLEXPORT void STDCALL FPDFPage_Delete(FPDF_DOCUMENT document, int page_index) {
- if (UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document))
- pDoc->DeletePage(page_index);
-}
-
-DLLEXPORT FPDF_PAGE STDCALL FPDFPage_New(FPDF_DOCUMENT document,
- int page_index,
- double width,
- double height) {
- CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
- if (!pDoc)
- return nullptr;
-
- page_index = std::min(std::max(page_index, 0), pDoc->GetPageCount());
- CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(page_index);
- if (!pPageDict)
- return nullptr;
-
- CPDF_Array* pMediaBoxArray = pPageDict->SetNewFor<CPDF_Array>("MediaBox");
- pMediaBoxArray->AddNew<CPDF_Number>(0);
- pMediaBoxArray->AddNew<CPDF_Number>(0);
- pMediaBoxArray->AddNew<CPDF_Number>(static_cast<FX_FLOAT>(width));
- pMediaBoxArray->AddNew<CPDF_Number>(static_cast<FX_FLOAT>(height));
- pPageDict->SetNewFor<CPDF_Number>("Rotate", 0);
- pPageDict->SetNewFor<CPDF_Dictionary>("Resources");
-
-#ifdef PDF_ENABLE_XFA
- CPDFXFA_Page* pPage =
- new CPDFXFA_Page(static_cast<CPDFXFA_Context*>(document), page_index);
- pPage->LoadPDFPage(pPageDict);
-#else // PDF_ENABLE_XFA
- CPDF_Page* pPage = new CPDF_Page(pDoc, pPageDict, true);
- pPage->ParseContent();
-#endif // PDF_ENABLE_XFA
-
- return pPage;
-}
-
-DLLEXPORT int STDCALL FPDFPage_GetRotation(FPDF_PAGE page) {
- CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
- if (!IsPageObject(pPage))
- return -1;
-
- CPDF_Dictionary* pDict = pPage->m_pFormDict;
- while (pDict) {
- if (pDict->KeyExist("Rotate")) {
- CPDF_Object* pRotateObj = pDict->GetObjectFor("Rotate")->GetDirect();
- return pRotateObj ? pRotateObj->GetInteger() / 90 : 0;
- }
- if (!pDict->KeyExist("Parent"))
- break;
-
- pDict = ToDictionary(pDict->GetObjectFor("Parent")->GetDirect());
- }
-
- return 0;
-}
-
-DLLEXPORT void STDCALL FPDFPage_InsertObject(FPDF_PAGE page,
- FPDF_PAGEOBJECT page_obj) {
- CPDF_PageObject* pPageObj = reinterpret_cast<CPDF_PageObject*>(page_obj);
- if (!pPageObj)
- return;
-
- std::unique_ptr<CPDF_PageObject> pPageObjHolder(pPageObj);
- CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
- if (!IsPageObject(pPage))
- return;
-
- pPage->GetPageObjectList()->push_back(std::move(pPageObjHolder));
+void CalcBoundingBox(CPDF_PageObject* pPageObj) {
switch (pPageObj->GetType()) {
case CPDF_PageObject::TEXT: {
break;
@@ -186,38 +87,135 @@
break;
}
default: {
- ASSERT(false);
+ NOTREACHED();
break;
}
}
}
-DLLEXPORT int STDCALL FPDFPage_CountObject(FPDF_PAGE page) {
+} // namespace
+
+FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument() {
+ auto pDoc = pdfium::MakeUnique<CPDF_Document>(nullptr);
+ pDoc->CreateNewDoc();
+
+ time_t currentTime;
+ ByteString DateStr;
+ if (FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS)) {
+ if (time(¤tTime) != -1) {
+ tm* pTM = localtime(¤tTime);
+ if (pTM) {
+ DateStr = ByteString::Format(
+ "D:%04d%02d%02d%02d%02d%02d", pTM->tm_year + 1900, pTM->tm_mon + 1,
+ pTM->tm_mday, pTM->tm_hour, pTM->tm_min, pTM->tm_sec);
+ }
+ }
+ }
+
+ CPDF_Dictionary* pInfoDict = pDoc->GetInfo();
+ if (pInfoDict) {
+ if (FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
+ pInfoDict->SetNewFor<CPDF_String>("CreationDate", DateStr, false);
+ pInfoDict->SetNewFor<CPDF_String>("Creator", L"PDFium");
+ }
+
+ // Caller takes ownership of pDoc.
+ return FPDFDocumentFromCPDFDocument(pDoc.release());
+}
+
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_Delete(FPDF_DOCUMENT document,
+ int page_index) {
+ if (UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document))
+ pDoc->DeletePage(page_index);
+}
+
+FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDFPage_New(FPDF_DOCUMENT document,
+ int page_index,
+ double width,
+ double height) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc)
+ return nullptr;
+
+ page_index = pdfium::clamp(page_index, 0, pDoc->GetPageCount());
+ CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(page_index);
+ if (!pPageDict)
+ return nullptr;
+
+ CPDF_Array* pMediaBoxArray = pPageDict->SetNewFor<CPDF_Array>("MediaBox");
+ pMediaBoxArray->AddNew<CPDF_Number>(0);
+ pMediaBoxArray->AddNew<CPDF_Number>(0);
+ pMediaBoxArray->AddNew<CPDF_Number>(static_cast<float>(width));
+ pMediaBoxArray->AddNew<CPDF_Number>(static_cast<float>(height));
+ pPageDict->SetNewFor<CPDF_Number>("Rotate", 0);
+ pPageDict->SetNewFor<CPDF_Dictionary>("Resources");
+
+#ifdef PDF_ENABLE_XFA
+ auto pXFAPage = pdfium::MakeRetain<CPDFXFA_Page>(
+ static_cast<CPDFXFA_Context*>(document), page_index);
+ pXFAPage->LoadPDFPage(pPageDict);
+ return pXFAPage.Leak(); // Caller takes ownership.
+#else // PDF_ENABLE_XFA
+ auto pPage = pdfium::MakeUnique<CPDF_Page>(pDoc, pPageDict, true);
+ pPage->ParseContent();
+ return pPage.release(); // Caller takes ownership.
+#endif // PDF_ENABLE_XFA
+}
+
+FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetRotation(FPDF_PAGE page) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ return IsPageObject(pPage) ? pPage->GetPageRotation() : -1;
+}
+
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertObject(FPDF_PAGE page,
+ FPDF_PAGEOBJECT page_obj) {
+ CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_obj);
+ if (!pPageObj)
+ return;
+
+ std::unique_ptr<CPDF_PageObject> pPageObjHolder(pPageObj);
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!IsPageObject(pPage))
+ return;
+ pPageObj->SetDirty(true);
+ pPage->GetPageObjectList()->push_back(std::move(pPageObjHolder));
+ CalcBoundingBox(pPageObj);
+}
+
+FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObject(FPDF_PAGE page) {
+ return FPDFPage_CountObjects(page);
+}
+
+FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObjects(FPDF_PAGE page) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!IsPageObject(pPage))
return -1;
return pdfium::CollectionSize<int>(*pPage->GetPageObjectList());
}
-DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPage_GetObject(FPDF_PAGE page,
- int index) {
+FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPage_GetObject(FPDF_PAGE page,
+ int index) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!IsPageObject(pPage))
return nullptr;
return pPage->GetPageObjectList()->GetPageObjectByIndex(index);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFPage_HasTransparency(FPDF_PAGE page) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_HasTransparency(FPDF_PAGE page) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
return pPage && pPage->BackgroundAlphaNeeded();
}
-DLLEXPORT FPDF_BOOL STDCALL
+FPDF_EXPORT void FPDF_CALLCONV FPDFPageObj_Destroy(FPDF_PAGEOBJECT page_obj) {
+ delete CPDFPageObjectFromFPDFPageObject(page_obj);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject) {
if (!pageObject)
return false;
- CPDF_PageObject* pPageObj = reinterpret_cast<CPDF_PageObject*>(pageObject);
+ CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(pageObject);
int blend_type = pPageObj->m_GeneralState.GetBlendType();
if (blend_type != FXDIB_BLEND_NORMAL)
return true;
@@ -237,7 +235,7 @@
if (pPageObj->IsForm()) {
const CPDF_Form* pForm = pPageObj->AsForm()->form();
if (pForm) {
- int trans = pForm->m_Transparency;
+ int trans = pForm->m_iTransparency;
if ((trans & PDFTRANS_ISOLATED) || (trans & PDFTRANS_GROUP))
return true;
}
@@ -246,7 +244,15 @@
return false;
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GenerateContent(FPDF_PAGE page) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFPageObj_GetType(FPDF_PAGEOBJECT pageObject) {
+ if (!pageObject)
+ return FPDF_PAGEOBJ_UNKNOWN;
+
+ CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(pageObject);
+ return pPageObj->GetType();
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GenerateContent(FPDF_PAGE page) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!IsPageObject(pPage))
return false;
@@ -256,29 +262,40 @@
return true;
}
-DLLEXPORT void STDCALL FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object,
- double a,
- double b,
- double c,
- double d,
- double e,
- double f) {
- CPDF_PageObject* pPageObj = reinterpret_cast<CPDF_PageObject*>(page_object);
+FPDF_EXPORT void FPDF_CALLCONV
+FPDFPageObj_Transform(FPDF_PAGEOBJECT page_object,
+ double a,
+ double b,
+ double c,
+ double d,
+ double e,
+ double f) {
+ CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object);
if (!pPageObj)
return;
- CFX_Matrix matrix((FX_FLOAT)a, (FX_FLOAT)b, (FX_FLOAT)c, (FX_FLOAT)d,
- (FX_FLOAT)e, (FX_FLOAT)f);
+ CFX_Matrix matrix((float)a, (float)b, (float)c, (float)d, (float)e, (float)f);
pPageObj->Transform(matrix);
}
-DLLEXPORT void STDCALL FPDFPage_TransformAnnots(FPDF_PAGE page,
- double a,
- double b,
- double c,
- double d,
- double e,
- double f) {
+FPDF_EXPORT void FPDF_CALLCONV
+FPDFPageObj_SetBlendMode(FPDF_PAGEOBJECT page_object,
+ FPDF_BYTESTRING blend_mode) {
+ CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object);
+ if (!pPageObj)
+ return;
+
+ pPageObj->m_GeneralState.SetBlendMode(blend_mode);
+ pPageObj->SetDirty(true);
+}
+
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_TransformAnnots(FPDF_PAGE page,
+ double a,
+ double b,
+ double c,
+ double d,
+ double e,
+ double f) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return;
@@ -286,30 +303,67 @@
CPDF_AnnotList AnnotList(pPage);
for (size_t i = 0; i < AnnotList.Count(); ++i) {
CPDF_Annot* pAnnot = AnnotList.GetAt(i);
- CFX_FloatRect rect = pAnnot->GetRect(); // transformAnnots Rectangle
- CFX_Matrix matrix((FX_FLOAT)a, (FX_FLOAT)b, (FX_FLOAT)c, (FX_FLOAT)d,
- (FX_FLOAT)e, (FX_FLOAT)f);
- matrix.TransformRect(rect);
+ CFX_Matrix matrix((float)a, (float)b, (float)c, (float)d, (float)e,
+ (float)f);
+ CFX_FloatRect rect = matrix.TransformRect(pAnnot->GetRect());
- CPDF_Array* pRectArray = pAnnot->GetAnnotDict()->GetArrayFor("Rect");
- if (!pRectArray)
- pRectArray = pAnnot->GetAnnotDict()->SetNewFor<CPDF_Array>("Rect");
+ CPDF_Dictionary* pAnnotDict = pAnnot->GetAnnotDict();
+ CPDF_Array* pRectArray = pAnnotDict->GetArrayFor("Rect");
+ if (pRectArray)
+ pRectArray->Clear();
+ else
+ pRectArray = pAnnotDict->SetNewFor<CPDF_Array>("Rect");
- pRectArray->SetNewAt<CPDF_Number>(0, rect.left);
- pRectArray->SetNewAt<CPDF_Number>(1, rect.bottom);
- pRectArray->SetNewAt<CPDF_Number>(2, rect.right);
- pRectArray->SetNewAt<CPDF_Number>(3, rect.top);
+ pRectArray->AddNew<CPDF_Number>(rect.left);
+ pRectArray->AddNew<CPDF_Number>(rect.bottom);
+ pRectArray->AddNew<CPDF_Number>(rect.right);
+ pRectArray->AddNew<CPDF_Number>(rect.top);
// TODO(unknown): Transform AP's rectangle
}
}
-DLLEXPORT void STDCALL FPDFPage_SetRotation(FPDF_PAGE page, int rotate) {
+FPDF_EXPORT void FPDF_CALLCONV FPDFPage_SetRotation(FPDF_PAGE page,
+ int rotate) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!IsPageObject(pPage))
return;
- CPDF_Dictionary* pDict = pPage->m_pFormDict;
rotate %= 4;
- pDict->SetNewFor<CPDF_Number>("Rotate", rotate * 90);
+ pPage->m_pFormDict->SetNewFor<CPDF_Number>("Rotate", rotate * 90);
+}
+
+FPDF_BOOL FPDFPageObj_SetFillColor(FPDF_PAGEOBJECT page_object,
+ unsigned int R,
+ unsigned int G,
+ unsigned int B,
+ unsigned int A) {
+ if (!page_object || R > 255 || G > 255 || B > 255 || A > 255)
+ return false;
+
+ float rgb[3] = {R / 255.f, G / 255.f, B / 255.f};
+ auto* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object);
+ pPageObj->m_GeneralState.SetFillAlpha(A / 255.f);
+ pPageObj->m_ColorState.SetFillColor(
+ CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);
+ pPageObj->SetDirty(true);
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPageObj_GetBounds(FPDF_PAGEOBJECT pageObject,
+ float* left,
+ float* bottom,
+ float* right,
+ float* top) {
+ if (!pageObject)
+ return false;
+
+ CPDF_PageObject* pPageObj = CPDFPageObjectFromFPDFPageObject(pageObject);
+ CFX_FloatRect bbox = pPageObj->GetRect();
+ *left = bbox.left;
+ *bottom = bbox.bottom;
+ *right = bbox.right;
+ *top = bbox.top;
+ return true;
}
diff --git a/fpdfsdk/fpdfeditpath.cpp b/fpdfsdk/fpdfeditpath.cpp
index 074f083..a291987 100644
--- a/fpdfsdk/fpdfeditpath.cpp
+++ b/fpdfsdk/fpdfeditpath.cpp
@@ -2,125 +2,210 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <vector>
+
#include "public/fpdf_edit.h"
#include "core/fpdfapi/page/cpdf_path.h"
#include "core/fpdfapi/page/cpdf_pathobject.h"
#include "core/fxcrt/fx_system.h"
+#include "fpdfsdk/fsdk_define.h"
+#include "third_party/base/ptr_util.h"
-DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewPath(float x, float y) {
- CPDF_PathObject* pPathObj = new CPDF_PathObject;
+// These checks are here because core/ and public/ cannot depend on each other.
+static_assert(CFX_GraphStateData::LineCapButt == FPDF_LINECAP_BUTT,
+ "CFX_GraphStateData::LineCapButt value mismatch");
+static_assert(CFX_GraphStateData::LineCapRound == FPDF_LINECAP_ROUND,
+ "CFX_GraphStateData::LineCapRound value mismatch");
+static_assert(CFX_GraphStateData::LineCapSquare ==
+ FPDF_LINECAP_PROJECTING_SQUARE,
+ "CFX_GraphStateData::LineCapSquare value mismatch");
+
+static_assert(CFX_GraphStateData::LineJoinMiter == FPDF_LINEJOIN_MITER,
+ "CFX_GraphStateData::LineJoinMiter value mismatch");
+static_assert(CFX_GraphStateData::LineJoinRound == FPDF_LINEJOIN_ROUND,
+ "CFX_GraphStateData::LineJoinRound value mismatch");
+static_assert(CFX_GraphStateData::LineJoinBevel == FPDF_LINEJOIN_BEVEL,
+ "CFX_GraphStateData::LineJoinBevel value mismatch");
+
+static_assert(static_cast<int>(FXPT_TYPE::LineTo) == FPDF_SEGMENT_LINETO,
+ "FXPT_TYPE::LineTo value mismatch");
+static_assert(static_cast<int>(FXPT_TYPE::BezierTo) == FPDF_SEGMENT_BEZIERTO,
+ "FXPT_TYPE::BezierTo value mismatch");
+static_assert(static_cast<int>(FXPT_TYPE::MoveTo) == FPDF_SEGMENT_MOVETO,
+ "FXPT_TYPE::MoveTo value mismatch");
+
+FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPageObj_CreateNewPath(float x,
+ float y) {
+ auto pPathObj = pdfium::MakeUnique<CPDF_PathObject>();
pPathObj->m_Path.AppendPoint(CFX_PointF(x, y), FXPT_TYPE::MoveTo, false);
pPathObj->DefaultStates();
- return pPathObj;
+ return pPathObj.release(); // Caller takes ownership.
}
-DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewRect(float x,
- float y,
- float w,
- float h) {
- CPDF_PathObject* pPathObj = new CPDF_PathObject;
+FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPageObj_CreateNewRect(float x,
+ float y,
+ float w,
+ float h) {
+ auto pPathObj = pdfium::MakeUnique<CPDF_PathObject>();
pPathObj->m_Path.AppendRect(x, y, x + w, y + h);
pPathObj->DefaultStates();
- return pPathObj;
+ return pPathObj.release(); // Caller takes ownership.
}
-DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path,
- unsigned int R,
- unsigned int G,
- unsigned int B,
- unsigned int A) {
- if (!path || R > 255 || G > 255 || B > 255 || A > 255)
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path,
+ unsigned int R,
+ unsigned int G,
+ unsigned int B,
+ unsigned int A) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj || R > 255 || G > 255 || B > 255 || A > 255)
return false;
- auto pPathObj = reinterpret_cast<CPDF_PathObject*>(path);
+ float rgb[3] = {R / 255.f, G / 255.f, B / 255.f};
pPathObj->m_GeneralState.SetStrokeAlpha(A / 255.f);
- FX_FLOAT rgb[3] = {R / 255.f, G / 255.f, B / 255.f};
pPathObj->m_ColorState.SetStrokeColor(
CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);
+ pPathObj->SetDirty(true);
return true;
}
-DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width) {
- if (!path || width < 0.0f)
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPath_GetStrokeColor(FPDF_PAGEOBJECT path,
+ unsigned int* R,
+ unsigned int* G,
+ unsigned int* B,
+ unsigned int* A) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj || !R || !G || !B || !A)
return false;
- auto pPathObj = reinterpret_cast<CPDF_PathObject*>(path);
+ uint32_t strokeRGB = pPathObj->m_ColorState.GetStrokeRGB();
+ *R = FXSYS_GetRValue(strokeRGB);
+ *G = FXSYS_GetGValue(strokeRGB);
+ *B = FXSYS_GetBValue(strokeRGB);
+ *A = static_cast<unsigned int>(
+ (pPathObj->m_GeneralState.GetStrokeAlpha() * 255.f) + 0.5f);
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj || width < 0.0f)
+ return false;
+
pPathObj->m_GraphState.SetLineWidth(width);
+ pPathObj->SetDirty(true);
return true;
}
-DLLEXPORT FPDF_BOOL FPDFPath_SetFillColor(FPDF_PAGEOBJECT path,
- unsigned int R,
- unsigned int G,
- unsigned int B,
- unsigned int A) {
- if (!path || R > 255 || G > 255 || B > 255 || A > 255)
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_SetFillColor(FPDF_PAGEOBJECT path,
+ unsigned int R,
+ unsigned int G,
+ unsigned int B,
+ unsigned int A) {
+ return FPDFPageObj_SetFillColor(path, R, G, B, A);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_GetFillColor(FPDF_PAGEOBJECT path,
+ unsigned int* R,
+ unsigned int* G,
+ unsigned int* B,
+ unsigned int* A) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj || !R || !G || !B || !A)
return false;
- auto pPathObj = reinterpret_cast<CPDF_PathObject*>(path);
- pPathObj->m_GeneralState.SetFillAlpha(A / 255.f);
- FX_FLOAT rgb[3] = {R / 255.f, G / 255.f, B / 255.f};
- pPathObj->m_ColorState.SetFillColor(
- CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);
+ uint32_t fillRGB = pPathObj->m_ColorState.GetFillRGB();
+ *R = FXSYS_GetRValue(fillRGB);
+ *G = FXSYS_GetGValue(fillRGB);
+ *B = FXSYS_GetBValue(fillRGB);
+ *A = static_cast<unsigned int>(
+ (pPathObj->m_GeneralState.GetFillAlpha() * 255.f) + 0.5f);
return true;
}
-DLLEXPORT FPDF_BOOL FPDFPath_MoveTo(FPDF_PAGEOBJECT path, float x, float y) {
- if (!path)
+FPDF_EXPORT int FPDF_CALLCONV FPDFPath_CountSegments(FPDF_PAGEOBJECT path) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj)
+ return -1;
+ return pdfium::CollectionSize<int>(pPathObj->m_Path.GetPoints());
+}
+
+FPDF_EXPORT FPDF_PATHSEGMENT FPDF_CALLCONV
+FPDFPath_GetPathSegment(FPDF_PAGEOBJECT path, int index) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj)
+ return nullptr;
+
+ const std::vector<FX_PATHPOINT>& points = pPathObj->m_Path.GetPoints();
+ return pdfium::IndexInBounds(points, index) ? &points[index] : nullptr;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_MoveTo(FPDF_PAGEOBJECT path,
+ float x,
+ float y) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj)
return false;
- auto pPathObj = reinterpret_cast<CPDF_PathObject*>(path);
pPathObj->m_Path.AppendPoint(CFX_PointF(x, y), FXPT_TYPE::MoveTo, false);
+ pPathObj->SetDirty(true);
return true;
}
-DLLEXPORT FPDF_BOOL FPDFPath_LineTo(FPDF_PAGEOBJECT path, float x, float y) {
- if (!path)
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_LineTo(FPDF_PAGEOBJECT path,
+ float x,
+ float y) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj)
return false;
- auto pPathObj = reinterpret_cast<CPDF_PathObject*>(path);
pPathObj->m_Path.AppendPoint(CFX_PointF(x, y), FXPT_TYPE::LineTo, false);
+ pPathObj->SetDirty(true);
return true;
}
-DLLEXPORT FPDF_BOOL FPDFPath_BezierTo(FPDF_PAGEOBJECT path,
- float x1,
- float y1,
- float x2,
- float y2,
- float x3,
- float y3) {
- if (!path)
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_BezierTo(FPDF_PAGEOBJECT path,
+ float x1,
+ float y1,
+ float x2,
+ float y2,
+ float x3,
+ float y3) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj)
return false;
- auto pPathObj = reinterpret_cast<CPDF_PathObject*>(path);
pPathObj->m_Path.AppendPoint(CFX_PointF(x1, y1), FXPT_TYPE::BezierTo, false);
pPathObj->m_Path.AppendPoint(CFX_PointF(x2, y2), FXPT_TYPE::BezierTo, false);
pPathObj->m_Path.AppendPoint(CFX_PointF(x3, y3), FXPT_TYPE::BezierTo, false);
+ pPathObj->SetDirty(true);
return true;
}
-DLLEXPORT FPDF_BOOL FPDFPath_Close(FPDF_PAGEOBJECT path) {
- if (!path)
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_Close(FPDF_PAGEOBJECT path) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj)
return false;
- auto pPathObj = reinterpret_cast<CPDF_PathObject*>(path);
if (pPathObj->m_Path.GetPoints().empty())
return false;
pPathObj->m_Path.ClosePath();
+ pPathObj->SetDirty(true);
return true;
}
-DLLEXPORT FPDF_BOOL FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path,
- int fillmode,
- FPDF_BOOL stroke) {
- if (!path)
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPath_SetDrawMode(FPDF_PAGEOBJECT path,
+ int fillmode,
+ FPDF_BOOL stroke) {
+ auto* pPathObj = CPDFPathObjectFromFPDFPageObject(path);
+ if (!pPathObj)
return false;
- auto pPathObj = reinterpret_cast<CPDF_PathObject*>(path);
-
if (fillmode == FPDF_FILLMODE_ALTERNATE)
pPathObj->m_FillType = FXFILL_ALTERNATE;
else if (fillmode == FPDF_FILLMODE_WINDING)
@@ -128,5 +213,65 @@
else
pPathObj->m_FillType = 0;
pPathObj->m_bStroke = stroke != 0;
+ pPathObj->SetDirty(true);
return true;
}
+
+FPDF_EXPORT void FPDF_CALLCONV FPDFPath_SetLineJoin(FPDF_PAGEOBJECT path,
+ int line_join) {
+ if (!path)
+ return;
+ if (line_join <
+ static_cast<int>(CFX_GraphStateData::LineJoin::LineJoinMiter) ||
+ line_join >
+ static_cast<int>(CFX_GraphStateData::LineJoin::LineJoinBevel)) {
+ return;
+ }
+ auto* pPathObj = CPDFPageObjectFromFPDFPageObject(path);
+ CFX_GraphStateData::LineJoin lineJoin =
+ static_cast<CFX_GraphStateData::LineJoin>(line_join);
+ pPathObj->m_GraphState.SetLineJoin(lineJoin);
+ pPathObj->SetDirty(true);
+}
+
+FPDF_EXPORT void FPDF_CALLCONV FPDFPath_SetLineCap(FPDF_PAGEOBJECT path,
+ int line_cap) {
+ if (!path)
+ return;
+ if (line_cap < static_cast<int>(CFX_GraphStateData::LineCap::LineCapButt) ||
+ line_cap > static_cast<int>(CFX_GraphStateData::LineCap::LineCapSquare)) {
+ return;
+ }
+ auto* pPathObj = CPDFPageObjectFromFPDFPageObject(path);
+ CFX_GraphStateData::LineCap lineCap =
+ static_cast<CFX_GraphStateData::LineCap>(line_cap);
+ pPathObj->m_GraphState.SetLineCap(lineCap);
+ pPathObj->SetDirty(true);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPathSegment_GetPoint(FPDF_PATHSEGMENT segment, float* x, float* y) {
+ auto* pPathPoint = FXPathPointFromFPDFPathSegment(segment);
+ if (!pPathPoint || !x || !y)
+ return false;
+
+ *x = pPathPoint->m_Point.x;
+ *y = pPathPoint->m_Point.y;
+
+ return true;
+}
+
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFPathSegment_GetType(FPDF_PATHSEGMENT segment) {
+ auto* pPathPoint = FXPathPointFromFPDFPathSegment(segment);
+
+ return pPathPoint ? static_cast<int>(pPathPoint->m_Type)
+ : FPDF_SEGMENT_UNKNOWN;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFPathSegment_GetClose(FPDF_PATHSEGMENT segment) {
+ auto* pPathPoint = FXPathPointFromFPDFPathSegment(segment);
+
+ return pPathPoint ? pPathPoint->m_CloseFigure : false;
+}
diff --git a/fpdfsdk/fpdfeditpath_embeddertest.cpp b/fpdfsdk/fpdfeditpath_embeddertest.cpp
new file mode 100644
index 0000000..59e5dbb
--- /dev/null
+++ b/fpdfsdk/fpdfeditpath_embeddertest.cpp
@@ -0,0 +1,63 @@
+// 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.
+
+#include "core/fxcrt/fx_system.h"
+#include "public/fpdf_edit.h"
+#include "testing/embedder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/test_support.h"
+
+class FPDFEditPathEmbedderTest : public EmbedderTest {};
+
+TEST_F(FPDFEditPathEmbedderTest, VerifyCorrectColoursReturned) {
+ CreateEmptyDocument();
+ FPDF_PAGE page = FPDFPage_New(document(), 0, 612, 792);
+
+ for (size_t i = 0; i < 256; ++i) {
+ FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
+ EXPECT_TRUE(FPDFPath_SetFillColor(path, i, i, i, i));
+ EXPECT_TRUE(FPDFPath_SetStrokeColor(path, i, i, i, i));
+ EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_ALTERNATE, 0));
+ EXPECT_TRUE(FPDFPath_LineTo(path, 400, 200));
+ EXPECT_TRUE(FPDFPath_LineTo(path, 300, 100));
+ EXPECT_TRUE(FPDFPath_Close(path));
+
+ FPDFPage_InsertObject(page, path);
+ }
+
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+ page = nullptr;
+
+ OpenSavedDocument();
+ page = LoadSavedPage(0);
+ ASSERT(page);
+
+ for (size_t i = 0; i < 256; ++i) {
+ FPDF_PAGEOBJECT path = FPDFPage_GetObject(page, i);
+ ASSERT(path);
+
+ EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
+
+ unsigned int r;
+ unsigned int g;
+ unsigned int b;
+ unsigned int a;
+ FPDFPath_GetFillColor(path, &r, &g, &b, &a);
+ EXPECT_EQ(i, r);
+ EXPECT_EQ(i, g);
+ EXPECT_EQ(i, b);
+ EXPECT_EQ(i, a);
+
+ FPDFPath_GetStrokeColor(path, &r, &g, &b, &a);
+ EXPECT_EQ(i, r);
+ EXPECT_EQ(i, g);
+ EXPECT_EQ(i, b);
+ EXPECT_EQ(i, a);
+ }
+
+ CloseSavedPage(page);
+ CloseSavedDocument();
+}
diff --git a/fpdfsdk/fpdfedittext.cpp b/fpdfsdk/fpdfedittext.cpp
index 8bf0a0a..22c6266 100644
--- a/fpdfsdk/fpdfedittext.cpp
+++ b/fpdfsdk/fpdfedittext.cpp
@@ -2,11 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <map>
+#include <memory>
#include <utility>
+#include <vector>
#include "core/fpdfapi/cpdf_modulemgr.h"
#include "core/fpdfapi/font/cpdf_font.h"
#include "core/fpdfapi/font/cpdf_type1font.h"
+#include "core/fpdfapi/page/cpdf_docpagedata.h"
#include "core/fpdfapi/page/cpdf_textobject.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
@@ -15,92 +19,34 @@
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fxcrt/fx_extension.h"
#include "core/fxge/cfx_fontmgr.h"
#include "core/fxge/fx_font.h"
#include "fpdfsdk/fsdk_define.h"
#include "public/fpdf_edit.h"
-DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_NewTextObj(FPDF_DOCUMENT document,
- FPDF_BYTESTRING font,
- float font_size) {
- CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
- if (!pDoc)
- return nullptr;
+namespace {
- CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc, CFX_ByteStringC(font));
- if (!pFont)
- return nullptr;
-
- CPDF_TextObject* pTextObj = new CPDF_TextObject;
- pTextObj->m_TextState.SetFont(pFont);
- pTextObj->m_TextState.SetFontSize(font_size);
- pTextObj->DefaultStates();
- return pTextObj;
-}
-
-DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetText(FPDF_PAGEOBJECT text_object,
- FPDF_BYTESTRING text) {
- if (!text_object)
- return false;
-
- auto pTextObj = reinterpret_cast<CPDF_TextObject*>(text_object);
- pTextObj->SetText(CFX_ByteString(text));
- return true;
-}
-
-DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadType1Font(FPDF_DOCUMENT document,
- const uint8_t* data,
- uint32_t size) {
- CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
- if (!pDoc || !data || size == 0)
- return nullptr;
-
- auto pFont = pdfium::MakeUnique<CFX_Font>();
-
- // TODO(npm): Maybe use FT_Get_X11_Font_Format to check format?
- if (!pFont->LoadEmbedded(data, size))
- return nullptr;
-
- CPDF_Dictionary* fontDict = pDoc->NewIndirect<CPDF_Dictionary>();
- fontDict->SetNewFor<CPDF_Name>("Type", "Font");
- fontDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
- CFX_ByteString name = pFont->GetFaceName();
- if (name.IsEmpty())
- name = "Unnamed";
- fontDict->SetNewFor<CPDF_Name>("BaseFont", name);
-
- uint32_t glyphIndex;
- int currentChar = FXFT_Get_First_Char(pFont->GetFace(), &glyphIndex);
- fontDict->SetNewFor<CPDF_Number>("FirstChar", currentChar);
- int nextChar;
- CPDF_Array* widthsArray = pDoc->NewIndirect<CPDF_Array>();
- while (true) {
- int width = pFont->GetGlyphWidth(glyphIndex);
- widthsArray->AddNew<CPDF_Number>(width);
- nextChar = FXFT_Get_Next_Char(pFont->GetFace(), currentChar, &glyphIndex);
- if (glyphIndex == 0)
- break;
- for (int i = currentChar + 1; i < nextChar; i++)
- widthsArray->AddNew<CPDF_Number>(0);
- currentChar = nextChar;
- }
- fontDict->SetNewFor<CPDF_Number>("LastChar", currentChar);
- fontDict->SetNewFor<CPDF_Reference>("Widths", pDoc, widthsArray->GetObjNum());
+CPDF_Dictionary* LoadFontDesc(CPDF_Document* pDoc,
+ const ByteString& font_name,
+ CFX_Font* pFont,
+ const uint8_t* data,
+ uint32_t size,
+ int font_type) {
CPDF_Dictionary* fontDesc = pDoc->NewIndirect<CPDF_Dictionary>();
fontDesc->SetNewFor<CPDF_Name>("Type", "FontDescriptor");
- fontDesc->SetNewFor<CPDF_Name>("FontName", name);
+ fontDesc->SetNewFor<CPDF_Name>("FontName", font_name);
int flags = 0;
if (FXFT_Is_Face_fixedwidth(pFont->GetFace()))
flags |= FXFONT_FIXED_PITCH;
- if (name.Find("Serif") > -1)
+ if (font_name.Contains("Serif"))
flags |= FXFONT_SERIF;
if (FXFT_Is_Face_Italic(pFont->GetFace()))
flags |= FXFONT_ITALIC;
if (FXFT_Is_Face_Bold(pFont->GetFace()))
flags |= FXFONT_BOLD;
- // TODO(npm): How do I know if a Type1 font is symbolic, script, allcap,
- // smallcap
+ // TODO(npm): How do I know if a font is symbolic, script, allcap, smallcap
flags |= FXFONT_NONSYMBOLIC;
fontDesc->SetNewFor<CPDF_Number>("Flags", flags);
@@ -108,9 +54,9 @@
pFont->GetBBox(bbox);
auto pBBox = pdfium::MakeUnique<CPDF_Array>();
pBBox->AddNew<CPDF_Number>(bbox.left);
- pBBox->AddNew<CPDF_Number>(bbox.bottom);
- pBBox->AddNew<CPDF_Number>(bbox.right);
pBBox->AddNew<CPDF_Number>(bbox.top);
+ pBBox->AddNew<CPDF_Number>(bbox.right);
+ pBBox->AddNew<CPDF_Number>(bbox.bottom);
fontDesc->SetFor("FontBBox", std::move(pBBox));
// TODO(npm): calculate italic angle correctly
@@ -125,8 +71,429 @@
CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>();
pStream->SetData(data, size);
- fontDesc->SetNewFor<CPDF_Reference>("FontFile", pDoc, pStream->GetObjNum());
+ // TODO(npm): Lengths for Type1 fonts.
+ if (font_type == FPDF_FONT_TRUETYPE) {
+ pStream->GetDict()->SetNewFor<CPDF_Number>("Length1",
+ static_cast<int>(size));
+ }
+ ByteString fontFile = font_type == FPDF_FONT_TYPE1 ? "FontFile" : "FontFile2";
+ fontDesc->SetNewFor<CPDF_Reference>(fontFile, pDoc, pStream->GetObjNum());
+ return fontDesc;
+}
+
+const char ToUnicodeStart[] =
+ "/CIDInit /ProcSet findresource begin\n"
+ "12 dict begin\n"
+ "begincmap\n"
+ "/CIDSystemInfo\n"
+ "<</Registry (Adobe)\n"
+ "/Ordering (Identity)\n"
+ "/Supplement 0\n"
+ ">> def\n"
+ "/CMapName /Adobe-Identity-H def\n"
+ "CMapType 2 def\n"
+ "1 begincodespacerange\n"
+ "<0000> <FFFFF>\n"
+ "endcodespacerange\n";
+
+const char ToUnicodeEnd[] =
+ "endcmap\n"
+ "CMapName currentdict /CMap defineresource pop\n"
+ "end\n"
+ "end\n";
+
+void AddCharcode(std::ostringstream* pBuffer, uint32_t number) {
+ ASSERT(number <= 0xFFFF);
+ *pBuffer << "<";
+ char ans[4];
+ FXSYS_IntToFourHexChars(number, ans);
+ for (size_t i = 0; i < 4; ++i)
+ *pBuffer << ans[i];
+ *pBuffer << ">";
+}
+
+// PDF spec 1.7 Section 5.9.2: "Unicode character sequences as expressed in
+// UTF-16BE encoding." See https://en.wikipedia.org/wiki/UTF-16#Description
+void AddUnicode(std::ostringstream* pBuffer, uint32_t unicode) {
+ if (unicode >= 0xD800 && unicode <= 0xDFFF)
+ unicode = 0;
+
+ char ans[8];
+ *pBuffer << "<";
+ size_t numChars = FXSYS_ToUTF16BE(unicode, ans);
+ for (size_t i = 0; i < numChars; ++i)
+ *pBuffer << ans[i];
+ *pBuffer << ">";
+}
+
+// Loads the charcode to unicode mapping into a stream
+CPDF_Stream* LoadUnicode(CPDF_Document* pDoc,
+ const std::map<uint32_t, uint32_t>& to_unicode) {
+ // A map charcode->unicode
+ std::map<uint32_t, uint32_t> char_to_uni;
+ // A map <char_start, char_end> to vector v of unicode characters of size (end
+ // - start + 1). This abbreviates: start->v[0], start+1->v[1], etc. PDF spec
+ // 1.7 Section 5.9.2 says that only the last byte of the unicode may change.
+ std::map<std::pair<uint32_t, uint32_t>, std::vector<uint32_t>>
+ map_range_vector;
+ // A map <start, end> -> unicode
+ // This abbreviates: start->unicode, start+1->unicode+1, etc.
+ // PDF spec 1.7 Section 5.9.2 says that only the last byte of the unicode may
+ // change.
+ std::map<std::pair<uint32_t, uint32_t>, uint32_t> map_range;
+
+ // Calculate the maps
+ for (auto iter = to_unicode.begin(); iter != to_unicode.end(); ++iter) {
+ uint32_t firstCharcode = iter->first;
+ uint32_t firstUnicode = iter->second;
+ if (std::next(iter) == to_unicode.end() ||
+ firstCharcode + 1 != std::next(iter)->first) {
+ char_to_uni[firstCharcode] = firstUnicode;
+ continue;
+ }
+ ++iter;
+ uint32_t curCharcode = iter->first;
+ uint32_t curUnicode = iter->second;
+ if (curCharcode % 256 == 0) {
+ char_to_uni[firstCharcode] = firstUnicode;
+ char_to_uni[curCharcode] = curUnicode;
+ continue;
+ }
+ const size_t maxExtra = 255 - (curCharcode % 256);
+ auto next_it = std::next(iter);
+ if (firstUnicode + 1 != curUnicode) {
+ // Consecutive charcodes mapping to non-consecutive unicodes
+ std::vector<uint32_t> unicodes;
+ unicodes.push_back(firstUnicode);
+ unicodes.push_back(curUnicode);
+ for (size_t i = 0; i < maxExtra; ++i) {
+ if (next_it == to_unicode.end() || curCharcode + 1 != next_it->first)
+ break;
+ ++iter;
+ ++curCharcode;
+ unicodes.push_back(iter->second);
+ next_it = std::next(iter);
+ }
+ ASSERT(iter->first - firstCharcode + 1 == unicodes.size());
+ map_range_vector[std::make_pair(firstCharcode, iter->first)] = unicodes;
+ continue;
+ }
+ // Consecutive charcodes mapping to consecutive unicodes
+ for (size_t i = 0; i < maxExtra; ++i) {
+ if (next_it == to_unicode.end() || curCharcode + 1 != next_it->first ||
+ curUnicode + 1 != next_it->second) {
+ break;
+ }
+ ++iter;
+ ++curCharcode;
+ ++curUnicode;
+ next_it = std::next(iter);
+ }
+ map_range[std::make_pair(firstCharcode, curCharcode)] = firstUnicode;
+ }
+ std::ostringstream buffer;
+ buffer << ToUnicodeStart;
+ // Add maps to buffer
+ buffer << static_cast<uint32_t>(char_to_uni.size()) << " beginbfchar\n";
+ for (const auto& iter : char_to_uni) {
+ AddCharcode(&buffer, iter.first);
+ buffer << " ";
+ AddUnicode(&buffer, iter.second);
+ buffer << "\n";
+ }
+ buffer << "endbfchar\n"
+ << static_cast<uint32_t>(map_range_vector.size() + map_range.size())
+ << " beginbfrange\n";
+ for (const auto& iter : map_range_vector) {
+ const std::pair<uint32_t, uint32_t>& charcodeRange = iter.first;
+ AddCharcode(&buffer, charcodeRange.first);
+ buffer << " ";
+ AddCharcode(&buffer, charcodeRange.second);
+ buffer << " [";
+ const std::vector<uint32_t>& unicodes = iter.second;
+ for (size_t i = 0; i < unicodes.size(); ++i) {
+ uint32_t uni = unicodes[i];
+ AddUnicode(&buffer, uni);
+ if (i != unicodes.size() - 1)
+ buffer << " ";
+ }
+ buffer << "]\n";
+ }
+ for (const auto& iter : map_range) {
+ const std::pair<uint32_t, uint32_t>& charcodeRange = iter.first;
+ AddCharcode(&buffer, charcodeRange.first);
+ buffer << " ";
+ AddCharcode(&buffer, charcodeRange.second);
+ buffer << " ";
+ AddUnicode(&buffer, iter.second);
+ buffer << "\n";
+ }
+ buffer << "endbfrange\n";
+ buffer << ToUnicodeEnd;
+ // TODO(npm): Encrypt / Compress?
+ CPDF_Stream* stream = pDoc->NewIndirect<CPDF_Stream>();
+ stream->SetData(&buffer);
+ return stream;
+}
+
+const uint32_t kMaxSimpleFontChar = 0xFF;
+
+void* LoadSimpleFont(CPDF_Document* pDoc,
+ std::unique_ptr<CFX_Font> pFont,
+ const uint8_t* data,
+ uint32_t size,
+ int font_type) {
+ CPDF_Dictionary* fontDict = pDoc->NewIndirect<CPDF_Dictionary>();
+ fontDict->SetNewFor<CPDF_Name>("Type", "Font");
+ fontDict->SetNewFor<CPDF_Name>(
+ "Subtype", font_type == FPDF_FONT_TYPE1 ? "Type1" : "TrueType");
+ ByteString name = pFont->GetFaceName();
+ if (name.IsEmpty())
+ name = "Unnamed";
+ fontDict->SetNewFor<CPDF_Name>("BaseFont", name);
+
+ uint32_t glyphIndex;
+ uint32_t currentChar = FXFT_Get_First_Char(pFont->GetFace(), &glyphIndex);
+ if (currentChar > kMaxSimpleFontChar || glyphIndex == 0)
+ return nullptr;
+ fontDict->SetNewFor<CPDF_Number>("FirstChar", static_cast<int>(currentChar));
+ CPDF_Array* widthsArray = pDoc->NewIndirect<CPDF_Array>();
+ while (true) {
+ widthsArray->AddNew<CPDF_Number>(pFont->GetGlyphWidth(glyphIndex));
+ uint32_t nextChar =
+ FXFT_Get_Next_Char(pFont->GetFace(), currentChar, &glyphIndex);
+ // Simple fonts have 1-byte charcodes only.
+ if (nextChar > kMaxSimpleFontChar || glyphIndex == 0)
+ break;
+ for (uint32_t i = currentChar + 1; i < nextChar; i++)
+ widthsArray->AddNew<CPDF_Number>(0);
+ currentChar = nextChar;
+ }
+ fontDict->SetNewFor<CPDF_Number>("LastChar", static_cast<int>(currentChar));
+ fontDict->SetNewFor<CPDF_Reference>("Widths", pDoc, widthsArray->GetObjNum());
+ CPDF_Dictionary* fontDesc =
+ LoadFontDesc(pDoc, name, pFont.get(), data, size, font_type);
+
fontDict->SetNewFor<CPDF_Reference>("FontDescriptor", pDoc,
fontDesc->GetObjNum());
return pDoc->LoadFont(fontDict);
}
+
+const uint32_t kMaxUnicode = 0x10FFFF;
+
+void* LoadCompositeFont(CPDF_Document* pDoc,
+ std::unique_ptr<CFX_Font> pFont,
+ const uint8_t* data,
+ uint32_t size,
+ int font_type) {
+ CPDF_Dictionary* fontDict = pDoc->NewIndirect<CPDF_Dictionary>();
+ fontDict->SetNewFor<CPDF_Name>("Type", "Font");
+ fontDict->SetNewFor<CPDF_Name>("Subtype", "Type0");
+ // TODO(npm): Get the correct encoding, if it's not identity.
+ ByteString encoding = "Identity-H";
+ fontDict->SetNewFor<CPDF_Name>("Encoding", encoding);
+ ByteString name = pFont->GetFaceName();
+ if (name.IsEmpty())
+ name = "Unnamed";
+ fontDict->SetNewFor<CPDF_Name>(
+ "BaseFont", font_type == FPDF_FONT_TYPE1 ? name + "-" + encoding : name);
+
+ CPDF_Dictionary* pCIDFont = pDoc->NewIndirect<CPDF_Dictionary>();
+ pCIDFont->SetNewFor<CPDF_Name>("Type", "Font");
+ pCIDFont->SetNewFor<CPDF_Name>("Subtype", font_type == FPDF_FONT_TYPE1
+ ? "CIDFontType0"
+ : "CIDFontType2");
+ pCIDFont->SetNewFor<CPDF_Name>("BaseFont", name);
+
+ // TODO(npm): Maybe use FT_Get_CID_Registry_Ordering_Supplement to get the
+ // CIDSystemInfo
+ CPDF_Dictionary* pCIDSystemInfo = pDoc->NewIndirect<CPDF_Dictionary>();
+ pCIDSystemInfo->SetNewFor<CPDF_Name>("Registry", "Adobe");
+ pCIDSystemInfo->SetNewFor<CPDF_Name>("Ordering", "Identity");
+ pCIDSystemInfo->SetNewFor<CPDF_Number>("Supplement", 0);
+ pCIDFont->SetNewFor<CPDF_Reference>("CIDSystemInfo", pDoc,
+ pCIDSystemInfo->GetObjNum());
+
+ CPDF_Dictionary* fontDesc =
+ LoadFontDesc(pDoc, name, pFont.get(), data, size, font_type);
+ pCIDFont->SetNewFor<CPDF_Reference>("FontDescriptor", pDoc,
+ fontDesc->GetObjNum());
+
+ uint32_t glyphIndex;
+ uint32_t currentChar = FXFT_Get_First_Char(pFont->GetFace(), &glyphIndex);
+ // If it doesn't have a single char, just fail
+ if (glyphIndex == 0 || currentChar > kMaxUnicode)
+ return nullptr;
+
+ std::map<uint32_t, uint32_t> to_unicode;
+ std::map<uint32_t, uint32_t> widths;
+ while (true) {
+ if (currentChar > kMaxUnicode)
+ break;
+
+ widths[glyphIndex] = pFont->GetGlyphWidth(glyphIndex);
+ to_unicode[glyphIndex] = currentChar;
+ currentChar =
+ FXFT_Get_Next_Char(pFont->GetFace(), currentChar, &glyphIndex);
+ if (glyphIndex == 0)
+ break;
+ }
+ CPDF_Array* widthsArray = pDoc->NewIndirect<CPDF_Array>();
+ for (auto it = widths.begin(); it != widths.end(); ++it) {
+ int ch = it->first;
+ int w = it->second;
+ if (std::next(it) == widths.end()) {
+ // Only one char left, use format c [w]
+ auto oneW = pdfium::MakeUnique<CPDF_Array>();
+ oneW->AddNew<CPDF_Number>(w);
+ widthsArray->AddNew<CPDF_Number>(ch);
+ widthsArray->Add(std::move(oneW));
+ break;
+ }
+ ++it;
+ int next_ch = it->first;
+ int next_w = it->second;
+ if (next_ch == ch + 1 && next_w == w) {
+ // The array can have a group c_first c_last w: all CIDs in the range from
+ // c_first to c_last will have width w
+ widthsArray->AddNew<CPDF_Number>(ch);
+ ch = next_ch;
+ while (true) {
+ auto next_it = std::next(it);
+ if (next_it == widths.end() || next_it->first != it->first + 1 ||
+ next_it->second != it->second) {
+ break;
+ }
+ ++it;
+ ch = it->first;
+ }
+ widthsArray->AddNew<CPDF_Number>(ch);
+ widthsArray->AddNew<CPDF_Number>(w);
+ continue;
+ }
+ // Otherwise we can have a group of the form c [w1 w2 ...]: c has width
+ // w1, c+1 has width w2, etc.
+ widthsArray->AddNew<CPDF_Number>(ch);
+ auto curWidthArray = pdfium::MakeUnique<CPDF_Array>();
+ curWidthArray->AddNew<CPDF_Number>(w);
+ curWidthArray->AddNew<CPDF_Number>(next_w);
+ while (true) {
+ auto next_it = std::next(it);
+ if (next_it == widths.end() || next_it->first != it->first + 1)
+ break;
+ ++it;
+ curWidthArray->AddNew<CPDF_Number>(static_cast<int>(it->second));
+ }
+ widthsArray->Add(std::move(curWidthArray));
+ }
+ pCIDFont->SetNewFor<CPDF_Reference>("W", pDoc, widthsArray->GetObjNum());
+ // TODO(npm): Support vertical writing
+
+ auto pDescendant = pdfium::MakeUnique<CPDF_Array>();
+ pDescendant->AddNew<CPDF_Reference>(pDoc, pCIDFont->GetObjNum());
+ fontDict->SetFor("DescendantFonts", std::move(pDescendant));
+ CPDF_Stream* toUnicodeStream = LoadUnicode(pDoc, to_unicode);
+ fontDict->SetNewFor<CPDF_Reference>("ToUnicode", pDoc,
+ toUnicodeStream->GetObjNum());
+ return pDoc->LoadFont(fontDict);
+}
+
+} // namespace
+
+FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
+FPDFPageObj_NewTextObj(FPDF_DOCUMENT document,
+ FPDF_BYTESTRING font,
+ float font_size) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc)
+ return nullptr;
+
+ CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc, ByteStringView(font));
+ if (!pFont)
+ return nullptr;
+
+ auto pTextObj = pdfium::MakeUnique<CPDF_TextObject>();
+ pTextObj->m_TextState.SetFont(pFont);
+ pTextObj->m_TextState.SetFontSize(font_size);
+ pTextObj->DefaultStates();
+ return pTextObj.release(); // Caller takes ownership.
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFText_SetText(FPDF_PAGEOBJECT text_object, FPDF_WIDESTRING text) {
+ auto* pTextObj = static_cast<CPDF_TextObject*>(text_object);
+ if (!pTextObj)
+ return false;
+
+ size_t len = WideString::WStringLength(text);
+ WideString encodedText = WideString::FromUTF16LE(text, len);
+ ByteString byteText;
+ for (wchar_t wc : encodedText) {
+ pTextObj->GetFont()->AppendChar(
+ &byteText, pTextObj->GetFont()->CharCodeFromUnicode(wc));
+ }
+ pTextObj->SetText(byteText);
+ return true;
+}
+
+FPDF_EXPORT FPDF_FONT FPDF_CALLCONV FPDFText_LoadFont(FPDF_DOCUMENT document,
+ const uint8_t* data,
+ uint32_t size,
+ int font_type,
+ FPDF_BOOL cid) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc || !data || size == 0 ||
+ (font_type != FPDF_FONT_TYPE1 && font_type != FPDF_FONT_TRUETYPE)) {
+ return nullptr;
+ }
+
+ auto pFont = pdfium::MakeUnique<CFX_Font>();
+
+ // TODO(npm): Maybe use FT_Get_X11_Font_Format to check format? Otherwise, we
+ // are allowing giving any font that can be loaded on freetype and setting it
+ // as any font type.
+ if (!pFont->LoadEmbedded(data, size))
+ return nullptr;
+
+ return cid ? LoadCompositeFont(pDoc, std::move(pFont), data, size, font_type)
+ : LoadSimpleFont(pDoc, std::move(pFont), data, size, font_type);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFText_SetFillColor(FPDF_PAGEOBJECT text_object,
+ unsigned int R,
+ unsigned int G,
+ unsigned int B,
+ unsigned int A) {
+ return FPDFPageObj_SetFillColor(text_object, R, G, B, A);
+}
+
+FPDF_EXPORT void FPDF_CALLCONV FPDFFont_Close(FPDF_FONT font) {
+ CPDF_Font* pFont = static_cast<CPDF_Font*>(font);
+ if (!pFont)
+ return;
+
+ CPDF_Document* pDoc = pFont->GetDocument();
+ if (!pDoc)
+ return;
+
+ CPDF_DocPageData* pPageData = pDoc->GetPageData();
+ if (!pPageData->IsForceClear())
+ pPageData->ReleaseFont(pFont->GetFontDict());
+}
+
+FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
+FPDFPageObj_CreateTextObj(FPDF_DOCUMENT document,
+ FPDF_FONT font,
+ float font_size) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ CPDF_Font* pFont = static_cast<CPDF_Font*>(font);
+ if (!pDoc || !pFont)
+ return nullptr;
+
+ auto pTextObj = pdfium::MakeUnique<CPDF_TextObject>();
+ pTextObj->m_TextState.SetFont(pDoc->LoadFont(pFont->GetFontDict()));
+ pTextObj->m_TextState.SetFontSize(font_size);
+ pTextObj->DefaultStates();
+ return pTextObj.release();
+}
diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp
index 57ff6b6..10aecb3 100644
--- a/fpdfsdk/fpdfformfill.cpp
+++ b/fpdfsdk/fpdfformfill.cpp
@@ -16,7 +16,7 @@
#include "core/fpdfdoc/cpdf_formfield.h"
#include "core/fpdfdoc/cpdf_interform.h"
#include "core/fpdfdoc/cpdf_occontext.h"
-#include "core/fxge/cfx_fxgedevice.h"
+#include "core/fxge/cfx_defaultrenderdevice.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_interform.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
@@ -29,11 +29,73 @@
#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffpageview.h"
-#include "xfa/fxfa/xfa_ffwidget.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffpageview.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
+
+static_assert(static_cast<int>(FormType::kNone) == FORMTYPE_NONE,
+ "None form types must match");
+static_assert(static_cast<int>(FormType::kAcroForm) == FORMTYPE_ACRO_FORM,
+ "AcroForm form types must match");
+static_assert(static_cast<int>(FormType::kXFAFull) == FORMTYPE_XFA_FULL,
+ "XFA full form types must match");
+static_assert(static_cast<int>(FormType::kXFAForeground) ==
+ FORMTYPE_XFA_FOREGROUND,
+ "XFA foreground form types must match");
#endif // PDF_ENABLE_XFA
+static_assert(static_cast<int>(FormFieldType::kUnknown) ==
+ FPDF_FORMFIELD_UNKNOWN,
+ "Unknown form field types must match");
+static_assert(static_cast<int>(FormFieldType::kPushButton) ==
+ FPDF_FORMFIELD_PUSHBUTTON,
+ "PushButton form field types must match");
+static_assert(static_cast<int>(FormFieldType::kCheckBox) ==
+ FPDF_FORMFIELD_CHECKBOX,
+ "CheckBox form field types must match");
+static_assert(static_cast<int>(FormFieldType::kRadioButton) ==
+ FPDF_FORMFIELD_RADIOBUTTON,
+ "RadioButton form field types must match");
+static_assert(static_cast<int>(FormFieldType::kComboBox) ==
+ FPDF_FORMFIELD_COMBOBOX,
+ "ComboBox form field types must match");
+static_assert(static_cast<int>(FormFieldType::kListBox) ==
+ FPDF_FORMFIELD_LISTBOX,
+ "ListBox form field types must match");
+static_assert(static_cast<int>(FormFieldType::kTextField) ==
+ FPDF_FORMFIELD_TEXTFIELD,
+ "TextField form field types must match");
+static_assert(static_cast<int>(FormFieldType::kSignature) ==
+ FPDF_FORMFIELD_SIGNATURE,
+ "Signature form field types must match");
+#ifdef PDF_ENABLE_XFA
+static_assert(static_cast<int>(FormFieldType::kXFA) == FPDF_FORMFIELD_XFA,
+ "XFA form field types must match");
+static_assert(static_cast<int>(FormFieldType::kXFA_CheckBox) ==
+ FPDF_FORMFIELD_XFA_CHECKBOX,
+ "XFA CheckBox form field types must match");
+static_assert(static_cast<int>(FormFieldType::kXFA_ComboBox) ==
+ FPDF_FORMFIELD_XFA_COMBOBOX,
+ "XFA ComboBox form field types must match");
+static_assert(static_cast<int>(FormFieldType::kXFA_ImageField) ==
+ FPDF_FORMFIELD_XFA_IMAGEFIELD,
+ "XFA ImageField form field types must match");
+static_assert(static_cast<int>(FormFieldType::kXFA_ListBox) ==
+ FPDF_FORMFIELD_XFA_LISTBOX,
+ "XFA ListBox form field types must match");
+static_assert(static_cast<int>(FormFieldType::kXFA_PushButton) ==
+ FPDF_FORMFIELD_XFA_PUSHBUTTON,
+ "XFA PushButton form field types must match");
+static_assert(static_cast<int>(FormFieldType::kXFA_Signature) ==
+ FPDF_FORMFIELD_XFA_SIGNATURE,
+ "XFA Signature form field types must match");
+static_assert(static_cast<int>(FormFieldType::kXFA_TextField) ==
+ FPDF_FORMFIELD_XFA_TEXTFIELD,
+ "XFA TextField form field types must match");
+#endif // PDF_ENABLE_XFA
+static_assert(kFormFieldTypeCount == FPDF_FORMFIELD_COUNT,
+ "Number of form field types must match");
+
namespace {
CPDFSDK_FormFillEnvironment* HandleToCPDFSDKEnvironment(
@@ -59,12 +121,12 @@
}
#ifdef PDF_ENABLE_XFA
-std::vector<CFX_ByteString>* FromFPDFStringHandle(FPDF_STRINGHANDLE handle) {
- return reinterpret_cast<std::vector<CFX_ByteString>*>(handle);
+std::vector<ByteString>* FromFPDFStringHandle(FPDF_STRINGHANDLE handle) {
+ return static_cast<std::vector<ByteString>*>(handle);
}
-FPDF_STRINGHANDLE ToFPDFStringHandle(std::vector<CFX_ByteString>* strings) {
- return reinterpret_cast<FPDF_STRINGHANDLE>(strings);
+FPDF_STRINGHANDLE ToFPDFStringHandle(std::vector<ByteString>* strings) {
+ return static_cast<FPDF_STRINGHANDLE>(strings);
}
#endif // PDF_ENABLE_XFA
@@ -102,67 +164,68 @@
pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
FX_RECT clip(start_x, start_y, start_x + size_x, start_y + size_y);
- std::unique_ptr<CFX_FxgeDevice> pDevice(new CFX_FxgeDevice);
+ auto pDevice = pdfium::MakeUnique<CFX_DefaultRenderDevice>();
#ifdef _SKIA_SUPPORT_
pDevice->AttachRecorder(static_cast<SkPictureRecorder*>(recorder));
#endif
- pDevice->Attach(CFXBitmapFromFPDFBitmap(bitmap), false, nullptr, false);
- pDevice->SaveState();
- pDevice->SetClip_Rect(clip);
+ RetainPtr<CFX_DIBitmap> holder(CFXBitmapFromFPDFBitmap(bitmap));
+ pDevice->Attach(holder, false, nullptr, false);
+ {
+ CFX_RenderDevice::StateRestorer restorer(pDevice.get());
+ pDevice->SetClip_Rect(clip);
- CPDF_RenderOptions options;
- if (flags & FPDF_LCD_TEXT)
- options.m_Flags |= RENDER_CLEARTYPE;
- else
- options.m_Flags &= ~RENDER_CLEARTYPE;
+ CPDF_RenderOptions options;
+ uint32_t option_flags = options.GetFlags();
+ if (flags & FPDF_LCD_TEXT)
+ option_flags |= RENDER_CLEARTYPE;
+ else
+ option_flags &= ~RENDER_CLEARTYPE;
+ options.SetFlags(option_flags);
- // Grayscale output
- if (flags & FPDF_GRAYSCALE) {
- options.m_ColorMode = RENDER_COLOR_GRAY;
- options.m_ForeColor = 0;
- options.m_BackColor = 0xffffff;
- }
- options.m_AddFlags = flags >> 8;
- options.m_bDrawAnnots = flags & FPDF_ANNOT;
+ // Grayscale output
+ if (flags & FPDF_GRAYSCALE)
+ options.SetColorMode(CPDF_RenderOptions::kGray);
+
+ options.SetDrawAnnots(flags & FPDF_ANNOT);
#ifdef PDF_ENABLE_XFA
- options.m_pOCContext =
- pdfium::MakeRetain<CPDF_OCContext>(pPDFDoc, CPDF_OCContext::View);
- if (CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, true))
- pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip);
+ options.SetOCContext(
+ pdfium::MakeRetain<CPDF_OCContext>(pPDFDoc, CPDF_OCContext::View));
+ if (CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, true))
+ pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip);
#else // PDF_ENABLE_XFA
- options.m_pOCContext = pdfium::MakeRetain<CPDF_OCContext>(
- pPage->m_pDocument, CPDF_OCContext::View);
- if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage))
- pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options);
+ options.SetOCContext(pdfium::MakeRetain<CPDF_OCContext>(
+ pPage->m_pDocument.Get(), CPDF_OCContext::View));
+ if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage))
+ pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options);
#endif // PDF_ENABLE_XFA
-
- pDevice->RestoreState(false);
+ }
#ifdef _SKIA_SUPPORT_PATHS_
- pDevice->Flush();
- CFXBitmapFromFPDFBitmap(bitmap)->UnPreMultiply();
+ pDevice->Flush(true);
+ holder->UnPreMultiply();
#endif
}
} // namespace
-DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- double page_x,
- double page_y) {
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ double page_x,
+ double page_y) {
if (!hHandle)
return -1;
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (pPage) {
- CPDF_InterForm interform(pPage->m_pDocument);
+ CPDF_InterForm interform(pPage->m_pDocument.Get());
CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint(
- pPage, CFX_PointF(static_cast<FX_FLOAT>(page_x),
- static_cast<FX_FLOAT>(page_y)),
+ pPage,
+ CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
nullptr);
if (!pFormCtrl)
return -1;
CPDF_FormField* pFormField = pFormCtrl->GetField();
- return pFormField ? pFormField->GetFieldType() : -1;
+ return pFormField ? static_cast<int>(pFormField->GetFieldType()) : -1;
}
#ifdef PDF_ENABLE_XFA
@@ -188,52 +251,40 @@
if (!pWidgetIterator)
return -1;
- CXFA_FFWidget* pXFAAnnot = pWidgetIterator->MoveToNext();
- while (pXFAAnnot) {
+ CXFA_FFWidget* pXFAAnnot;
+ while ((pXFAAnnot = pWidgetIterator->MoveToNext()) != nullptr) {
CFX_RectF rcBBox = pXFAAnnot->GetBBox(0);
CFX_FloatRect rcWidget(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width,
rcBBox.top + rcBBox.height);
- rcWidget.left -= 1.0f;
- rcWidget.right += 1.0f;
- rcWidget.bottom -= 1.0f;
- rcWidget.top += 1.0f;
-
- if (rcWidget.Contains(CFX_PointF(static_cast<FX_FLOAT>(page_x),
- static_cast<FX_FLOAT>(page_y)))) {
- return FPDF_FORMFIELD_XFA;
+ rcWidget.Inflate(1.0f, 1.0f);
+ if (rcWidget.Contains(CFX_PointF(static_cast<float>(page_x),
+ static_cast<float>(page_y)))) {
+ return static_cast<int>(pXFAAnnot->GetFormFieldType());
}
- pXFAAnnot = pWidgetIterator->MoveToNext();
}
#endif // PDF_ENABLE_XFA
return -1;
}
-DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- double page_x,
- double page_y) {
- return FPDFPage_HasFormFieldAtPoint(hHandle, page, page_x, page_y);
-}
-
-DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- double page_x,
- double page_y) {
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ double page_x,
+ double page_y) {
if (!hHandle)
return -1;
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return -1;
- CPDF_InterForm interform(pPage->m_pDocument);
+ CPDF_InterForm interform(pPage->m_pDocument.Get());
int z_order = -1;
(void)interform.GetControlAtPoint(
- pPage,
- CFX_PointF(static_cast<FX_FLOAT>(page_x), static_cast<FX_FLOAT>(page_y)),
+ pPage, CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
&z_order);
return z_order;
}
-DLLEXPORT FPDF_FORMHANDLE STDCALL
+FPDF_EXPORT FPDF_FORMHANDLE FPDF_CALLCONV
FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document,
FPDF_FORMFILLINFO* formInfo) {
#ifdef PDF_ENABLE_XFA
@@ -256,23 +307,22 @@
return pDocument->GetFormFillEnv();
#endif
- CPDFSDK_FormFillEnvironment* pFormFillEnv =
- new CPDFSDK_FormFillEnvironment(pDocument, formInfo);
+ auto pFormFillEnv =
+ pdfium::MakeUnique<CPDFSDK_FormFillEnvironment>(pDocument, formInfo);
#ifdef PDF_ENABLE_XFA
- pDocument->SetFormFillEnv(pFormFillEnv);
+ pDocument->SetFormFillEnv(pFormFillEnv.get());
#endif // PDF_ENABLE_XFA
- return pFormFillEnv;
+ return pFormFillEnv.release(); // Caller takes ownership.
}
-DLLEXPORT void STDCALL
+FPDF_EXPORT void FPDF_CALLCONV
FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) {
- if (!hHandle)
- return;
-
CPDFSDK_FormFillEnvironment* pFormFillEnv =
HandleToCPDFSDKEnvironment(hHandle);
+ if (!pFormFillEnv)
+ return;
#ifdef PDF_ENABLE_XFA
// Reset the focused annotations and remove the SDK document from the
@@ -283,105 +333,141 @@
if (pFormFillEnv->GetXFAContext())
pFormFillEnv->GetXFAContext()->SetFormFillEnv(nullptr);
#endif // PDF_ENABLE_XFA
-
delete pFormFillEnv;
}
-DLLEXPORT FPDF_BOOL STDCALL FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- int modifier,
- double page_x,
- double page_y) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int modifier,
+ double page_x,
+ double page_y) {
CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
if (!pPageView)
return false;
return pPageView->OnMouseMove(CFX_PointF(page_x, page_y), modifier);
}
-DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- int modifier,
- double page_x,
- double page_y) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnFocus(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int modifier,
+ double page_x,
+ double page_y) {
+ CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
+ if (!pPageView)
+ return false;
+ return pPageView->OnFocus(CFX_PointF(page_x, page_y), modifier);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int modifier,
+ double page_x,
+ double page_y) {
CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
if (!pPageView)
return false;
return pPageView->OnLButtonDown(CFX_PointF(page_x, page_y), modifier);
}
-DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- int modifier,
- double page_x,
- double page_y) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int modifier,
+ double page_x,
+ double page_y) {
CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
if (!pPageView)
return false;
-
- CFX_PointF pt((FX_FLOAT)page_x, (FX_FLOAT)page_y);
- return pPageView->OnLButtonUp(pt, modifier);
+ return pPageView->OnLButtonUp(CFX_PointF(page_x, page_y), modifier);
}
#ifdef PDF_ENABLE_XFA
-DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- int modifier,
- double page_x,
- double page_y) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int modifier,
+ double page_x,
+ double page_y) {
CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
if (!pPageView)
return false;
return pPageView->OnRButtonDown(CFX_PointF(page_x, page_y), modifier);
}
-DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- int modifier,
- double page_x,
- double page_y) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int modifier,
+ double page_x,
+ double page_y) {
CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
if (!pPageView)
return false;
-
- CFX_PointF pt((FX_FLOAT)page_x, (FX_FLOAT)page_y);
- return pPageView->OnRButtonUp(pt, modifier);
+ return pPageView->OnRButtonUp(CFX_PointF(page_x, page_y), modifier);
}
#endif // PDF_ENABLE_XFA
-DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- int nKeyCode,
- int modifier) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int nKeyCode,
+ int modifier) {
CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
if (!pPageView)
return false;
-
return pPageView->OnKeyDown(nKeyCode, modifier);
}
-DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- int nKeyCode,
- int modifier) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int nKeyCode,
+ int modifier) {
CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
if (!pPageView)
return false;
-
return pPageView->OnKeyUp(nKeyCode, modifier);
}
-DLLEXPORT FPDF_BOOL STDCALL FORM_OnChar(FPDF_FORMHANDLE hHandle,
- FPDF_PAGE page,
- int nChar,
- int modifier) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnChar(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ int nChar,
+ int modifier) {
CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
if (!pPageView)
return false;
-
return pPageView->OnChar(nChar, modifier);
}
-DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FORM_GetSelectedText(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ void* buffer,
+ unsigned long buflen) {
+ CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
+ if (!pPageView)
+ return 0;
+
+ WideString wide_str_form_text = pPageView->GetSelectedText();
+ ByteString encoded_form_text = wide_str_form_text.UTF16LE_Encode();
+ unsigned long form_text_len = encoded_form_text.GetLength();
+
+ if (buffer && buflen >= form_text_len)
+ memcpy(buffer, encoded_form_text.c_str(), form_text_len);
+
+ return form_text_len;
+}
+
+FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle,
+ FPDF_PAGE page,
+ FPDF_WIDESTRING wsText) {
+ CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
+ if (!pPageView)
+ return;
+
+ size_t len = WideString::WStringLength(wsText);
+ WideString wide_str_text = WideString::FromUTF16LE(wsText, len);
+
+ pPageView->ReplaceSelection(wide_str_text);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) {
CPDFSDK_FormFillEnvironment* pFormFillEnv =
HandleToCPDFSDKEnvironment(hHandle);
if (!pFormFillEnv)
@@ -389,90 +475,86 @@
return pFormFillEnv->KillFocusAnnot(0);
}
-DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
- FPDF_BITMAP bitmap,
- FPDF_PAGE page,
- int start_x,
- int start_y,
- int size_x,
- int size_y,
- int rotate,
- int flags) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
+ FPDF_BITMAP bitmap,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags) {
FFLCommon(hHandle, bitmap, nullptr, page, start_x, start_y, size_x, size_y,
rotate, flags);
}
#ifdef _SKIA_SUPPORT_
-DLLEXPORT void STDCALL FPDF_FFLRecord(FPDF_FORMHANDLE hHandle,
- FPDF_RECORDER recorder,
- FPDF_PAGE page,
- int start_x,
- int start_y,
- int size_x,
- int size_y,
- int rotate,
- int flags) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLRecord(FPDF_FORMHANDLE hHandle,
+ FPDF_RECORDER recorder,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags) {
FFLCommon(hHandle, nullptr, recorder, page, start_x, start_y, size_x, size_y,
rotate, flags);
}
#endif
#ifdef PDF_ENABLE_XFA
-DLLEXPORT void STDCALL FPDF_Widget_Undo(FPDF_DOCUMENT document,
- FPDF_WIDGET hWidget) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Undo(FPDF_DOCUMENT document,
+ FPDF_WIDGET hWidget) {
if (!hWidget || !document)
return;
CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
- pContext->GetDocType() != XFA_DOCTYPE_Static)
+ if (!pContext->ContainsXFAForm())
return;
static_cast<CXFA_FFWidget*>(hWidget)->Undo();
}
-DLLEXPORT void STDCALL FPDF_Widget_Redo(FPDF_DOCUMENT document,
- FPDF_WIDGET hWidget) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Redo(FPDF_DOCUMENT document,
+ FPDF_WIDGET hWidget) {
if (!hWidget || !document)
return;
CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
- pContext->GetDocType() != XFA_DOCTYPE_Static)
+ if (!pContext->ContainsXFAForm())
return;
static_cast<CXFA_FFWidget*>(hWidget)->Redo();
}
-DLLEXPORT void STDCALL FPDF_Widget_SelectAll(FPDF_DOCUMENT document,
- FPDF_WIDGET hWidget) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_SelectAll(FPDF_DOCUMENT document,
+ FPDF_WIDGET hWidget) {
if (!hWidget || !document)
return;
CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
- pContext->GetDocType() != XFA_DOCTYPE_Static)
+ if (!pContext->ContainsXFAForm())
return;
static_cast<CXFA_FFWidget*>(hWidget)->SelectAll();
}
-DLLEXPORT void STDCALL FPDF_Widget_Copy(FPDF_DOCUMENT document,
- FPDF_WIDGET hWidget,
- FPDF_WIDESTRING wsText,
- FPDF_DWORD* size) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Copy(FPDF_DOCUMENT document,
+ FPDF_WIDGET hWidget,
+ FPDF_WIDESTRING wsText,
+ FPDF_DWORD* size) {
if (!hWidget || !document)
return;
CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
- pContext->GetDocType() != XFA_DOCTYPE_Static)
+ if (!pContext->ContainsXFAForm())
return;
- CFX_WideString wsCpText;
- static_cast<CXFA_FFWidget*>(hWidget)->Copy(wsCpText);
+ WideString wsCpText =
+ static_cast<CXFA_FFWidget*>(hWidget)->Copy().value_or(WideString());
- CFX_ByteString bsCpText = wsCpText.UTF16LE_Encode();
+ ByteString bsCpText = wsCpText.UTF16LE_Encode();
uint32_t len = bsCpText.GetLength() / sizeof(unsigned short);
if (!wsText) {
*size = len;
@@ -481,30 +563,29 @@
uint32_t real_size = len < *size ? len : *size;
if (real_size > 0) {
- FXSYS_memcpy((void*)wsText,
- bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
- real_size * sizeof(unsigned short));
+ memcpy((void*)wsText,
+ bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
+ real_size * sizeof(unsigned short));
bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short));
}
*size = real_size;
}
-DLLEXPORT void STDCALL FPDF_Widget_Cut(FPDF_DOCUMENT document,
- FPDF_WIDGET hWidget,
- FPDF_WIDESTRING wsText,
- FPDF_DWORD* size) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Cut(FPDF_DOCUMENT document,
+ FPDF_WIDGET hWidget,
+ FPDF_WIDESTRING wsText,
+ FPDF_DWORD* size) {
if (!hWidget || !document)
return;
CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
- pContext->GetDocType() != XFA_DOCTYPE_Static)
+ if (!pContext->ContainsXFAForm())
return;
- CFX_WideString wsCpText;
- static_cast<CXFA_FFWidget*>(hWidget)->Cut(wsCpText);
+ WideString wsCpText =
+ static_cast<CXFA_FFWidget*>(hWidget)->Cut().value_or(WideString());
- CFX_ByteString bsCpText = wsCpText.UTF16LE_Encode();
+ ByteString bsCpText = wsCpText.UTF16LE_Encode();
uint32_t len = bsCpText.GetLength() / sizeof(unsigned short);
if (!wsText) {
*size = len;
@@ -513,31 +594,30 @@
uint32_t real_size = len < *size ? len : *size;
if (real_size > 0) {
- FXSYS_memcpy((void*)wsText,
- bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
- real_size * sizeof(unsigned short));
+ memcpy((void*)wsText,
+ bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
+ real_size * sizeof(unsigned short));
bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short));
}
*size = real_size;
}
-DLLEXPORT void STDCALL FPDF_Widget_Paste(FPDF_DOCUMENT document,
- FPDF_WIDGET hWidget,
- FPDF_WIDESTRING wsText,
- FPDF_DWORD size) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Paste(FPDF_DOCUMENT document,
+ FPDF_WIDGET hWidget,
+ FPDF_WIDESTRING wsText,
+ FPDF_DWORD size) {
if (!hWidget || !document)
return;
CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
- pContext->GetDocType() != XFA_DOCTYPE_Static)
+ if (!pContext->ContainsXFAForm())
return;
- CFX_WideString wstr = CFX_WideString::FromUTF16LE(wsText, size);
+ WideString wstr = WideString::FromUTF16LE(wsText, size);
static_cast<CXFA_FFWidget*>(hWidget)->Paste(wstr);
}
-DLLEXPORT void STDCALL
+FPDF_EXPORT void FPDF_CALLCONV
FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document,
FPDF_WIDGET hWidget,
float x,
@@ -547,18 +627,17 @@
return;
CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
- pContext->GetDocType() != XFA_DOCTYPE_Static)
+ if (!pContext->ContainsXFAForm())
return;
CFX_PointF ptPopup;
ptPopup.x = x;
ptPopup.y = y;
- CFX_ByteStringC bs(bsText);
+ ByteStringView bs(bsText);
static_cast<CXFA_FFWidget*>(hWidget)->ReplaceSpellCheckWord(ptPopup, bs);
}
-DLLEXPORT void STDCALL
+FPDF_EXPORT void FPDF_CALLCONV
FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document,
FPDF_WIDGET hWidget,
float x,
@@ -567,26 +646,28 @@
if (!hWidget || !document)
return;
- CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
- pContext->GetDocType() != XFA_DOCTYPE_Static)
+ auto* pContext = static_cast<CPDFXFA_Context*>(document);
+ if (!pContext->ContainsXFAForm())
return;
- std::vector<CFX_ByteString>* sSuggestWords = new std::vector<CFX_ByteString>;
CFX_PointF ptPopup;
ptPopup.x = x;
ptPopup.y = y;
- static_cast<CXFA_FFWidget*>(hWidget)
- ->GetSuggestWords(ptPopup, *sSuggestWords);
- *stringHandle = ToFPDFStringHandle(sSuggestWords);
+ auto sSuggestWords = pdfium::MakeUnique<std::vector<ByteString>>();
+ static_cast<CXFA_FFWidget*>(hWidget)->GetSuggestWords(ptPopup,
+ sSuggestWords.get());
+
+ // Caller takes ownership.
+ *stringHandle = ToFPDFStringHandle(sSuggestWords.release());
}
-DLLEXPORT int STDCALL FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle) {
- std::vector<CFX_ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
+FPDF_EXPORT int FPDF_CALLCONV
+FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle) {
+ std::vector<ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
return sSuggestWords ? pdfium::CollectionSize<int>(*sSuggestWords) : -1;
}
-DLLEXPORT FPDF_BOOL STDCALL
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle,
int index,
FPDF_BYTESTRING bsText,
@@ -598,7 +679,7 @@
if (index < 0 || index >= count)
return false;
- std::vector<CFX_ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
+ std::vector<ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
uint32_t len = (*sSuggestWords)[index].GetLength();
if (!bsText) {
*size = len;
@@ -607,57 +688,67 @@
uint32_t real_size = len < *size ? len : *size;
if (real_size > 0)
- FXSYS_memcpy((void*)bsText, (*sSuggestWords)[index].c_str(), real_size);
+ memcpy((void*)bsText, (*sSuggestWords)[index].c_str(), real_size);
*size = real_size;
return true;
}
-DLLEXPORT void STDCALL
+FPDF_EXPORT void FPDF_CALLCONV
FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle) {
delete FromFPDFStringHandle(stringHandle);
}
-DLLEXPORT FPDF_BOOL STDCALL
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle,
FPDF_BYTESTRING bsText,
FPDF_DWORD size) {
if (!stringHandle || !bsText || size == 0)
return false;
- FromFPDFStringHandle(stringHandle)->push_back(CFX_ByteString(bsText, size));
+ FromFPDFStringHandle(stringHandle)->push_back(ByteString(bsText, size));
return true;
}
#endif // PDF_ENABLE_XFA
-DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,
- int fieldType,
- unsigned long color) {
- if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
- pInterForm->SetHighlightColor(color, fieldType);
+FPDF_EXPORT void FPDF_CALLCONV
+FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,
+ int fieldType,
+ unsigned long color) {
+ CPDFSDK_InterForm* interForm = FormHandleToInterForm(hHandle);
+ if (!interForm)
+ return;
+
+ Optional<FormFieldType> cast_input = IntToFormFieldType(fieldType);
+ if (!cast_input)
+ return;
+
+ if (cast_input.value() == FormFieldType::kUnknown) {
+ interForm->SetAllHighlightColors(color);
+ } else {
+ interForm->SetHighlightColor(color, cast_input.value());
+ }
}
-DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle,
- unsigned char alpha) {
+FPDF_EXPORT void FPDF_CALLCONV
+FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha) {
if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
pInterForm->SetHighlightAlpha(alpha);
}
-DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
+FPDF_EXPORT void FPDF_CALLCONV
+FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
- pInterForm->RemoveAllHighLight();
+ pInterForm->RemoveAllHighLights();
}
-DLLEXPORT void STDCALL FORM_OnAfterLoadPage(FPDF_PAGE page,
- FPDF_FORMHANDLE hHandle) {
+FPDF_EXPORT void FPDF_CALLCONV FORM_OnAfterLoadPage(FPDF_PAGE page,
+ FPDF_FORMHANDLE hHandle) {
if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page))
pPageView->SetValid(true);
}
-DLLEXPORT void STDCALL FORM_OnBeforeClosePage(FPDF_PAGE page,
- FPDF_FORMHANDLE hHandle) {
- if (!hHandle)
- return;
-
+FPDF_EXPORT void FPDF_CALLCONV FORM_OnBeforeClosePage(FPDF_PAGE page,
+ FPDF_FORMHANDLE hHandle) {
CPDFSDK_FormFillEnvironment* pFormFillEnv =
HandleToCPDFSDKEnvironment(hHandle);
if (!pFormFillEnv)
@@ -675,48 +766,47 @@
}
}
-DLLEXPORT void STDCALL FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) {
+FPDF_EXPORT void FPDF_CALLCONV
+FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) {
CPDFSDK_FormFillEnvironment* pFormFillEnv =
HandleToCPDFSDKEnvironment(hHandle);
if (pFormFillEnv && pFormFillEnv->IsJSInitiated())
pFormFillEnv->ProcJavascriptFun();
}
-DLLEXPORT void STDCALL FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) {
+FPDF_EXPORT void FPDF_CALLCONV
+FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) {
CPDFSDK_FormFillEnvironment* pFormFillEnv =
HandleToCPDFSDKEnvironment(hHandle);
if (pFormFillEnv && pFormFillEnv->IsJSInitiated())
pFormFillEnv->ProcOpenAction();
}
-DLLEXPORT void STDCALL FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,
- int aaType) {
+FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,
+ int aaType) {
CPDFSDK_FormFillEnvironment* pFormFillEnv =
HandleToCPDFSDKEnvironment(hHandle);
if (!pFormFillEnv)
return;
CPDF_Document* pDoc = pFormFillEnv->GetPDFDocument();
- CPDF_Dictionary* pDic = pDoc->GetRoot();
- if (!pDic)
+ const CPDF_Dictionary* pDict = pDoc->GetRoot();
+ if (!pDict)
return;
- CPDF_AAction aa(pDic->GetDictFor("AA"));
- if (aa.ActionExist((CPDF_AAction::AActionType)aaType)) {
- CPDF_Action action = aa.GetAction((CPDF_AAction::AActionType)aaType);
+ CPDF_AAction aa(pDict->GetDictFor("AA"));
+ auto type = static_cast<CPDF_AAction::AActionType>(aaType);
+ if (aa.ActionExist(type)) {
+ CPDF_Action action = aa.GetAction(type);
CPDFSDK_ActionHandler* pActionHandler =
- HandleToCPDFSDKEnvironment(hHandle)->GetActionHander();
- pActionHandler->DoAction_Document(action, (CPDF_AAction::AActionType)aaType,
- pFormFillEnv);
+ HandleToCPDFSDKEnvironment(hHandle)->GetActionHandler();
+ pActionHandler->DoAction_Document(action, type, pFormFillEnv);
}
}
-DLLEXPORT void STDCALL FORM_DoPageAAction(FPDF_PAGE page,
- FPDF_FORMHANDLE hHandle,
- int aaType) {
- if (!hHandle)
- return;
-
+FPDF_EXPORT void FPDF_CALLCONV FORM_DoPageAAction(FPDF_PAGE page,
+ FPDF_FORMHANDLE hHandle,
+ int aaType) {
CPDFSDK_FormFillEnvironment* pFormFillEnv =
HandleToCPDFSDKEnvironment(hHandle);
if (!pFormFillEnv)
@@ -730,20 +820,14 @@
if (!pFormFillEnv->GetPageView(pPage, false))
return;
- CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHander();
- CPDF_Dictionary* pPageDict = pPDFPage->m_pFormDict;
+ CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler();
+ CPDF_Dictionary* pPageDict = pPDFPage->m_pFormDict.Get();
CPDF_AAction aa(pPageDict->GetDictFor("AA"));
- if (FPDFPAGE_AACTION_OPEN == aaType) {
- if (aa.ActionExist(CPDF_AAction::OpenPage)) {
- CPDF_Action action = aa.GetAction(CPDF_AAction::OpenPage);
- pActionHandler->DoAction_Page(action, CPDF_AAction::OpenPage,
- pFormFillEnv);
- }
- } else {
- if (aa.ActionExist(CPDF_AAction::ClosePage)) {
- CPDF_Action action = aa.GetAction(CPDF_AAction::ClosePage);
- pActionHandler->DoAction_Page(action, CPDF_AAction::ClosePage,
- pFormFillEnv);
- }
+ CPDF_AAction::AActionType type = aaType == FPDFPAGE_AACTION_OPEN
+ ? CPDF_AAction::OpenPage
+ : CPDF_AAction::ClosePage;
+ if (aa.ActionExist(type)) {
+ CPDF_Action action = aa.GetAction(type);
+ pActionHandler->DoAction_Page(action, type, pFormFillEnv);
}
}
diff --git a/fpdfsdk/fpdfformfill_embeddertest.cpp b/fpdfsdk/fpdfformfill_embeddertest.cpp
index 47f1a75..ae1c02e 100644
--- a/fpdfsdk/fpdfformfill_embeddertest.cpp
+++ b/fpdfsdk/fpdfformfill_embeddertest.cpp
@@ -2,7 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/fx_system.h"
+#include "public/cpp/fpdf_deleters.h"
#include "public/fpdf_formfill.h"
+#include "public/fpdf_fwlevent.h"
#include "testing/embedder_test.h"
#include "testing/embedder_test_mock_delegate.h"
#include "testing/embedder_test_timer_handling_delegate.h"
@@ -10,9 +19,291 @@
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
-using testing::Return;
-class FPDFFormFillEmbeddertest : public EmbedderTest {};
+using FPDFFormFillEmbeddertest = EmbedderTest;
+
+// A base class for many related tests that involve clicking and typing into
+// form fields.
+class FPDFFormFillInteractiveEmbeddertest : public FPDFFormFillEmbeddertest {
+ protected:
+ FPDFFormFillInteractiveEmbeddertest() = default;
+ ~FPDFFormFillInteractiveEmbeddertest() override = default;
+
+ void SetUp() override {
+ FPDFFormFillEmbeddertest::SetUp();
+ ASSERT_TRUE(OpenDocument(GetDocumentName()));
+ page_ = LoadPage(0);
+ ASSERT_TRUE(page_);
+ FormSanityChecks();
+ }
+
+ void TearDown() override {
+ UnloadPage(page_);
+ FPDFFormFillEmbeddertest::TearDown();
+ }
+
+ // Returns the name of the PDF to use.
+ virtual const char* GetDocumentName() const = 0;
+
+ // Returns the type of field(s) in the PDF.
+ virtual int GetFormType() const = 0;
+
+ // Optionally do some sanity check on the document after loading.
+ virtual void FormSanityChecks() {}
+
+ FPDF_PAGE page() { return page_; }
+
+ int GetFormTypeAtPoint(const CFX_PointF& point) {
+ return FPDFPage_HasFormFieldAtPoint(form_handle(), page_, point.x, point.y);
+ }
+
+ void ClickOnFormFieldAtPoint(const CFX_PointF& point) {
+ // Click on the text field or combobox as specified by coordinates.
+ FORM_OnMouseMove(form_handle(), page_, 0, point.x, point.y);
+ FORM_OnLButtonDown(form_handle(), page_, 0, point.x, point.y);
+ FORM_OnLButtonUp(form_handle(), page_, 0, point.x, point.y);
+ }
+
+ void TypeTextIntoTextField(int num_chars, const CFX_PointF& point) {
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(point));
+ ClickOnFormFieldAtPoint(point);
+
+ // Type text starting with 'A' to as many chars as specified by |num_chars|.
+ for (int i = 0; i < num_chars; ++i) {
+ FORM_OnChar(form_handle(), page_, 'A' + i, 0);
+ }
+ }
+
+ // Navigates to text field using the mouse and then selects text via the
+ // shift and specfied left or right arrow key.
+ void SelectTextWithKeyboard(int num_chars,
+ int arrow_key,
+ const CFX_PointF& point) {
+ // Navigate to starting position for selection.
+ ClickOnFormFieldAtPoint(point);
+
+ // Hold down shift (and don't release until entire text is selected).
+ FORM_OnKeyDown(form_handle(), page_, FWL_VKEY_Shift, 0);
+
+ // Select text char by char via left or right arrow key.
+ for (int i = 0; i < num_chars; ++i) {
+ FORM_OnKeyDown(form_handle(), page_, arrow_key, FWL_EVENTFLAG_ShiftKey);
+ FORM_OnKeyUp(form_handle(), page_, arrow_key, FWL_EVENTFLAG_ShiftKey);
+ }
+ FORM_OnKeyUp(form_handle(), page_, FWL_VKEY_Shift, 0);
+ }
+
+ // Uses the mouse to navigate to text field and select text.
+ void SelectTextWithMouse(const CFX_PointF& start, const CFX_PointF& end) {
+ ASSERT(start.y == end.y);
+
+ // Navigate to starting position and click mouse.
+ FORM_OnMouseMove(form_handle(), page_, 0, start.x, start.y);
+ FORM_OnLButtonDown(form_handle(), page_, 0, start.x, start.y);
+
+ // Hold down mouse until reach end of desired selection.
+ FORM_OnMouseMove(form_handle(), page_, 0, end.x, end.y);
+ FORM_OnLButtonUp(form_handle(), page_, 0, end.x, end.y);
+ }
+
+ void CheckSelection(const WideStringView& expected_string) {
+ // Calculate expected length for selected text.
+ int num_chars = expected_string.GetLength();
+
+ // Check actual selection against expected selection.
+ const unsigned long expected_length =
+ sizeof(unsigned short) * (num_chars + 1);
+ unsigned long sel_text_len =
+ FORM_GetSelectedText(form_handle(), page_, nullptr, 0);
+ ASSERT_EQ(expected_length, sel_text_len);
+
+ std::vector<unsigned short> buf(sel_text_len);
+ EXPECT_EQ(expected_length, FORM_GetSelectedText(form_handle(), page_,
+ buf.data(), sel_text_len));
+
+ EXPECT_EQ(expected_string, WideString::FromUTF16LE(buf.data(), num_chars));
+ }
+
+ private:
+ FPDF_PAGE page_ = nullptr;
+};
+
+class FPDFFormFillTextFormEmbeddertest
+ : public FPDFFormFillInteractiveEmbeddertest {
+ protected:
+ FPDFFormFillTextFormEmbeddertest() = default;
+ ~FPDFFormFillTextFormEmbeddertest() override = default;
+
+ const char* GetDocumentName() const override {
+ // PDF with several form text fields:
+ // - "Text Box" - Regular text box with no special attributes.
+ // - "ReadOnly" - Ff: 1.
+ // - "CharLimit" - MaxLen: 10, V: Elephant.
+ return "text_form_multiple.pdf";
+ }
+
+ int GetFormType() const override { return FPDF_FORMFIELD_TEXTFIELD; }
+
+ void FormSanityChecks() override {
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(CharLimitFormBegin()));
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(CharLimitFormEnd()));
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(RegularFormBegin()));
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(RegularFormEnd()));
+ }
+
+ void SelectAllCharLimitFormTextWithMouse() {
+ SelectTextWithMouse(CharLimitFormEnd(), CharLimitFormBegin());
+ }
+
+ void SelectAllRegularFormTextWithMouse() {
+ SelectTextWithMouse(RegularFormEnd(), RegularFormBegin());
+ }
+
+ const CFX_PointF& CharLimitFormBegin() const {
+ static const CFX_PointF point = CharLimitFormAtX(kFormBeginX);
+ return point;
+ }
+
+ const CFX_PointF& CharLimitFormEnd() const {
+ static const CFX_PointF point = CharLimitFormAtX(kFormEndX);
+ return point;
+ }
+
+ const CFX_PointF& RegularFormBegin() const {
+ static const CFX_PointF point = RegularFormAtX(kFormBeginX);
+ return point;
+ }
+
+ const CFX_PointF& RegularFormEnd() const {
+ static const CFX_PointF point = RegularFormAtX(kFormEndX);
+ return point;
+ }
+
+ static CFX_PointF CharLimitFormAtX(float x) {
+ ASSERT(x >= kFormBeginX);
+ ASSERT(x <= kFormEndX);
+ return CFX_PointF(x, kCharLimitFormY);
+ }
+
+ static CFX_PointF RegularFormAtX(float x) {
+ ASSERT(x >= kFormBeginX);
+ ASSERT(x <= kFormEndX);
+ return CFX_PointF(x, kRegularFormY);
+ }
+
+ private:
+ static constexpr float kFormBeginX = 102.0;
+ static constexpr float kFormEndX = 195.0;
+ static constexpr float kCharLimitFormY = 60.0;
+ static constexpr float kRegularFormY = 115.0;
+};
+
+class FPDFFormFillComboBoxFormEmbeddertest
+ : public FPDFFormFillInteractiveEmbeddertest {
+ protected:
+ FPDFFormFillComboBoxFormEmbeddertest() = default;
+ ~FPDFFormFillComboBoxFormEmbeddertest() override = default;
+
+ const char* GetDocumentName() const override {
+ // PDF with form comboboxes:
+ // - "Combo_Editable" - Ff: 393216, 3 options with pair values.
+ // - "Combo1" - Ff: 131072, 3 options with single values.
+ // - "Combo_ReadOnly" - Ff: 131073, 3 options with single values.
+ return "combobox_form.pdf";
+ }
+
+ int GetFormType() const override { return FPDF_FORMFIELD_COMBOBOX; }
+
+ void FormSanityChecks() override {
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(EditableFormBegin()));
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(EditableFormEnd()));
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(EditableFormDropDown()));
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(NonEditableFormBegin()));
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(NonEditableFormEnd()));
+ EXPECT_EQ(GetFormType(), GetFormTypeAtPoint(NonEditableFormDropDown()));
+ }
+
+ void SelectEditableFormOption(int item_index) {
+ SelectOption(item_index, EditableFormDropDown());
+ }
+
+ void SelectNonEditableFormOption(int item_index) {
+ SelectOption(item_index, NonEditableFormDropDown());
+ }
+
+ void SelectAllEditableFormTextWithMouse() {
+ SelectTextWithMouse(EditableFormEnd(), EditableFormBegin());
+ }
+
+ const CFX_PointF& EditableFormBegin() const {
+ static const CFX_PointF point = EditableFormAtX(kFormBeginX);
+ return point;
+ }
+
+ const CFX_PointF& EditableFormEnd() const {
+ static const CFX_PointF point = EditableFormAtX(kFormEndX);
+ return point;
+ }
+
+ const CFX_PointF& EditableFormDropDown() const {
+ static const CFX_PointF point(kFormDropDownX, kEditableFormY);
+ return point;
+ }
+
+ const CFX_PointF& NonEditableFormBegin() const {
+ static const CFX_PointF point = NonEditableFormAtX(kFormBeginX);
+ return point;
+ }
+
+ const CFX_PointF& NonEditableFormEnd() const {
+ static const CFX_PointF point = NonEditableFormAtX(kFormEndX);
+ return point;
+ }
+
+ const CFX_PointF& NonEditableFormDropDown() const {
+ static const CFX_PointF point(kFormDropDownX, kNonEditableFormY);
+ return point;
+ }
+
+ static CFX_PointF EditableFormAtX(float x) {
+ ASSERT(x >= kFormBeginX);
+ ASSERT(x <= kFormEndX);
+ return CFX_PointF(x, kEditableFormY);
+ }
+
+ static CFX_PointF NonEditableFormAtX(float x) {
+ ASSERT(x >= kFormBeginX);
+ ASSERT(x <= kFormEndX);
+ return CFX_PointF(x, kNonEditableFormY);
+ }
+
+ private:
+ // Selects one of the pre-selected values from a combobox with three options.
+ // Options are specified by |item_index|, which is 0-based.
+ void SelectOption(int item_index, const CFX_PointF& point) {
+ // Only relevant for comboboxes with three choices and the same dimensions
+ // as those in combobox_form.pdf.
+ ASSERT(item_index >= 0);
+ ASSERT(item_index < 3);
+
+ // Navigate to button for drop down and click mouse to reveal options.
+ ClickOnFormFieldAtPoint(point);
+
+ // Calculate to Y-coordinate of dropdown option to be selected.
+ constexpr double kChoiceHeight = 15;
+ CFX_PointF option_point = point;
+ option_point.y -= kChoiceHeight * (item_index + 1);
+
+ // Navigate to option and click mouse to select it.
+ ClickOnFormFieldAtPoint(option_point);
+ }
+
+ static constexpr float kFormBeginX = 102.0;
+ static constexpr float kFormEndX = 183.0;
+ static constexpr float kFormDropDownX = 192.0;
+ static constexpr float kEditableFormY = 60.0;
+ static constexpr float kNonEditableFormY = 110.0;
+};
TEST_F(FPDFFormFillEmbeddertest, FirstTest) {
EmbedderTestMockDelegate mock;
@@ -196,4 +487,888 @@
EXPECT_EQ(0u, alerts.size());
}
+TEST_F(FPDFFormFillEmbeddertest, BUG_707673) {
+ EmbedderTestTimerHandlingDelegate delegate;
+ SetDelegate(&delegate);
+
+ EXPECT_TRUE(OpenDocument("bug_707673.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+
+ DoOpenActions();
+ FORM_OnLButtonDown(form_handle(), page, 0, 140, 590);
+ FORM_OnLButtonUp(form_handle(), page, 0, 140, 590);
+ delegate.AdvanceTime(1000);
+ UnloadPage(page);
+
+ const auto& alerts = delegate.GetAlerts();
+ EXPECT_EQ(0u, alerts.size());
+}
+
+TEST_F(FPDFFormFillEmbeddertest, BUG_765384) {
+ EXPECT_TRUE(OpenDocument("bug_765384.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+
+ DoOpenActions();
+ FORM_OnLButtonDown(form_handle(), page, 0, 140, 590);
+ FORM_OnLButtonUp(form_handle(), page, 0, 140, 590);
+ UnloadPage(page);
+}
+
#endif // PDF_ENABLE_V8
+
+TEST_F(FPDFFormFillEmbeddertest, FormText) {
+#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ const char md5_1[] = "5f11dbe575fe197a37c3fb422559f8ff";
+ const char md5_2[] = "35b1a4b679eafc749a0b6fda750c0e8d";
+ const char md5_3[] = "65c64a7c355388f719a752aa1e23f6fe";
+#else
+ const char md5_1[] = "b890950d4b9bc163b1a96797f3004b53";
+ const char md5_2[] = "11487d5597599a26e8912b9c1d9422cb";
+ const char md5_3[] = "bffe0ecea9a533f217047ee41d6be466";
+#endif
+ {
+ EXPECT_TRUE(OpenDocument("text_form.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+ std::unique_ptr<void, FPDFBitmapDeleter> bitmap1(RenderPage(page));
+ CompareBitmap(bitmap1.get(), 300, 300, md5_1);
+
+ // Click on the textfield
+ EXPECT_EQ(FPDF_FORMFIELD_TEXTFIELD,
+ FPDFPage_HasFormFieldAtPoint(form_handle(), page, 120.0, 120.0));
+ FORM_OnMouseMove(form_handle(), page, 0, 120.0, 120.0);
+ FORM_OnLButtonDown(form_handle(), page, 0, 120.0, 120.0);
+ FORM_OnLButtonUp(form_handle(), page, 0, 120.0, 120.0);
+
+ // Write "ABC"
+ FORM_OnChar(form_handle(), page, 65, 0);
+ FORM_OnChar(form_handle(), page, 66, 0);
+ FORM_OnChar(form_handle(), page, 67, 0);
+ std::unique_ptr<void, FPDFBitmapDeleter> bitmap2(RenderPage(page));
+ CompareBitmap(bitmap2.get(), 300, 300, md5_2);
+
+ // Take out focus by clicking out of the textfield
+ FORM_OnMouseMove(form_handle(), page, 0, 15.0, 15.0);
+ FORM_OnLButtonDown(form_handle(), page, 0, 15.0, 15.0);
+ FORM_OnLButtonUp(form_handle(), page, 0, 15.0, 15.0);
+ std::unique_ptr<void, FPDFBitmapDeleter> bitmap3(RenderPage(page));
+ CompareBitmap(bitmap3.get(), 300, 300, md5_3);
+
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+
+ // Close page
+ UnloadPage(page);
+ }
+ // Check saved document
+ VerifySavedDocument(300, 300, md5_3);
+}
+
+TEST_F(FPDFFormFillEmbeddertest, HasFormInfoNone) {
+ EXPECT_TRUE(OpenDocument("hello_world.pdf"));
+ EXPECT_EQ(FORMTYPE_NONE, FPDF_GetFormType(document_));
+}
+
+TEST_F(FPDFFormFillEmbeddertest, HasFormInfoAcroForm) {
+ EXPECT_TRUE(OpenDocument("text_form.pdf"));
+ EXPECT_EQ(FORMTYPE_ACRO_FORM, FPDF_GetFormType(document_));
+}
+
+TEST_F(FPDFFormFillEmbeddertest, HasFormInfoXFAFull) {
+ EXPECT_TRUE(OpenDocument("simple_xfa.pdf"));
+ EXPECT_EQ(FORMTYPE_XFA_FULL, FPDF_GetFormType(document_));
+}
+
+TEST_F(FPDFFormFillEmbeddertest, HasFormInfoXFAForeground) {
+ EXPECT_TRUE(OpenDocument("bug_216.pdf"));
+ EXPECT_EQ(FORMTYPE_XFA_FOREGROUND, FPDF_GetFormType(document_));
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextEmptyAndBasicKeyboard) {
+ // Test empty selection.
+ CheckSelection(L"");
+
+ // Test basic selection.
+ TypeTextIntoTextField(3, RegularFormBegin());
+ SelectTextWithKeyboard(3, FWL_VKEY_Left, RegularFormAtX(123.0));
+ CheckSelection(L"ABC");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextEmptyAndBasicMouse) {
+ // Test empty selection.
+ CheckSelection(L"");
+
+ // Test basic selection.
+ TypeTextIntoTextField(3, RegularFormBegin());
+ SelectTextWithMouse(RegularFormAtX(125.0), RegularFormBegin());
+ CheckSelection(L"ABC");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextFragmentsKeyBoard) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Test selecting first character in forward direction.
+ SelectTextWithKeyboard(1, FWL_VKEY_Right, RegularFormBegin());
+ CheckSelection(L"A");
+
+ // Test selecting entire long string in backwards direction.
+ SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"ABCDEFGHIJKL");
+
+ // Test selecting middle section in backwards direction.
+ SelectTextWithKeyboard(6, FWL_VKEY_Left, RegularFormAtX(170.0));
+ CheckSelection(L"DEFGHI");
+
+ // Test selecting middle selection in forward direction.
+ SelectTextWithKeyboard(6, FWL_VKEY_Right, RegularFormAtX(125.0));
+ CheckSelection(L"DEFGHI");
+
+ // Test selecting last character in backwards direction.
+ SelectTextWithKeyboard(1, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"L");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextFragmentsMouse) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Test selecting first character in forward direction.
+ SelectTextWithMouse(RegularFormBegin(), RegularFormAtX(106.0));
+ CheckSelection(L"A");
+
+ // Test selecting entire long string in backwards direction.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"ABCDEFGHIJKL");
+
+ // Test selecting middle section in backwards direction.
+ SelectTextWithMouse(RegularFormAtX(170.0), RegularFormAtX(125.0));
+ CheckSelection(L"DEFGHI");
+
+ // Test selecting middle selection in forward direction.
+ SelectTextWithMouse(RegularFormAtX(125.0), RegularFormAtX(170.0));
+ CheckSelection(L"DEFGHI");
+
+ // Test selecting last character in backwards direction.
+ SelectTextWithMouse(RegularFormEnd(), RegularFormAtX(186.0));
+ CheckSelection(L"L");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ GetSelectedTextEmptyAndBasicNormalComboBox) {
+ // Test empty selection.
+ CheckSelection(L"");
+
+ // Non-editable comboboxes don't allow selection with keyboard.
+ SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(142.0));
+ CheckSelection(L"Banana");
+
+ // Select other another provided option.
+ SelectNonEditableFormOption(0);
+ CheckSelection(L"Apple");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ GetSelectedTextEmptyAndBasicEditableComboBoxKeyboard) {
+ // Test empty selection.
+ CheckSelection(L"");
+
+ // Test basic selection of text within user editable combobox using keyboard.
+ TypeTextIntoTextField(3, EditableFormBegin());
+ SelectTextWithKeyboard(3, FWL_VKEY_Left, EditableFormAtX(128.0));
+ CheckSelection(L"ABC");
+
+ // Select a provided option.
+ SelectEditableFormOption(1);
+ CheckSelection(L"Bar");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ GetSelectedTextEmptyAndBasicEditableComboBoxMouse) {
+ // Test empty selection.
+ CheckSelection(L"");
+
+ // Test basic selection of text within user editable combobox using mouse.
+ TypeTextIntoTextField(3, EditableFormBegin());
+ SelectTextWithMouse(EditableFormAtX(128.0), EditableFormBegin());
+ CheckSelection(L"ABC");
+
+ // Select a provided option.
+ SelectEditableFormOption(2);
+ CheckSelection(L"Qux");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ GetSelectedTextFragmentsNormalComboBox) {
+ // Test selecting first character in forward direction.
+ SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(107.0));
+ CheckSelection(L"B");
+
+ // Test selecting entire string in backwards direction.
+ SelectTextWithMouse(NonEditableFormAtX(142.0), NonEditableFormBegin());
+ CheckSelection(L"Banana");
+
+ // Test selecting middle section in backwards direction.
+ SelectTextWithMouse(NonEditableFormAtX(135.0), NonEditableFormAtX(117.0));
+ CheckSelection(L"nan");
+
+ // Test selecting middle section in forward direction.
+ SelectTextWithMouse(NonEditableFormAtX(117.0), NonEditableFormAtX(135.0));
+ CheckSelection(L"nan");
+
+ // Test selecting last character in backwards direction.
+ SelectTextWithMouse(NonEditableFormAtX(142.0), NonEditableFormAtX(138.0));
+ CheckSelection(L"a");
+
+ // Select another option and then reset selection as first three chars.
+ SelectNonEditableFormOption(2);
+ CheckSelection(L"Cherry");
+ SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(122.0));
+ CheckSelection(L"Che");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ GetSelectedTextFragmentsEditableComboBoxKeyboard) {
+ TypeTextIntoTextField(10, EditableFormBegin());
+
+ // Test selecting first character in forward direction.
+ SelectTextWithKeyboard(1, FWL_VKEY_Right, EditableFormBegin());
+ CheckSelection(L"A");
+
+ // Test selecting entire long string in backwards direction.
+ SelectTextWithKeyboard(10, FWL_VKEY_Left, EditableFormEnd());
+ CheckSelection(L"ABCDEFGHIJ");
+
+ // Test selecting middle section in backwards direction.
+ SelectTextWithKeyboard(5, FWL_VKEY_Left, EditableFormAtX(168.0));
+ CheckSelection(L"DEFGH");
+
+ // Test selecting middle selection in forward direction.
+ SelectTextWithKeyboard(5, FWL_VKEY_Right, EditableFormAtX(127.0));
+ CheckSelection(L"DEFGH");
+
+ // Test selecting last character in backwards direction.
+ SelectTextWithKeyboard(1, FWL_VKEY_Left, EditableFormEnd());
+ CheckSelection(L"J");
+
+ // Select a provided option and then reset selection as first two chars.
+ SelectEditableFormOption(0);
+ CheckSelection(L"Foo");
+ SelectTextWithKeyboard(2, FWL_VKEY_Right, EditableFormBegin());
+ CheckSelection(L"Fo");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ GetSelectedTextFragmentsEditableComboBoxMouse) {
+ TypeTextIntoTextField(10, EditableFormBegin());
+
+ // Test selecting first character in forward direction.
+ SelectTextWithMouse(EditableFormBegin(), EditableFormAtX(107.0));
+ CheckSelection(L"A");
+
+ // Test selecting entire long string in backwards direction.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCDEFGHIJ");
+
+ // Test selecting middle section in backwards direction.
+ SelectTextWithMouse(EditableFormAtX(168.0), EditableFormAtX(127.0));
+ CheckSelection(L"DEFGH");
+
+ // Test selecting middle selection in forward direction.
+ SelectTextWithMouse(EditableFormAtX(127.0), EditableFormAtX(168.0));
+ CheckSelection(L"DEFGH");
+
+ // Test selecting last character in backwards direction.
+ SelectTextWithMouse(EditableFormEnd(), EditableFormAtX(174.0));
+ CheckSelection(L"J");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldEntireSelection) {
+ // Select entire contents of text field.
+ TypeTextIntoTextField(12, RegularFormBegin());
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"ABCDEFGHIJKL");
+
+ // Test deleting current text selection. Select what remains after deletion to
+ // check that remaining text is as expected.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+
+ SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldSelectionMiddle) {
+ // Select middle section of text.
+ TypeTextIntoTextField(12, RegularFormBegin());
+ SelectTextWithMouse(RegularFormAtX(170.0), RegularFormAtX(125.0));
+ CheckSelection(L"DEFGHI");
+
+ // Test deleting current text selection. Select what remains after deletion to
+ // check that remaining text is as expected.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"ABCJKL");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldSelectionLeft) {
+ // Select first few characters of text.
+ TypeTextIntoTextField(12, RegularFormBegin());
+ SelectTextWithMouse(RegularFormBegin(), RegularFormAtX(132.0));
+ CheckSelection(L"ABCD");
+
+ // Test deleting current text selection. Select what remains after deletion to
+ // check that remaining text is as expected.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"EFGHIJKL");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldSelectionRight) {
+ // Select last few characters of text.
+ TypeTextIntoTextField(12, RegularFormBegin());
+ SelectTextWithMouse(RegularFormEnd(), RegularFormAtX(165.0));
+ CheckSelection(L"IJKL");
+
+ // Test deleting current text selection. Select what remains after deletion to
+ // check that remaining text is as expected.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"ABCDEFGH");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteEmptyTextFieldSelection) {
+ // Do not select text.
+ TypeTextIntoTextField(12, RegularFormBegin());
+ CheckSelection(L"");
+
+ // Test that attempt to delete empty text selection has no effect.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"ABCDEFGHIJKL");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ DeleteEditableComboBoxEntireSelection) {
+ // Select entire contents of user-editable combobox text field.
+ TypeTextIntoTextField(10, EditableFormBegin());
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCDEFGHIJ");
+
+ // Test deleting current text selection. Select what remains after deletion to
+ // check that remaining text is as expected.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ DeleteEditableComboBoxSelectionMiddle) {
+ // Select middle section of text.
+ TypeTextIntoTextField(10, EditableFormBegin());
+ SelectTextWithMouse(EditableFormAtX(168.0), EditableFormAtX(127.0));
+ CheckSelection(L"DEFGH");
+
+ // Test deleting current text selection. Select what remains after deletion to
+ // check that remaining text is as expected.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCIJ");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ DeleteEditableComboBoxSelectionLeft) {
+ // Select first few characters of text.
+ TypeTextIntoTextField(10, EditableFormBegin());
+ SelectTextWithMouse(EditableFormBegin(), EditableFormAtX(132.0));
+ CheckSelection(L"ABCD");
+
+ // Test deleting current text selection. Select what remains after deletion to
+ // check that remaining text is as expected.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"EFGHIJ");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ DeleteEditableComboBoxSelectionRight) {
+ // Select last few characters of text.
+ TypeTextIntoTextField(10, EditableFormBegin());
+ SelectTextWithMouse(EditableFormEnd(), EditableFormAtX(152.0));
+ CheckSelection(L"GHIJ");
+
+ // Test deleting current text selection. Select what remains after deletion to
+ // check that remaining text is as expected.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCDEF");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ DeleteEmptyEditableComboBoxSelection) {
+ // Do not select text.
+ TypeTextIntoTextField(10, EditableFormBegin());
+ CheckSelection(L"");
+
+ // Test that attempt to delete empty text selection has no effect.
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCDEFGHIJ");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInEmptyTextField) {
+ ClickOnFormFieldAtPoint(RegularFormBegin());
+
+ // Test inserting text into empty text field.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"Hello");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInPopulatedTextFieldLeft) {
+ TypeTextIntoTextField(8, RegularFormBegin());
+
+ // Click on the leftmost part of the text field.
+ ClickOnFormFieldAtPoint(RegularFormBegin());
+
+ // Test inserting text in front of existing text in text field.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"HelloABCDEFGH");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInPopulatedTextFieldMiddle) {
+ TypeTextIntoTextField(8, RegularFormBegin());
+
+ // Click on the middle of the text field.
+ ClickOnFormFieldAtPoint(RegularFormAtX(134.0));
+
+ // Test inserting text in the middle of existing text in text field.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"ABCDHelloEFGH");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInPopulatedTextFieldRight) {
+ TypeTextIntoTextField(8, RegularFormBegin());
+
+ // Click on the rightmost part of the text field.
+ ClickOnFormFieldAtPoint(RegularFormAtX(166.0));
+
+ // Test inserting text behind existing text in text field.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"ABCDEFGHHello");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedTextFieldWhole) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Select entire string in text field.
+ SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"ABCDEFGHIJKL");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"Hello");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedTextFieldLeft) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Select left portion of string in text field.
+ SelectTextWithKeyboard(6, FWL_VKEY_Left, RegularFormAtX(148.0));
+ CheckSelection(L"ABCDEF");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"HelloGHIJKL");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedTextFieldMiddle) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Select middle portion of string in text field.
+ SelectTextWithKeyboard(6, FWL_VKEY_Left, RegularFormAtX(171.0));
+ CheckSelection(L"DEFGHI");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"ABCHelloJKL");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedTextFieldRight) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Select right portion of string in text field.
+ SelectTextWithKeyboard(6, FWL_VKEY_Left, RegularFormEnd());
+ CheckSelection(L"GHIJKL");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllRegularFormTextWithMouse();
+ CheckSelection(L"ABCDEFHello");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ InsertTextInEmptyEditableComboBox) {
+ ClickOnFormFieldAtPoint(EditableFormBegin());
+
+ // Test inserting text into empty user-editable combobox.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of user-editable combobox text field to check that
+ // insertion worked as expected.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"Hello");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ InsertTextInPopulatedEditableComboBoxLeft) {
+ TypeTextIntoTextField(6, EditableFormBegin());
+
+ // Click on the leftmost part of the user-editable combobox.
+ ClickOnFormFieldAtPoint(EditableFormBegin());
+
+ // Test inserting text in front of existing text in user-editable combobox.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of user-editable combobox text field to check that
+ // insertion worked as expected.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"HelloABCDEF");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ InsertTextInPopulatedEditableComboBoxMiddle) {
+ TypeTextIntoTextField(6, EditableFormBegin());
+
+ // Click on the middle of the user-editable combobox.
+ ClickOnFormFieldAtPoint(EditableFormAtX(126.0));
+
+ // Test inserting text in the middle of existing text in user-editable
+ // combobox.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of user-editable combobox text field to check that
+ // insertion worked as expected.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCHelloDEF");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ InsertTextInPopulatedEditableComboBoxRight) {
+ TypeTextIntoTextField(6, EditableFormBegin());
+
+ // Click on the rightmost part of the user-editable combobox.
+ ClickOnFormFieldAtPoint(EditableFormEnd());
+
+ // Test inserting text behind existing text in user-editable combobox.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of user-editable combobox text field to check that
+ // insertion worked as expected.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCDEFHello");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole) {
+ TypeTextIntoTextField(10, EditableFormBegin());
+
+ // Select entire string in user-editable combobox.
+ SelectTextWithKeyboard(10, FWL_VKEY_Left, EditableFormEnd());
+ CheckSelection(L"ABCDEFGHIJ");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of user-editable combobox text field to check that
+ // insertion worked as expected.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"Hello");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft) {
+ TypeTextIntoTextField(10, EditableFormBegin());
+
+ // Select left portion of string in user-editable combobox.
+ SelectTextWithKeyboard(5, FWL_VKEY_Left, EditableFormAtX(142.0));
+ CheckSelection(L"ABCDE");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of user-editable combobox text field to check that
+ // insertion worked as expected.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"HelloFGHIJ");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle) {
+ TypeTextIntoTextField(10, EditableFormBegin());
+
+ // Select middle portion of string in user-editable combobox.
+ SelectTextWithKeyboard(5, FWL_VKEY_Left, EditableFormAtX(167.0));
+ CheckSelection(L"DEFGH");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of user-editable combobox text field to check that
+ // insertion worked as expected.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCHelloIJ");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight) {
+ TypeTextIntoTextField(10, EditableFormBegin());
+
+ // Select right portion of string in user-editable combobox.
+ SelectTextWithKeyboard(5, FWL_VKEY_Left, EditableFormEnd());
+ CheckSelection(L"FGHIJ");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hello");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of user-editable combobox text field to check that
+ // insertion worked as expected.
+ SelectAllEditableFormTextWithMouse();
+ CheckSelection(L"ABCDEHello");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextInEmptyCharLimitTextFieldOverflow) {
+ // Click on the textfield.
+ ClickOnFormFieldAtPoint(CharLimitFormEnd());
+
+ // Delete pre-filled contents of text field with char limit.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"Elephant");
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+
+ // Test inserting text into now empty text field so text to be inserted
+ // exceeds the char limit and is cut off.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hippopotamus");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"Hippopotam");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextInEmptyCharLimitTextFieldFit) {
+ // Click on the textfield.
+ ClickOnFormFieldAtPoint(CharLimitFormEnd());
+
+ // Delete pre-filled contents of text field with char limit.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"Elephant");
+ FORM_ReplaceSelection(form_handle(), page(), nullptr);
+
+ // Test inserting text into now empty text field so text to be inserted
+ // exceeds the char limit and is cut off.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Zebra");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"Zebra");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextInPopulatedCharLimitTextFieldLeft) {
+ // Click on the leftmost part of the text field.
+ ClickOnFormFieldAtPoint(CharLimitFormBegin());
+
+ // Test inserting text in front of existing text in text field.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hippopotamus");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"HiElephant");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextInPopulatedCharLimitTextFieldMiddle) {
+ TypeTextIntoTextField(8, RegularFormBegin());
+
+ // Click on the middle of the text field.
+ ClickOnFormFieldAtPoint(CharLimitFormAtX(134.0));
+
+ // Test inserting text in the middle of existing text in text field.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hippopotamus");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"ElephHiant");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextInPopulatedCharLimitTextFieldRight) {
+ TypeTextIntoTextField(8, RegularFormBegin());
+
+ // Click on the rightmost part of the text field.
+ ClickOnFormFieldAtPoint(CharLimitFormAtX(166.0));
+
+ // Test inserting text behind existing text in text field.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hippopotamus");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"ElephantHi");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldWhole) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Select entire string in text field.
+ SelectTextWithKeyboard(12, FWL_VKEY_Left, CharLimitFormEnd());
+ CheckSelection(L"Elephant");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hippopotamus");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"Hippopotam");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldLeft) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Select left portion of string in text field.
+ SelectTextWithKeyboard(4, FWL_VKEY_Left, CharLimitFormAtX(122.0));
+ CheckSelection(L"Elep");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hippopotamus");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"Hippophant");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldMiddle) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Select middle portion of string in text field.
+ SelectTextWithKeyboard(4, FWL_VKEY_Left, CharLimitFormAtX(136.0));
+ CheckSelection(L"epha");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hippopotamus");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"ElHippopnt");
+}
+
+TEST_F(FPDFFormFillTextFormEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldRight) {
+ TypeTextIntoTextField(12, RegularFormBegin());
+
+ // Select right portion of string in text field.
+ SelectTextWithKeyboard(4, FWL_VKEY_Left, CharLimitFormAtX(152.0));
+ CheckSelection(L"hant");
+
+ // Test replacing text selection with text to be inserted.
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
+ GetFPDFWideString(L"Hippopotamus");
+ FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+
+ // Select entire contents of text field to check that insertion worked
+ // as expected.
+ SelectAllCharLimitFormTextWithMouse();
+ CheckSelection(L"ElepHippop");
+}
diff --git a/fpdfsdk/fpdfppo.cpp b/fpdfsdk/fpdfppo.cpp
index 4e06856..d88f910 100644
--- a/fpdfsdk/fpdfppo.cpp
+++ b/fpdfsdk/fpdfppo.cpp
@@ -18,14 +18,14 @@
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_string.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/fsdk_define.h"
#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
namespace {
CPDF_Object* PageDictGetInheritableTag(CPDF_Dictionary* pDict,
- const CFX_ByteString& bsSrcTag) {
+ const ByteString& bsSrcTag) {
if (!pDict || bsSrcTag.IsEmpty())
return nullptr;
if (!pDict->KeyExist("Parent") || !pDict->KeyExist("Type"))
@@ -57,7 +57,7 @@
bool CopyInheritable(CPDF_Dictionary* pCurPageDict,
CPDF_Dictionary* pSrcPageDict,
- const CFX_ByteString& key) {
+ const ByteString& key) {
if (pCurPageDict->KeyExist(key))
return true;
@@ -69,54 +69,57 @@
return true;
}
-bool ParserPageRangeString(CFX_ByteString rangstring,
+bool ParserPageRangeString(ByteString rangstring,
std::vector<uint16_t>* pageArray,
int nCount) {
if (rangstring.IsEmpty())
return true;
rangstring.Remove(' ');
- int nLength = rangstring.GetLength();
- CFX_ByteString cbCompareString("0123456789-,");
- for (int i = 0; i < nLength; ++i) {
- if (cbCompareString.Find(rangstring[i]) == -1)
+ size_t nLength = rangstring.GetLength();
+ ByteString cbCompareString("0123456789-,");
+ for (size_t i = 0; i < nLength; ++i) {
+ if (!cbCompareString.Contains(rangstring[i]))
return false;
}
- CFX_ByteString cbMidRange;
- int nStringFrom = 0;
- int nStringTo = 0;
+ ByteString cbMidRange;
+ size_t nStringFrom = 0;
+ Optional<size_t> nStringTo = 0;
while (nStringTo < nLength) {
nStringTo = rangstring.Find(',', nStringFrom);
- if (nStringTo == -1)
+ if (!nStringTo.has_value())
nStringTo = nLength;
- cbMidRange = rangstring.Mid(nStringFrom, nStringTo - nStringFrom);
- int nMid = cbMidRange.Find('-');
- if (nMid == -1) {
- long lPageNum = atol(cbMidRange.c_str());
- if (lPageNum <= 0 || lPageNum > nCount)
+ cbMidRange = rangstring.Mid(nStringFrom, nStringTo.value() - nStringFrom);
+ auto nMid = cbMidRange.Find('-');
+ if (!nMid.has_value()) {
+ uint16_t pageNum =
+ pdfium::base::checked_cast<uint16_t>(atoi(cbMidRange.c_str()));
+ if (pageNum <= 0 || pageNum > nCount)
return false;
- pageArray->push_back((uint16_t)lPageNum);
+ pageArray->push_back(pageNum);
} else {
- int nStartPageNum = atol(cbMidRange.Mid(0, nMid).c_str());
+ uint16_t nStartPageNum = pdfium::base::checked_cast<uint16_t>(
+ atoi(cbMidRange.Left(nMid.value()).c_str()));
if (nStartPageNum == 0)
return false;
- ++nMid;
- int nEnd = cbMidRange.GetLength() - nMid;
+ nMid = nMid.value() + 1;
+ size_t nEnd = cbMidRange.GetLength() - nMid.value();
if (nEnd == 0)
return false;
- int nEndPageNum = atol(cbMidRange.Mid(nMid, nEnd).c_str());
+ uint16_t nEndPageNum = pdfium::base::checked_cast<uint16_t>(
+ atoi(cbMidRange.Mid(nMid.value(), nEnd).c_str()));
if (nStartPageNum < 0 || nStartPageNum > nEndPageNum ||
nEndPageNum > nCount) {
return false;
}
- for (int i = nStartPageNum; i <= nEndPageNum; ++i) {
+ for (uint16_t i = nStartPageNum; i <= nEndPageNum; ++i) {
pageArray->push_back(i);
}
}
- nStringFrom = nStringTo + 1;
+ nStringFrom = nStringTo.value() + 1;
}
return true;
}
@@ -137,8 +140,8 @@
bool UpdateReference(CPDF_Object* pObj, ObjectNumberMap* pObjNumberMap);
uint32_t GetNewObjId(ObjectNumberMap* pObjNumberMap, CPDF_Reference* pRef);
- CPDF_Document* m_pDestPDFDoc;
- CPDF_Document* m_pSrcPDFDoc;
+ UnownedPtr<CPDF_Document> m_pDestPDFDoc;
+ UnownedPtr<CPDF_Document> m_pSrcPDFDoc;
};
CPDF_PageOrganizer::CPDF_PageOrganizer(CPDF_Document* pDestPDFDoc,
@@ -161,7 +164,7 @@
pDocInfoDict->SetNewFor<CPDF_String>("Producer", "PDFium", false);
- CFX_ByteString cbRootType = pNewRoot->GetStringFor("Type", "");
+ ByteString cbRootType = pNewRoot->GetStringFor("Type", "");
if (cbRootType.IsEmpty())
pNewRoot->SetNewFor<CPDF_Name>("Type", "Catalog");
@@ -170,18 +173,18 @@
pElement ? ToDictionary(pElement->GetDirect()) : nullptr;
if (!pNewPages) {
pNewPages = m_pDestPDFDoc->NewIndirect<CPDF_Dictionary>();
- pNewRoot->SetNewFor<CPDF_Reference>("Pages", m_pDestPDFDoc,
+ pNewRoot->SetNewFor<CPDF_Reference>("Pages", m_pDestPDFDoc.Get(),
pNewPages->GetObjNum());
}
- CFX_ByteString cbPageType = pNewPages->GetStringFor("Type", "");
+ ByteString cbPageType = pNewPages->GetStringFor("Type", "");
if (cbPageType.IsEmpty())
pNewPages->SetNewFor<CPDF_Name>("Type", "Pages");
if (!pNewPages->GetArrayFor("Kids")) {
pNewPages->SetNewFor<CPDF_Number>("Count", 0);
pNewPages->SetNewFor<CPDF_Reference>(
- "Kids", m_pDestPDFDoc,
+ "Kids", m_pDestPDFDoc.Get(),
m_pDestPDFDoc->NewIndirect<CPDF_Array>()->GetObjNum());
}
@@ -192,8 +195,7 @@
int nIndex) {
int curpage = nIndex;
auto pObjNumberMap = pdfium::MakeUnique<ObjectNumberMap>();
- int nSize = pdfium::CollectionSize<int>(pageNums);
- for (int i = 0; i < nSize; ++i) {
+ for (size_t i = 0; i < pageNums.size(); ++i) {
CPDF_Dictionary* pCurPageDict = m_pDestPDFDoc->CreateNewPage(curpage);
CPDF_Dictionary* pSrcPageDict = m_pSrcPDFDoc->GetPage(pageNums[i] - 1);
if (!pSrcPageDict || !pCurPageDict)
@@ -201,7 +203,7 @@
// Clone the page dictionary
for (const auto& it : *pSrcPageDict) {
- const CFX_ByteString& cbSrcKeyStr = it.first;
+ const ByteString& cbSrcKeyStr = it.first;
if (cbSrcKeyStr == "Type" || cbSrcKeyStr == "Parent")
continue;
@@ -210,16 +212,18 @@
}
// inheritable item
+ // Even though some entries are required by the PDF spec, there exist
+ // PDFs that omit them. Set some defaults in this case.
// 1 MediaBox - required
if (!CopyInheritable(pCurPageDict, pSrcPageDict, "MediaBox")) {
- // Search for "CropBox" in the source page dictionary,
- // if it does not exists, use the default letter size.
+ // Search for "CropBox" in the source page dictionary.
+ // If it does not exist, use the default letter size.
CPDF_Object* pInheritable =
PageDictGetInheritableTag(pSrcPageDict, "CropBox");
if (pInheritable) {
pCurPageDict->SetFor("MediaBox", pInheritable->Clone());
} else {
- // Make the default size to be letter size (8.5'x11')
+ // Make the default size letter size (8.5"x11")
CPDF_Array* pArray = pCurPageDict->SetNewFor<CPDF_Array>("MediaBox");
pArray->AddNew<CPDF_Number>(0);
pArray->AddNew<CPDF_Number>(0);
@@ -229,8 +233,10 @@
}
// 2 Resources - required
- if (!CopyInheritable(pCurPageDict, pSrcPageDict, "Resources"))
- return false;
+ if (!CopyInheritable(pCurPageDict, pSrcPageDict, "Resources")) {
+ // Use a default empty resources if it does not exist.
+ pCurPageDict->SetNewFor<CPDF_Dictionary>("Resources");
+ }
// 3 CropBox - optional
CopyInheritable(pCurPageDict, pSrcPageDict, "CropBox");
@@ -256,14 +262,14 @@
uint32_t newobjnum = GetNewObjId(pObjNumberMap, pReference);
if (newobjnum == 0)
return false;
- pReference->SetRef(m_pDestPDFDoc, newobjnum);
+ pReference->SetRef(m_pDestPDFDoc.Get(), newobjnum);
break;
}
case CPDF_Object::DICTIONARY: {
CPDF_Dictionary* pDict = pObj->AsDictionary();
auto it = pDict->begin();
while (it != pDict->end()) {
- const CFX_ByteString& key = it->first;
+ const ByteString& key = it->first;
CPDF_Object* pNextObj = it->second.get();
++it;
if (key == "Parent" || key == "Prev" || key == "First")
@@ -322,7 +328,7 @@
std::unique_ptr<CPDF_Object> pClone = pDirect->Clone();
if (CPDF_Dictionary* pDictClone = pClone->AsDictionary()) {
if (pDictClone->KeyExist("Type")) {
- CFX_ByteString strType = pDictClone->GetStringFor("Type");
+ ByteString strType = pDictClone->GetStringFor("Type");
if (!FXSYS_stricmp(strType.c_str(), "Pages"))
return 4;
if (!FXSYS_stricmp(strType.c_str(), "Page"))
@@ -339,10 +345,10 @@
return dwNewObjNum;
}
-DLLEXPORT FPDF_BOOL STDCALL FPDF_ImportPages(FPDF_DOCUMENT dest_doc,
- FPDF_DOCUMENT src_doc,
- FPDF_BYTESTRING pagerange,
- int index) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPages(FPDF_DOCUMENT dest_doc,
+ FPDF_DOCUMENT src_doc,
+ FPDF_BYTESTRING pagerange,
+ int index) {
CPDF_Document* pDestDoc = CPDFDocumentFromFPDFDocument(dest_doc);
if (!dest_doc)
return false;
@@ -366,8 +372,8 @@
return pageOrg.PDFDocInit() && pageOrg.ExportPage(pageArray, index);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc,
- FPDF_DOCUMENT src_doc) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc) {
CPDF_Document* pDstDoc = CPDFDocumentFromFPDFDocument(dest_doc);
if (!pDstDoc)
return false;
diff --git a/fpdfsdk/fpdfppo_embeddertest.cpp b/fpdfsdk/fpdfppo_embeddertest.cpp
index 0972316..c642b71 100644
--- a/fpdfsdk/fpdfppo_embeddertest.cpp
+++ b/fpdfsdk/fpdfppo_embeddertest.cpp
@@ -1,11 +1,11 @@
// Copyright 2016 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.
+#include <string>
-#include "public/fpdf_ppo.h"
-
-#include "core/fxcrt/fx_basic.h"
#include "public/fpdf_edit.h"
+#include "public/fpdf_ppo.h"
+#include "public/fpdf_save.h"
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -15,6 +15,12 @@
class FPDFPPOEmbeddertest : public EmbedderTest {};
+int FakeBlockWriter(FPDF_FILEWRITE* pThis,
+ const void* pData,
+ unsigned long size) {
+ return size;
+}
+
} // namespace
TEST_F(FPDFPPOEmbeddertest, NoViewerPreferences) {
@@ -36,13 +42,13 @@
}
TEST_F(FPDFPPOEmbeddertest, ImportPages) {
- EXPECT_TRUE(OpenDocument("viewer_ref.pdf"));
+ ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
FPDF_PAGE page = LoadPage(0);
EXPECT_TRUE(page);
FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
- EXPECT_TRUE(output_doc);
+ ASSERT_TRUE(output_doc);
EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document()));
EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "1", 0));
EXPECT_EQ(1, FPDF_GetPageCount(output_doc));
@@ -51,6 +57,36 @@
UnloadPage(page);
}
+TEST_F(FPDFPPOEmbeddertest, BadRepeatViewerPref) {
+ ASSERT_TRUE(OpenDocument("repeat_viewer_ref.pdf"));
+
+ FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
+ EXPECT_TRUE(output_doc);
+ EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document()));
+
+ FPDF_FILEWRITE writer;
+ writer.version = 1;
+ writer.WriteBlock = FakeBlockWriter;
+
+ EXPECT_TRUE(FPDF_SaveAsCopy(output_doc, &writer, 0));
+ FPDF_CloseDocument(output_doc);
+}
+
+TEST_F(FPDFPPOEmbeddertest, BadCircularViewerPref) {
+ ASSERT_TRUE(OpenDocument("circular_viewer_ref.pdf"));
+
+ FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
+ EXPECT_TRUE(output_doc);
+ EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc, document()));
+
+ FPDF_FILEWRITE writer;
+ writer.version = 1;
+ writer.WriteBlock = FakeBlockWriter;
+
+ EXPECT_TRUE(FPDF_SaveAsCopy(output_doc, &writer, 0));
+ FPDF_CloseDocument(output_doc);
+}
+
TEST_F(FPDFPPOEmbeddertest, BadRanges) {
EXPECT_TRUE(OpenDocument("viewer_ref.pdf"));
@@ -95,7 +131,7 @@
EXPECT_TRUE(OpenDocument("bug_664284.pdf"));
FPDF_PAGE page = LoadPage(0);
- EXPECT_TRUE(page);
+ ASSERT_NE(nullptr, page);
FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
EXPECT_TRUE(output_doc);
@@ -104,3 +140,81 @@
UnloadPage(page);
}
+
+TEST_F(FPDFPPOEmbeddertest, BUG_750568) {
+ const char* const kHashes[] = {
+ "64ad08132a1c5a166768298c8a578f57", "83b83e2f6bc80707d0a917c7634140b9",
+ "913cd3723a451e4e46fbc2c05702d1ee", "81fb7cfd4860f855eb468f73dfeb6d60"};
+
+ ASSERT_TRUE(OpenDocument("bug_750568.pdf"));
+ ASSERT_EQ(4, FPDF_GetPageCount(document()));
+
+ for (size_t i = 0; i < 4; ++i) {
+ FPDF_PAGE page = LoadPage(i);
+ ASSERT_NE(nullptr, page);
+
+ FPDF_BITMAP bitmap = RenderPage(page);
+ ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap));
+ ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap));
+ ASSERT_EQ(800, FPDFBitmap_GetStride(bitmap));
+
+ std::string digest = HashBitmap(bitmap);
+ FPDFBitmap_Destroy(bitmap);
+ UnloadPage(page);
+ EXPECT_EQ(kHashes[i], digest);
+ }
+
+ FPDF_DOCUMENT output_doc = FPDF_CreateNewDocument();
+ ASSERT_TRUE(output_doc);
+ EXPECT_TRUE(FPDF_ImportPages(output_doc, document(), "1,2,3,4", 0));
+ ASSERT_EQ(4, FPDF_GetPageCount(output_doc));
+ for (size_t i = 0; i < 4; ++i) {
+ FPDF_PAGE page = FPDF_LoadPage(output_doc, i);
+ ASSERT_NE(nullptr, page);
+
+ FPDF_BITMAP bitmap = RenderPage(page);
+ ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap));
+ ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap));
+ ASSERT_EQ(800, FPDFBitmap_GetStride(bitmap));
+
+ std::string digest = HashBitmap(bitmap);
+ FPDFBitmap_Destroy(bitmap);
+ FPDF_ClosePage(page);
+ EXPECT_EQ(kHashes[i], digest);
+ }
+ FPDF_CloseDocument(output_doc);
+}
+
+TEST_F(FPDFPPOEmbeddertest, ImportWithZeroLengthStream) {
+ EXPECT_TRUE(OpenDocument("zero_length_stream.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_NE(nullptr, page);
+
+ FPDF_BITMAP bitmap = RenderPage(page);
+ ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap));
+ ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap));
+ ASSERT_EQ(800, FPDFBitmap_GetStride(bitmap));
+
+ std::string digest = HashBitmap(bitmap);
+ FPDFBitmap_Destroy(bitmap);
+ FPDF_ClosePage(page);
+
+ FPDF_DOCUMENT new_doc = FPDF_CreateNewDocument();
+ EXPECT_TRUE(new_doc);
+ EXPECT_TRUE(FPDF_ImportPages(new_doc, document(), "1", 0));
+
+ EXPECT_EQ(1, FPDF_GetPageCount(new_doc));
+ FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
+ ASSERT_NE(nullptr, new_page);
+ FPDF_BITMAP new_bitmap = RenderPage(new_page);
+ ASSERT_EQ(200, FPDFBitmap_GetWidth(new_bitmap));
+ ASSERT_EQ(200, FPDFBitmap_GetHeight(new_bitmap));
+ ASSERT_EQ(800, FPDFBitmap_GetStride(new_bitmap));
+
+ std::string new_digest = HashBitmap(new_bitmap);
+ FPDFBitmap_Destroy(new_bitmap);
+ FPDF_ClosePage(new_page);
+ FPDF_CloseDocument(new_doc);
+
+ EXPECT_EQ(digest, new_digest);
+}
diff --git a/fpdfsdk/fpdfsave.cpp b/fpdfsdk/fpdfsave.cpp
index 0cfcd4a..ddbc994 100644
--- a/fpdfsdk/fpdfsave.cpp
+++ b/fpdfsdk/fpdfsave.cpp
@@ -16,73 +16,40 @@
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fpdfapi/parser/cpdf_string.h"
-#include "core/fxcrt/fx_ext.h"
+#include "core/fxcrt/cfx_memorystream.h"
+#include "core/fxcrt/fx_extension.h"
#include "fpdfsdk/fsdk_define.h"
+#include "fpdfsdk/fsdk_filewriteadapter.h"
#include "public/fpdf_edit.h"
#ifdef PDF_ENABLE_XFA
+#include "core/fxcrt/cfx_checksumcontext.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
#include "public/fpdf_formfill.h"
#include "xfa/fxfa/cxfa_eventparam.h"
-#include "xfa/fxfa/xfa_checksum.h"
-#include "xfa/fxfa/xfa_ffapp.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffwidgethandler.h"
+#include "xfa/fxfa/cxfa_ffapp.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffwidgethandler.h"
+#include "xfa/fxfa/cxfa_widgetacciterator.h"
+#include "xfa/fxfa/parser/cxfa_object.h"
#endif
-#if _FX_OS_ == _FX_ANDROID_
+#if _FX_OS_ == _FX_OS_ANDROID_
#include <time.h>
#else
#include <ctime>
#endif
-class CFX_IFileWrite final : public IFX_WriteStream {
- public:
- static CFX_RetainPtr<CFX_IFileWrite> Create();
- bool Init(FPDF_FILEWRITE* pFileWriteStruct);
- bool WriteBlock(const void* pData, size_t size) override;
-
- protected:
- CFX_IFileWrite();
- ~CFX_IFileWrite() override {}
-
- FPDF_FILEWRITE* m_pFileWriteStruct;
-};
-
-CFX_RetainPtr<CFX_IFileWrite> CFX_IFileWrite::Create() {
- return CFX_RetainPtr<CFX_IFileWrite>(new CFX_IFileWrite());
-}
-
-CFX_IFileWrite::CFX_IFileWrite() : m_pFileWriteStruct(nullptr) {}
-
-bool CFX_IFileWrite::Init(FPDF_FILEWRITE* pFileWriteStruct) {
- if (!pFileWriteStruct)
- return false;
-
- m_pFileWriteStruct = pFileWriteStruct;
- return true;
-}
-
-bool CFX_IFileWrite::WriteBlock(const void* pData, size_t size) {
- if (!m_pFileWriteStruct)
- return false;
-
- m_pFileWriteStruct->WriteBlock(m_pFileWriteStruct, pData, size);
- return true;
-}
-
namespace {
#ifdef PDF_ENABLE_XFA
-bool SaveXFADocumentData(
- CPDFXFA_Context* pContext,
- std::vector<CFX_RetainPtr<IFX_SeekableStream>>* fileList) {
+bool SaveXFADocumentData(CPDFXFA_Context* pContext,
+ std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
if (!pContext)
return false;
- if (pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
- pContext->GetDocType() != DOCTYPE_STATIC_XFA)
+ if (!pContext->ContainsXFAForm())
return true;
CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
@@ -93,7 +60,7 @@
if (!pPDFDocument)
return false;
- CPDF_Dictionary* pRoot = pPDFDocument->GetRoot();
+ const CPDF_Dictionary* pRoot = pPDFDocument->GetRoot();
if (!pRoot)
return false;
@@ -125,18 +92,17 @@
else if (pPDFObj->GetString() == "template")
iTemplate = i + 1;
}
- std::unique_ptr<CXFA_ChecksumContext> pChecksum(new CXFA_ChecksumContext);
+ auto pChecksum = pdfium::MakeUnique<CFX_ChecksumContext>();
pChecksum->StartChecksum();
// template
if (iTemplate > -1) {
CPDF_Stream* pTemplateStream = pArray->GetStreamAt(iTemplate);
- CPDF_StreamAcc streamAcc;
- streamAcc.LoadAllData(pTemplateStream);
- uint8_t* pData = (uint8_t*)streamAcc.GetData();
- uint32_t dwSize2 = streamAcc.GetSize();
- CFX_RetainPtr<IFX_SeekableStream> pTemplate =
- IFX_MemoryStream::Create(pData, dwSize2);
+ auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pTemplateStream);
+ pAcc->LoadAllDataFiltered();
+ RetainPtr<IFX_SeekableStream> pTemplate =
+ pdfium::MakeRetain<CFX_MemoryStream>(
+ const_cast<uint8_t*>(pAcc->GetData()), pAcc->GetSize(), false);
pChecksum->UpdateChecksum(pTemplate);
}
CPDF_Stream* pFormStream = nullptr;
@@ -169,9 +135,12 @@
}
// L"datasets"
{
- CFX_RetainPtr<IFX_SeekableStream> pDsfileWrite = IFX_MemoryStream::Create();
- if (pXFADocView->GetDoc()->SavePackage(XFA_HASHCODE_Datasets, pDsfileWrite,
- nullptr) &&
+ RetainPtr<IFX_SeekableStream> pDsfileWrite =
+ pdfium::MakeRetain<CFX_MemoryStream>(false);
+ CXFA_FFDoc* ffdoc = pXFADocView->GetDoc();
+ if (ffdoc->SavePackage(
+ ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Datasets)),
+ pDsfileWrite, nullptr) &&
pDsfileWrite->GetSize() > 0) {
// Datasets
pChecksum->UpdateChecksum(pDsfileWrite);
@@ -196,9 +165,13 @@
}
// L"form"
{
- CFX_RetainPtr<IFX_SeekableStream> pfileWrite = IFX_MemoryStream::Create();
- if (pXFADocView->GetDoc()->SavePackage(XFA_HASHCODE_Form, pfileWrite,
- pChecksum.get()) &&
+ RetainPtr<IFX_SeekableStream> pfileWrite =
+ pdfium::MakeRetain<CFX_MemoryStream>(false);
+
+ CXFA_FFDoc* ffdoc = pXFADocView->GetDoc();
+ if (ffdoc->SavePackage(
+ ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)),
+ pfileWrite, pChecksum.get()) &&
pfileWrite->GetSize() > 0) {
auto pDataDict = pdfium::MakeUnique<CPDF_Dictionary>(
pPDFDocument->GetByteStringPool());
@@ -223,45 +196,42 @@
if (!pContext)
return false;
- if (pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
- pContext->GetDocType() != DOCTYPE_STATIC_XFA)
+ if (!pContext->ContainsXFAForm())
return true;
CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
if (!pXFADocView)
return false;
- CXFA_FFWidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler();
- std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator(
- pXFADocView->CreateWidgetAccIterator());
+ CXFA_FFWidgetHandler* pWidgetHandler = pXFADocView->GetWidgetHandler();
+ std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator =
+ pXFADocView->CreateWidgetAccIterator();
while (CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext()) {
CXFA_EventParam preParam;
preParam.m_eType = XFA_EVENT_PostSave;
- pWidgetHander->ProcessEvent(pWidgetAcc, &preParam);
+ pWidgetHandler->ProcessEvent(pWidgetAcc, &preParam);
}
pXFADocView->UpdateDocView();
pContext->ClearChangeMark();
return true;
}
-bool SendPreSaveToXFADoc(
- CPDFXFA_Context* pContext,
- std::vector<CFX_RetainPtr<IFX_SeekableStream>>* fileList) {
- if (pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
- pContext->GetDocType() != DOCTYPE_STATIC_XFA)
+bool SendPreSaveToXFADoc(CPDFXFA_Context* pContext,
+ std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
+ if (!pContext->ContainsXFAForm())
return true;
CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
if (!pXFADocView)
return true;
- CXFA_FFWidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler();
- std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator(
- pXFADocView->CreateWidgetAccIterator());
+ CXFA_FFWidgetHandler* pWidgetHandler = pXFADocView->GetWidgetHandler();
+ std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator =
+ pXFADocView->CreateWidgetAccIterator();
while (CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext()) {
CXFA_EventParam preParam;
preParam.m_eType = XFA_EVENT_PreSave;
- pWidgetHander->ProcessEvent(pWidgetAcc, &preParam);
+ pWidgetHandler->ProcessEvent(pWidgetAcc, &preParam);
}
pXFADocView->UpdateDocView();
return SaveXFADocumentData(pContext, fileList);
@@ -279,24 +249,23 @@
#ifdef PDF_ENABLE_XFA
CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
- std::vector<CFX_RetainPtr<IFX_SeekableStream>> fileList;
+ std::vector<RetainPtr<IFX_SeekableStream>> fileList;
SendPreSaveToXFADoc(pContext, &fileList);
#endif // PDF_ENABLE_XFA
if (flags < FPDF_INCREMENTAL || flags > FPDF_REMOVE_SECURITY)
flags = 0;
- CPDF_Creator FileMaker(pPDFDoc);
+ CPDF_Creator fileMaker(pPDFDoc,
+ pdfium::MakeRetain<FSDK_FileWriteAdapter>(pFileWrite));
if (bSetVersion)
- FileMaker.SetFileVersion(fileVerion);
+ fileMaker.SetFileVersion(fileVerion);
if (flags == FPDF_REMOVE_SECURITY) {
flags = 0;
- FileMaker.RemoveSecurity();
+ fileMaker.RemoveSecurity();
}
- CFX_RetainPtr<CFX_IFileWrite> pStreamWrite = CFX_IFileWrite::Create();
- pStreamWrite->Init(pFileWrite);
- bool bRet = FileMaker.Create(pStreamWrite, flags);
+ bool bRet = fileMaker.Create(flags);
#ifdef PDF_ENABLE_XFA
SendPostSaveToXFADoc(pContext);
#endif // PDF_ENABLE_XFA
@@ -305,15 +274,16 @@
} // namespace
-DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveAsCopy(FPDF_DOCUMENT document,
- FPDF_FILEWRITE* pFileWrite,
- FPDF_DWORD flags) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document,
+ FPDF_FILEWRITE* pFileWrite,
+ FPDF_DWORD flags) {
return FPDF_Doc_Save(document, pFileWrite, flags, false, 0);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveWithVersion(FPDF_DOCUMENT document,
- FPDF_FILEWRITE* pFileWrite,
- FPDF_DWORD flags,
- int fileVersion) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDF_SaveWithVersion(FPDF_DOCUMENT document,
+ FPDF_FILEWRITE* pFileWrite,
+ FPDF_DWORD flags,
+ int fileVersion) {
return FPDF_Doc_Save(document, pFileWrite, flags, true, fileVersion);
}
diff --git a/fpdfsdk/fpdfsave_embeddertest.cpp b/fpdfsdk/fpdfsave_embeddertest.cpp
index 9187270..3122be1 100644
--- a/fpdfsdk/fpdfsave_embeddertest.cpp
+++ b/fpdfsdk/fpdfsave_embeddertest.cpp
@@ -4,34 +4,32 @@
#include "public/fpdf_save.h"
-#include <string.h>
+#include <string>
#include "core/fxcrt/fx_string.h"
#include "public/fpdf_edit.h"
#include "public/fpdf_ppo.h"
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
-#include "testing/fx_string_testhelpers.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
-class FPDFSaveEmbedderTest : public EmbedderTest, public TestSaver {};
+class FPDFSaveEmbedderTest : public EmbedderTest {};
TEST_F(FPDFSaveEmbedderTest, SaveSimpleDoc) {
EXPECT_TRUE(OpenDocument("hello_world.pdf"));
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
EXPECT_THAT(GetString(), testing::StartsWith("%PDF-1.7\r\n"));
- EXPECT_EQ(843u, GetString().length());
+ EXPECT_EQ(805u, GetString().length());
}
TEST_F(FPDFSaveEmbedderTest, SaveSimpleDocWithVersion) {
EXPECT_TRUE(OpenDocument("hello_world.pdf"));
EXPECT_TRUE(FPDF_SaveWithVersion(document(), this, 0, 14));
EXPECT_THAT(GetString(), testing::StartsWith("%PDF-1.4\r\n"));
- EXPECT_EQ(843u, GetString().length());
+ EXPECT_EQ(805u, GetString().length());
}
-
TEST_F(FPDFSaveEmbedderTest, SaveSimpleDocWithBadVersion) {
EXPECT_TRUE(OpenDocument("hello_world.pdf"));
EXPECT_TRUE(FPDF_SaveWithVersion(document(), this, 0, -1));
@@ -61,6 +59,39 @@
UnloadPage(page);
}
+TEST_F(FPDFSaveEmbedderTest, SaveLinearizedDoc) {
+ const int kPageCount = 3;
+ std::string original_md5[kPageCount];
+
+ EXPECT_TRUE(OpenDocument("linearized.pdf"));
+ for (int i = 0; i < kPageCount; ++i) {
+ FPDF_PAGE page = LoadPage(i);
+ FPDF_BITMAP bitmap = RenderPage(page);
+ EXPECT_EQ(612, FPDFBitmap_GetWidth(bitmap));
+ EXPECT_EQ(792, FPDFBitmap_GetHeight(bitmap));
+ original_md5[i] = HashBitmap(bitmap);
+ FPDFBitmap_Destroy(bitmap);
+ UnloadPage(page);
+ }
+
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ EXPECT_THAT(GetString(), testing::StartsWith("%PDF-1.6\r\n"));
+ EXPECT_THAT(GetString(), testing::HasSubstr("/Root "));
+ EXPECT_THAT(GetString(), testing::HasSubstr("/Info "));
+ EXPECT_EQ(8219u, GetString().length());
+
+ // Make sure new document renders the same as the old one.
+ EXPECT_TRUE(OpenSavedDocument());
+ for (int i = 0; i < kPageCount; ++i) {
+ FPDF_PAGE page = LoadSavedPage(i);
+ FPDF_BITMAP bitmap = RenderSavedPage(page);
+ EXPECT_EQ(original_md5[i], HashBitmap(bitmap));
+ FPDFBitmap_Destroy(bitmap);
+ CloseSavedPage(page);
+ }
+ CloseSavedDocument();
+}
+
TEST_F(FPDFSaveEmbedderTest, BUG_342) {
EXPECT_TRUE(OpenDocument("hello_world.pdf"));
EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
diff --git a/fpdfsdk/fpdftext.cpp b/fpdfsdk/fpdftext.cpp
index 0432afd..68bf4f8 100644
--- a/fpdfsdk/fpdftext.cpp
+++ b/fpdfsdk/fpdftext.cpp
@@ -29,6 +29,8 @@
namespace {
+constexpr size_t kBytesPerCharacter = sizeof(unsigned short);
+
CPDF_TextPage* CPDFTextPageFromFPDFTextPage(FPDF_TEXTPAGE text_page) {
return static_cast<CPDF_TextPage*>(text_page);
}
@@ -43,7 +45,7 @@
} // namespace
-DLLEXPORT FPDF_TEXTPAGE STDCALL FPDFText_LoadPage(FPDF_PAGE page) {
+FPDF_EXPORT FPDF_TEXTPAGE FPDF_CALLCONV FPDFText_LoadPage(FPDF_PAGE page) {
CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page);
if (!pPDFPage)
return nullptr;
@@ -53,7 +55,7 @@
CPDFXFA_Context* pContext = pPage->GetContext();
CPDF_ViewerPreferences viewRef(pContext->GetPDFDoc());
#else // PDF_ENABLE_XFA
- CPDF_ViewerPreferences viewRef(pPDFPage->m_pDocument);
+ CPDF_ViewerPreferences viewRef(pPDFPage->m_pDocument.Get());
#endif // PDF_ENABLE_XFA
CPDF_TextPage* textpage = new CPDF_TextPage(
@@ -63,11 +65,11 @@
return textpage;
}
-DLLEXPORT void STDCALL FPDFText_ClosePage(FPDF_TEXTPAGE text_page) {
+FPDF_EXPORT void FPDF_CALLCONV FPDFText_ClosePage(FPDF_TEXTPAGE text_page) {
delete CPDFTextPageFromFPDFTextPage(text_page);
}
-DLLEXPORT int STDCALL FPDFText_CountChars(FPDF_TEXTPAGE text_page) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountChars(FPDF_TEXTPAGE text_page) {
if (!text_page)
return -1;
@@ -75,8 +77,8 @@
return textpage->CountChars();
}
-DLLEXPORT unsigned int STDCALL FPDFText_GetUnicode(FPDF_TEXTPAGE text_page,
- int index) {
+FPDF_EXPORT unsigned int FPDF_CALLCONV
+FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, int index) {
if (!text_page)
return 0;
@@ -89,8 +91,8 @@
return charinfo.m_Unicode;
}
-DLLEXPORT double STDCALL FPDFText_GetFontSize(FPDF_TEXTPAGE text_page,
- int index) {
+FPDF_EXPORT double FPDF_CALLCONV FPDFText_GetFontSize(FPDF_TEXTPAGE text_page,
+ int index) {
if (!text_page)
return 0;
CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
@@ -103,68 +105,101 @@
return charinfo.m_FontSize;
}
-DLLEXPORT void STDCALL FPDFText_GetCharBox(FPDF_TEXTPAGE text_page,
- int index,
- double* left,
- double* right,
- double* bottom,
- double* top) {
- if (!text_page)
- return;
- CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetCharBox(FPDF_TEXTPAGE text_page,
+ int index,
+ double* left,
+ double* right,
+ double* bottom,
+ double* top) {
+ if (!text_page || index < 0)
+ return false;
- if (index < 0 || index >= textpage->CountChars())
- return;
+ CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
+ if (index >= textpage->CountChars())
+ return false;
+
FPDF_CHAR_INFO charinfo;
textpage->GetCharInfo(index, &charinfo);
*left = charinfo.m_CharBox.left;
*right = charinfo.m_CharBox.right;
*bottom = charinfo.m_CharBox.bottom;
*top = charinfo.m_CharBox.top;
+ return true;
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFText_GetCharOrigin(FPDF_TEXTPAGE text_page,
+ int index,
+ double* x,
+ double* y) {
+ if (!text_page)
+ return false;
+ CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
+
+ if (index < 0 || index >= textpage->CountChars())
+ return false;
+ FPDF_CHAR_INFO charinfo;
+ textpage->GetCharInfo(index, &charinfo);
+ *x = charinfo.m_Origin.x;
+ *y = charinfo.m_Origin.y;
+ return true;
}
// select
-DLLEXPORT int STDCALL FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page,
- double x,
- double y,
- double xTolerance,
- double yTolerance) {
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page,
+ double x,
+ double y,
+ double xTolerance,
+ double yTolerance) {
if (!text_page)
return -3;
CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
return textpage->GetIndexAtPos(
- CFX_PointF(static_cast<FX_FLOAT>(x), static_cast<FX_FLOAT>(y)),
- CFX_SizeF(static_cast<FX_FLOAT>(xTolerance),
- static_cast<FX_FLOAT>(yTolerance)));
+ CFX_PointF(static_cast<float>(x), static_cast<float>(y)),
+ CFX_SizeF(static_cast<float>(xTolerance),
+ static_cast<float>(yTolerance)));
}
-DLLEXPORT int STDCALL FPDFText_GetText(FPDF_TEXTPAGE text_page,
- int start,
- int count,
- unsigned short* result) {
- if (!text_page)
+FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetText(FPDF_TEXTPAGE page,
+ int char_start,
+ int char_count,
+ unsigned short* result) {
+ if (!page || char_start < 0 || char_count < 0 || !result)
return 0;
- CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
- if (start >= textpage->CountChars())
+ CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(page);
+ int char_available = textpage->CountChars() - char_start;
+ if (char_available <= 0)
return 0;
- CFX_WideString str = textpage->GetPageText(start, count);
- if (str.GetLength() > count)
- str = str.Left(count);
+ char_count = std::min(char_count, char_available);
+ if (char_count == 0) {
+ // Writing out "", which has a character count of 1 due to the NUL.
+ *result = '\0';
+ return 1;
+ }
- CFX_ByteString cbUTF16str = str.UTF16LE_Encode();
- FXSYS_memcpy(result, cbUTF16str.GetBuffer(cbUTF16str.GetLength()),
- cbUTF16str.GetLength());
- cbUTF16str.ReleaseBuffer(cbUTF16str.GetLength());
+ WideString str = textpage->GetPageText(char_start, char_count);
- return cbUTF16str.GetLength() / sizeof(unsigned short);
+ if (str.GetLength() > static_cast<size_t>(char_count))
+ str = str.Left(static_cast<size_t>(char_count));
+
+ // UFT16LE_Encode doesn't handle surrogate pairs properly, so it is expected
+ // the number of items to stay the same.
+ ByteString byte_str = str.UTF16LE_Encode();
+ size_t byte_str_len = byte_str.GetLength();
+ int ret_count = byte_str_len / kBytesPerCharacter;
+
+ ASSERT(ret_count <= char_count + 1); // +1 to account for the NUL terminator.
+ memcpy(result, byte_str.GetBuffer(byte_str_len), byte_str_len);
+ return ret_count;
}
-DLLEXPORT int STDCALL FPDFText_CountRects(FPDF_TEXTPAGE text_page,
- int start,
- int count) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountRects(FPDF_TEXTPAGE text_page,
+ int start,
+ int count) {
if (!text_page)
return 0;
@@ -172,47 +207,48 @@
return textpage->CountRects(start, count);
}
-DLLEXPORT void STDCALL FPDFText_GetRect(FPDF_TEXTPAGE text_page,
- int rect_index,
- double* left,
- double* top,
- double* right,
- double* bottom) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetRect(FPDF_TEXTPAGE text_page,
+ int rect_index,
+ double* left,
+ double* top,
+ double* right,
+ double* bottom) {
if (!text_page)
- return;
+ return false;
CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
CFX_FloatRect rect;
- textpage->GetRect(rect_index, rect.left, rect.top, rect.right, rect.bottom);
+ bool result = textpage->GetRect(rect_index, &rect);
+
*left = rect.left;
*top = rect.top;
*right = rect.right;
*bottom = rect.bottom;
+ return result;
}
-DLLEXPORT int STDCALL FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page,
- double left,
- double top,
- double right,
- double bottom,
- unsigned short* buffer,
- int buflen) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page,
+ double left,
+ double top,
+ double right,
+ double bottom,
+ unsigned short* buffer,
+ int buflen) {
if (!text_page)
return 0;
CPDF_TextPage* textpage = CPDFTextPageFromFPDFTextPage(text_page);
- CFX_FloatRect rect((FX_FLOAT)left, (FX_FLOAT)bottom, (FX_FLOAT)right,
- (FX_FLOAT)top);
- CFX_WideString str = textpage->GetTextByRect(rect);
+ CFX_FloatRect rect((float)left, (float)bottom, (float)right, (float)top);
+ WideString str = textpage->GetTextByRect(rect);
if (buflen <= 0 || !buffer)
return str.GetLength();
- CFX_ByteString cbUTF16Str = str.UTF16LE_Encode();
+ ByteString cbUTF16Str = str.UTF16LE_Encode();
int len = cbUTF16Str.GetLength() / sizeof(unsigned short);
int size = buflen > len ? len : buflen;
- FXSYS_memcpy(buffer, cbUTF16Str.GetBuffer(size * sizeof(unsigned short)),
- size * sizeof(unsigned short));
+ memcpy(buffer, cbUTF16Str.GetBuffer(size * sizeof(unsigned short)),
+ size * sizeof(unsigned short));
cbUTF16Str.ReleaseBuffer(size * sizeof(unsigned short));
return size;
@@ -220,22 +256,24 @@
// Search
// -1 for end
-DLLEXPORT FPDF_SCHHANDLE STDCALL FPDFText_FindStart(FPDF_TEXTPAGE text_page,
- FPDF_WIDESTRING findwhat,
- unsigned long flags,
- int start_index) {
+FPDF_EXPORT FPDF_SCHHANDLE FPDF_CALLCONV
+FPDFText_FindStart(FPDF_TEXTPAGE text_page,
+ FPDF_WIDESTRING findwhat,
+ unsigned long flags,
+ int start_index) {
if (!text_page)
return nullptr;
CPDF_TextPageFind* textpageFind =
new CPDF_TextPageFind(CPDFTextPageFromFPDFTextPage(text_page));
- FX_STRSIZE len = CFX_WideString::WStringLength(findwhat);
- textpageFind->FindFirst(CFX_WideString::FromUTF16LE(findwhat, len), flags,
- start_index);
+ size_t len = WideString::WStringLength(findwhat);
+ textpageFind->FindFirst(
+ WideString::FromUTF16LE(findwhat, len), flags,
+ start_index >= 0 ? Optional<size_t>(start_index) : Optional<size_t>());
return textpageFind;
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindNext(FPDF_SCHHANDLE handle) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_FindNext(FPDF_SCHHANDLE handle) {
if (!handle)
return false;
@@ -243,7 +281,7 @@
return textpageFind->FindNext();
}
-DLLEXPORT FPDF_BOOL STDCALL FPDFText_FindPrev(FPDF_SCHHANDLE handle) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_FindPrev(FPDF_SCHHANDLE handle) {
if (!handle)
return false;
@@ -251,7 +289,8 @@
return textpageFind->FindPrev();
}
-DLLEXPORT int STDCALL FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle) {
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFText_GetSchResultIndex(FPDF_SCHHANDLE handle) {
if (!handle)
return 0;
@@ -259,7 +298,7 @@
return textpageFind->GetCurOrder();
}
-DLLEXPORT int STDCALL FPDFText_GetSchCount(FPDF_SCHHANDLE handle) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetSchCount(FPDF_SCHHANDLE handle) {
if (!handle)
return 0;
@@ -267,7 +306,7 @@
return textpageFind->GetMatchedCount();
}
-DLLEXPORT void STDCALL FPDFText_FindClose(FPDF_SCHHANDLE handle) {
+FPDF_EXPORT void FPDF_CALLCONV FPDFText_FindClose(FPDF_SCHHANDLE handle) {
if (!handle)
return;
@@ -277,7 +316,8 @@
}
// web link
-DLLEXPORT FPDF_PAGELINK STDCALL FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page) {
+FPDF_EXPORT FPDF_PAGELINK FPDF_CALLCONV
+FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page) {
if (!text_page)
return nullptr;
@@ -287,7 +327,7 @@
return pageLink;
}
-DLLEXPORT int STDCALL FPDFLink_CountWebLinks(FPDF_PAGELINK link_page) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountWebLinks(FPDF_PAGELINK link_page) {
if (!link_page)
return 0;
@@ -295,16 +335,16 @@
return pdfium::base::checked_cast<int>(pageLink->CountLinks());
}
-DLLEXPORT int STDCALL FPDFLink_GetURL(FPDF_PAGELINK link_page,
- int link_index,
- unsigned short* buffer,
- int buflen) {
- CFX_WideString wsUrl(L"");
+FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetURL(FPDF_PAGELINK link_page,
+ int link_index,
+ unsigned short* buffer,
+ int buflen) {
+ WideString wsUrl(L"");
if (link_page && link_index >= 0) {
CPDF_LinkExtract* pageLink = CPDFLinkExtractFromFPDFPageLink(link_page);
wsUrl = pageLink->GetURL(link_index);
}
- CFX_ByteString cbUTF16URL = wsUrl.UTF16LE_Encode();
+ ByteString cbUTF16URL = wsUrl.UTF16LE_Encode();
int required = cbUTF16URL.GetLength() / sizeof(unsigned short);
if (!buffer || buflen <= 0)
return required;
@@ -312,13 +352,13 @@
int size = std::min(required, buflen);
if (size > 0) {
int buf_size = size * sizeof(unsigned short);
- FXSYS_memcpy(buffer, cbUTF16URL.GetBuffer(buf_size), buf_size);
+ memcpy(buffer, cbUTF16URL.GetBuffer(buf_size), buf_size);
}
return size;
}
-DLLEXPORT int STDCALL FPDFLink_CountRects(FPDF_PAGELINK link_page,
- int link_index) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountRects(FPDF_PAGELINK link_page,
+ int link_index) {
if (!link_page || link_index < 0)
return 0;
@@ -326,27 +366,28 @@
return pdfium::CollectionSize<int>(pageLink->GetRects(link_index));
}
-DLLEXPORT void STDCALL FPDFLink_GetRect(FPDF_PAGELINK link_page,
- int link_index,
- int rect_index,
- double* left,
- double* top,
- double* right,
- double* bottom) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetRect(FPDF_PAGELINK link_page,
+ int link_index,
+ int rect_index,
+ double* left,
+ double* top,
+ double* right,
+ double* bottom) {
if (!link_page || link_index < 0 || rect_index < 0)
- return;
+ return false;
CPDF_LinkExtract* pageLink = CPDFLinkExtractFromFPDFPageLink(link_page);
std::vector<CFX_FloatRect> rectArray = pageLink->GetRects(link_index);
if (rect_index >= pdfium::CollectionSize<int>(rectArray))
- return;
+ return false;
*left = rectArray[rect_index].left;
*right = rectArray[rect_index].right;
*top = rectArray[rect_index].top;
*bottom = rectArray[rect_index].bottom;
+ return true;
}
-DLLEXPORT void STDCALL FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page) {
+FPDF_EXPORT void FPDF_CALLCONV FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page) {
delete CPDFLinkExtractFromFPDFPageLink(link_page);
}
diff --git a/fpdfsdk/fpdftext_embeddertest.cpp b/fpdfsdk/fpdftext_embeddertest.cpp
index 198ef8a..86d32a7 100644
--- a/fpdfsdk/fpdftext_embeddertest.cpp
+++ b/fpdfsdk/fpdftext_embeddertest.cpp
@@ -4,7 +4,7 @@
#include <memory>
-#include "core/fxcrt/fx_basic.h"
+#include "core/fxcrt/fx_memory.h"
#include "public/fpdf_text.h"
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
@@ -16,13 +16,12 @@
bool check_unsigned_shorts(const char* expected,
const unsigned short* actual,
size_t length) {
- if (length > strlen(expected) + 1) {
+ if (length > strlen(expected) + 1)
return false;
- }
+
for (size_t i = 0; i < length; ++i) {
- if (actual[i] != static_cast<unsigned short>(expected[i])) {
+ if (actual[i] != static_cast<unsigned short>(expected[i]))
return false;
- }
}
return true;
}
@@ -43,6 +42,19 @@
unsigned short fixed_buffer[128];
memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
+ // Check that edge cases are handled gracefully
+ EXPECT_EQ(0, FPDFText_GetText(textpage, 0, 128, nullptr));
+ EXPECT_EQ(0, FPDFText_GetText(textpage, -1, 128, fixed_buffer));
+ EXPECT_EQ(0, FPDFText_GetText(textpage, 0, -1, fixed_buffer));
+ EXPECT_EQ(1, FPDFText_GetText(textpage, 0, 0, fixed_buffer));
+ EXPECT_EQ(0, fixed_buffer[0]);
+
+ // Keep going and check the next case.
+ memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
+ EXPECT_EQ(2, FPDFText_GetText(textpage, 0, 1, fixed_buffer));
+ EXPECT_EQ(expected[0], fixed_buffer[0]);
+ EXPECT_EQ(0, fixed_buffer[1]);
+
// Check includes the terminating NUL that is provided.
int num_chars = FPDFText_GetText(textpage, 0, 128, fixed_buffer);
ASSERT_GE(num_chars, 0);
@@ -58,6 +70,16 @@
<< " at " << i;
}
+ // Extracting using a buffer that will be completely filled. Small buffer is
+ // 12 elements long, since it will need 2 locations per displayed character in
+ // the expected string, plus 2 more for the terminating character.
+ static const char small_expected[] = "Hello";
+ unsigned short small_buffer[12];
+ memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
+ EXPECT_EQ(6, FPDFText_GetText(textpage, 0, 5, small_buffer));
+ EXPECT_TRUE(check_unsigned_shorts(small_expected, small_buffer,
+ sizeof(small_expected)));
+
EXPECT_EQ(12.0, FPDFText_GetFontSize(textpage, 0));
EXPECT_EQ(16.0, FPDFText_GetFontSize(textpage, 15));
@@ -65,12 +87,34 @@
double right = 0.0;
double bottom = 0.0;
double top = 0.0;
- FPDFText_GetCharBox(textpage, 4, &left, &right, &bottom, &top);
+ EXPECT_FALSE(FPDFText_GetCharBox(nullptr, 4, &left, &right, &bottom, &top));
+ EXPECT_DOUBLE_EQ(0.0, left);
+ EXPECT_DOUBLE_EQ(0.0, right);
+ EXPECT_DOUBLE_EQ(0.0, bottom);
+ EXPECT_DOUBLE_EQ(0.0, top);
+ EXPECT_FALSE(FPDFText_GetCharBox(textpage, -1, &left, &right, &bottom, &top));
+ EXPECT_DOUBLE_EQ(0.0, left);
+ EXPECT_DOUBLE_EQ(0.0, right);
+ EXPECT_DOUBLE_EQ(0.0, bottom);
+ EXPECT_DOUBLE_EQ(0.0, top);
+ EXPECT_FALSE(FPDFText_GetCharBox(textpage, 55, &left, &right, &bottom, &top));
+ EXPECT_DOUBLE_EQ(0.0, left);
+ EXPECT_DOUBLE_EQ(0.0, right);
+ EXPECT_DOUBLE_EQ(0.0, bottom);
+ EXPECT_DOUBLE_EQ(0.0, top);
+
+ EXPECT_TRUE(FPDFText_GetCharBox(textpage, 4, &left, &right, &bottom, &top));
EXPECT_NEAR(41.071, left, 0.001);
EXPECT_NEAR(46.243, right, 0.001);
EXPECT_NEAR(49.844, bottom, 0.001);
EXPECT_NEAR(55.520, top, 0.001);
+ double x = 0.0;
+ double y = 0.0;
+ EXPECT_TRUE(FPDFText_GetCharOrigin(textpage, 4, &x, &y));
+ EXPECT_NEAR(40.664, x, 0.001);
+ EXPECT_NEAR(50.000, y, 0.001);
+
EXPECT_EQ(4, FPDFText_GetCharIndexAtPos(textpage, 42.0, 50.0, 1.0, 1.0));
EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, 0.0, 0.0, 1.0, 1.0));
EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, 199.0, 199.0, 1.0, 1.0));
@@ -87,7 +131,7 @@
right = 0.0;
bottom = 0.0;
top = 0.0;
- FPDFText_GetRect(textpage, 1, &left, &top, &right, &bottom);
+ EXPECT_TRUE(FPDFText_GetRect(textpage, 1, &left, &top, &right, &bottom));
EXPECT_NEAR(20.847, left, 0.001);
EXPECT_NEAR(135.167, right, 0.001);
EXPECT_NEAR(96.655, bottom, 0.001);
@@ -98,7 +142,7 @@
right = -1.0;
bottom = -1.0;
top = -1.0;
- FPDFText_GetRect(textpage, -1, &left, &top, &right, &bottom);
+ EXPECT_FALSE(FPDFText_GetRect(textpage, -1, &left, &top, &right, &bottom));
EXPECT_EQ(0.0, left);
EXPECT_EQ(0.0, right);
EXPECT_EQ(0.0, bottom);
@@ -108,7 +152,7 @@
right = -2.0;
bottom = -2.0;
top = -2.0;
- FPDFText_GetRect(textpage, 2, &left, &top, &right, &bottom);
+ EXPECT_FALSE(FPDFText_GetRect(textpage, 2, &left, &top, &right, &bottom));
EXPECT_EQ(0.0, left);
EXPECT_EQ(0.0, right);
EXPECT_EQ(0.0, bottom);
@@ -337,7 +381,7 @@
double right = 0.0;
double top = 0.0;
double bottom = 0.0;
- FPDFLink_GetRect(pagelink, 0, 0, &left, &top, &right, &bottom);
+ EXPECT_TRUE(FPDFLink_GetRect(pagelink, 0, 0, &left, &top, &right, &bottom));
EXPECT_NEAR(50.791, left, 0.001);
EXPECT_NEAR(187.963, right, 0.001);
EXPECT_NEAR(97.624, bottom, 0.001);
@@ -348,7 +392,7 @@
right = -1.0;
top = -1.0;
bottom = -1.0;
- FPDFLink_GetRect(pagelink, 0, 1, &left, &top, &right, &bottom);
+ EXPECT_FALSE(FPDFLink_GetRect(pagelink, 0, 1, &left, &top, &right, &bottom));
EXPECT_EQ(-1.0, left);
EXPECT_EQ(-1.0, right);
EXPECT_EQ(-1.0, bottom);
@@ -359,7 +403,7 @@
right = -2.0;
top = -2.0;
bottom = -2.0;
- FPDFLink_GetRect(pagelink, -1, 0, &left, &top, &right, &bottom);
+ EXPECT_FALSE(FPDFLink_GetRect(pagelink, -1, 0, &left, &top, &right, &bottom));
EXPECT_EQ(-2.0, left);
EXPECT_EQ(-2.0, right);
EXPECT_EQ(-2.0, bottom);
@@ -370,6 +414,74 @@
UnloadPage(page);
}
+TEST_F(FPDFTextEmbeddertest, WebLinksAcrossLines) {
+ EXPECT_TRUE(OpenDocument("weblinks_across_lines.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+
+ FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
+ EXPECT_TRUE(textpage);
+
+ FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage);
+ EXPECT_TRUE(pagelink);
+
+ static const char* const kExpectedUrls[] = {
+ "http://example.com", // from "http://www.example.com?\r\nfoo"
+ "http://example.com/", // from "http://www.example.com/\r\nfoo"
+ "http://example.com/test-foo", // from "http://example.com/test-\r\nfoo"
+ "http://abc.com/test-foo", // from "http://abc.com/test-\r\n\r\nfoo"
+ // Next two links from "http://www.example.com/\r\nhttp://www.abc.com/"
+ "http://example.com/", "http://www.abc.com",
+ };
+ static const int kNumLinks = static_cast<int>(FX_ArraySize(kExpectedUrls));
+
+ EXPECT_EQ(kNumLinks, FPDFLink_CountWebLinks(pagelink));
+
+ unsigned short fixed_buffer[128];
+ for (int i = 0; i < kNumLinks; i++) {
+ const size_t expected_len = strlen(kExpectedUrls[i]) + 1;
+ memset(fixed_buffer, 0, FX_ArraySize(fixed_buffer));
+ EXPECT_EQ(static_cast<int>(expected_len),
+ FPDFLink_GetURL(pagelink, i, nullptr, 0));
+ EXPECT_EQ(
+ static_cast<int>(expected_len),
+ FPDFLink_GetURL(pagelink, i, fixed_buffer, FX_ArraySize(fixed_buffer)));
+ EXPECT_TRUE(
+ check_unsigned_shorts(kExpectedUrls[i], fixed_buffer, expected_len));
+ }
+
+ FPDFLink_CloseWebLinks(pagelink);
+ FPDFText_ClosePage(textpage);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFTextEmbeddertest, WebLinksAcrossLinesBug) {
+ EXPECT_TRUE(OpenDocument("bug_650.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+
+ FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
+ EXPECT_TRUE(textpage);
+
+ FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage);
+ EXPECT_TRUE(pagelink);
+
+ EXPECT_EQ(2, FPDFLink_CountWebLinks(pagelink));
+ unsigned short fixed_buffer[128] = {0};
+ static const char kExpectedUrl[] =
+ "http://tutorial45.com/learn-autocad-basics-day-166/";
+ static const int kUrlSize = static_cast<int>(sizeof(kExpectedUrl));
+
+ EXPECT_EQ(kUrlSize, FPDFLink_GetURL(pagelink, 1, nullptr, 0));
+ EXPECT_EQ(kUrlSize, FPDFLink_GetURL(pagelink, 1, fixed_buffer,
+ FX_ArraySize(fixed_buffer)));
+ EXPECT_TRUE(check_unsigned_shorts(kExpectedUrl, fixed_buffer, kUrlSize));
+
+ FPDFLink_CloseWebLinks(pagelink);
+ FPDFText_ClosePage(textpage);
+ UnloadPage(page);
+}
+
TEST_F(FPDFTextEmbeddertest, GetFontSize) {
EXPECT_TRUE(OpenDocument("hello_world.pdf"));
FPDF_PAGE page = LoadPage(0);
@@ -405,3 +517,127 @@
FPDFText_ClosePage(textpage);
UnloadPage(page);
}
+
+TEST_F(FPDFTextEmbeddertest, Bug_921) {
+ EXPECT_TRUE(OpenDocument("bug_921.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+
+ FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
+ EXPECT_TRUE(textpage);
+
+ static constexpr unsigned int kData[] = {
+ 1095, 1077, 1083, 1086, 1074, 1077, 1095, 1077, 1089, 1082, 1086, 1077,
+ 32, 1089, 1090, 1088, 1072, 1076, 1072, 1085, 1080, 1077, 46, 32};
+ static constexpr int kStartIndex = 238;
+
+ ASSERT_EQ(268, FPDFText_CountChars(textpage));
+ for (size_t i = 0; i < FX_ArraySize(kData); ++i)
+ EXPECT_EQ(kData[i], FPDFText_GetUnicode(textpage, kStartIndex + i));
+
+ unsigned short buffer[FX_ArraySize(kData) + 1];
+ memset(buffer, 0xbd, sizeof(buffer));
+ int count =
+ FPDFText_GetText(textpage, kStartIndex, FX_ArraySize(kData), buffer);
+ ASSERT_GT(count, 0);
+ ASSERT_EQ(FX_ArraySize(kData) + 1, static_cast<size_t>(count));
+ for (size_t i = 0; i < FX_ArraySize(kData); ++i)
+ EXPECT_EQ(kData[i], buffer[i]);
+ EXPECT_EQ(0, buffer[FX_ArraySize(kData)]);
+
+ FPDFText_ClosePage(textpage);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFTextEmbeddertest, GetTextWithHyphen) {
+ EXPECT_TRUE(OpenDocument("bug_781804.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+
+ FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
+ EXPECT_TRUE(textpage);
+
+ // Check that soft hyphens are not included
+ // Expecting 'Veritaserum', except there is a \uFFFE where the hyphen was in
+ // the original text. This is a weird thing that Adobe does, which we
+ // replicate.
+ constexpr unsigned short soft_expected[] = {
+ 0x0056, 0x0065, 0x0072, 0x0069, 0x0074, 0x0061, 0xfffe,
+ 0x0073, 0x0065, 0x0072, 0x0075, 0x006D, 0x0000};
+ {
+ constexpr int count = FX_ArraySize(soft_expected) - 1;
+ unsigned short buffer[FX_ArraySize(soft_expected)];
+ memset(buffer, 0, sizeof(buffer));
+
+ EXPECT_EQ(count + 1, FPDFText_GetText(textpage, 0, count, buffer));
+ for (int i = 0; i < count; i++)
+ EXPECT_EQ(soft_expected[i], buffer[i]);
+ }
+
+ // Check that hard hyphens are included
+ {
+ // There isn't the \0 in the actual doc, but there is a \r\n, so need to
+ // add 1 to get aligned.
+ constexpr size_t offset = FX_ArraySize(soft_expected) + 1;
+ // Expecting 'User-\r\ngenerated', the - is a unicode character, so cannnot
+ // store in a char[].
+ constexpr unsigned short hard_expected[] = {
+ 0x0055, 0x0073, 0x0065, 0x0072, 0x2010, 0x000d, 0x000a, 0x0067, 0x0065,
+ 0x006e, 0x0065, 0x0072, 0x0061, 0x0074, 0x0065, 0x0064, 0x0000};
+ constexpr int count = FX_ArraySize(hard_expected) - 1;
+ unsigned short buffer[FX_ArraySize(hard_expected)];
+
+ EXPECT_EQ(count + 1, FPDFText_GetText(textpage, offset, count, buffer));
+ for (int i = 0; i < count; i++)
+ EXPECT_EQ(hard_expected[i], buffer[i]);
+ }
+
+ FPDFText_ClosePage(textpage);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFTextEmbeddertest, bug_782596) {
+ // If there is a regression in this test, it will only fail under ASAN
+ EXPECT_TRUE(OpenDocument("bug_782596.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+ FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
+ EXPECT_TRUE(textpage);
+ FPDFText_ClosePage(textpage);
+ UnloadPage(page);
+}
+
+TEST_F(FPDFTextEmbeddertest, ControlCharacters) {
+ EXPECT_TRUE(OpenDocument("control_characters.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_TRUE(page);
+
+ FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
+ EXPECT_TRUE(textpage);
+
+ // Should not include the control characters in the output
+ static const char expected[] = "Hello, world!\r\nGoodbye, world!";
+ unsigned short fixed_buffer[128];
+ memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
+ int num_chars = FPDFText_GetText(textpage, 0, 128, fixed_buffer);
+
+ ASSERT_GE(num_chars, 0);
+ EXPECT_EQ(sizeof(expected), static_cast<size_t>(num_chars));
+ EXPECT_TRUE(check_unsigned_shorts(expected, fixed_buffer, sizeof(expected)));
+
+ // Attempting to get a chunk of text after the control characters
+ static const char expected_substring[] = "Goodbye, world!";
+ // Offset is the length of 'Hello, world!\r\n' + 2 control characters in the
+ // original stream
+ static const int offset = 17;
+ memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
+ num_chars = FPDFText_GetText(textpage, offset, 128, fixed_buffer);
+
+ ASSERT_GE(num_chars, 0);
+ EXPECT_EQ(sizeof(expected_substring), static_cast<size_t>(num_chars));
+ EXPECT_TRUE(check_unsigned_shorts(expected_substring, fixed_buffer,
+ sizeof(expected_substring)));
+
+ FPDFText_ClosePage(textpage);
+ UnloadPage(page);
+}
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index 1e7a651..97fc02a 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -8,11 +8,17 @@
#include <memory>
#include <utility>
+#include <vector>
#include "core/fpdfapi/cpdf_modulemgr.h"
#include "core/fpdfapi/cpdf_pagerendercontext.h"
+#include "core/fpdfapi/page/cpdf_image.h"
+#include "core/fpdfapi/page/cpdf_imageobject.h"
#include "core/fpdfapi/page/cpdf_page.h"
+#include "core/fpdfapi/page/cpdf_pageobject.h"
+#include "core/fpdfapi/page/cpdf_pathobject.h"
#include "core/fpdfapi/parser/cpdf_array.h"
+#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
#include "core/fpdfapi/render/cpdf_progressiverenderer.h"
@@ -21,18 +27,21 @@
#include "core/fpdfdoc/cpdf_nametree.h"
#include "core/fpdfdoc/cpdf_occontext.h"
#include "core/fpdfdoc/cpdf_viewerpreferences.h"
-#include "core/fxcodec/fx_codec.h"
#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/fx_safe_types.h"
-#include "core/fxge/cfx_fxgedevice.h"
+#include "core/fxcrt/fx_stream.h"
+#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_gemodule.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "fpdfsdk/fsdk_define.h"
#include "fpdfsdk/fsdk_pauseadapter.h"
-#include "fpdfsdk/javascript/ijs_runtime.h"
+#include "fxjs/ijs_runtime.h"
+#include "public/fpdf_edit.h"
#include "public/fpdf_ext.h"
+#include "public/fpdf_formfill.h"
#include "public/fpdf_progressive.h"
+#include "third_party/base/allocator/partition_allocator/partition_alloc.h"
#include "third_party/base/numerics/safe_conversions_impl.h"
#include "third_party/base/ptr_util.h"
@@ -40,34 +49,26 @@
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
-#include "public/fpdf_formfill.h"
-#include "xfa/fxbarcode/BC_Library.h"
+#include "fxbarcode/BC_Library.h"
#endif // PDF_ENABLE_XFA
-#ifdef PDF_ENABLE_XFA_BMP
-#include "core/fxcodec/codec/ccodec_bmpmodule.h"
-#endif
+#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
+#include "core/fxge/cfx_windowsrenderdevice.h"
-#ifdef PDF_ENABLE_XFA_GIF
-#include "core/fxcodec/codec/ccodec_gifmodule.h"
-#endif
-
-#ifdef PDF_ENABLE_XFA_PNG
-#include "core/fxcodec/codec/ccodec_pngmodule.h"
-#endif
-
-#ifdef PDF_ENABLE_XFA_TIFF
-#include "core/fxcodec/codec/ccodec_tiffmodule.h"
-#endif
-
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
-#include "core/fxge/cfx_windowsdevice.h"
+// These checks are here because core/ and public/ cannot depend on each other.
+static_assert(WindowsPrintMode::kModeEmf == FPDF_PRINTMODE_EMF,
+ "WindowsPrintMode::kModeEmf value mismatch");
+static_assert(WindowsPrintMode::kModeTextOnly == FPDF_PRINTMODE_TEXTONLY,
+ "WindowsPrintMode::kModeTextOnly value mismatch");
+static_assert(WindowsPrintMode::kModePostScript2 == FPDF_PRINTMODE_POSTSCRIPT2,
+ "WindowsPrintMode::kModePostScript2 value mismatch");
+static_assert(WindowsPrintMode::kModePostScript3 == FPDF_PRINTMODE_POSTSCRIPT3,
+ "WindowsPrintMode::kModePostScript3 value mismatch");
#endif
namespace {
-// Also indicates whether library is currently initialized.
-CCodec_ModuleMgr* g_pCodecModule = nullptr;
+bool g_bLibraryInitialized = false;
void RenderPageImpl(CPDF_PageRenderContext* pContext,
CPDF_Page* pPage,
@@ -79,42 +80,39 @@
if (!pContext->m_pOptions)
pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
+ uint32_t option_flags = pContext->m_pOptions->GetFlags();
if (flags & FPDF_LCD_TEXT)
- pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
+ option_flags |= RENDER_CLEARTYPE;
else
- pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
+ option_flags &= ~RENDER_CLEARTYPE;
if (flags & FPDF_NO_NATIVETEXT)
- pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
+ option_flags |= RENDER_NO_NATIVETEXT;
if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
- pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
+ option_flags |= RENDER_LIMITEDIMAGECACHE;
if (flags & FPDF_RENDER_FORCEHALFTONE)
- pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
+ option_flags |= RENDER_FORCE_HALFTONE;
#ifndef PDF_ENABLE_XFA
if (flags & FPDF_RENDER_NO_SMOOTHTEXT)
- pContext->m_pOptions->m_Flags |= RENDER_NOTEXTSMOOTH;
+ option_flags |= RENDER_NOTEXTSMOOTH;
if (flags & FPDF_RENDER_NO_SMOOTHIMAGE)
- pContext->m_pOptions->m_Flags |= RENDER_NOIMAGESMOOTH;
+ option_flags |= RENDER_NOIMAGESMOOTH;
if (flags & FPDF_RENDER_NO_SMOOTHPATH)
- pContext->m_pOptions->m_Flags |= RENDER_NOPATHSMOOTH;
+ option_flags |= RENDER_NOPATHSMOOTH;
#endif // PDF_ENABLE_XFA
+ pContext->m_pOptions->SetFlags(option_flags);
// Grayscale output
- if (flags & FPDF_GRAYSCALE) {
- pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
- pContext->m_pOptions->m_ForeColor = 0;
- pContext->m_pOptions->m_BackColor = 0xffffff;
- }
+ if (flags & FPDF_GRAYSCALE)
+ pContext->m_pOptions->SetColorMode(CPDF_RenderOptions::kGray);
const CPDF_OCContext::UsageType usage =
(flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
- pContext->m_pOptions->m_AddFlags = flags >> 8;
- pContext->m_pOptions->m_pOCContext =
- pdfium::MakeRetain<CPDF_OCContext>(pPage->m_pDocument, usage);
+ pContext->m_pOptions->SetOCContext(
+ pdfium::MakeRetain<CPDF_OCContext>(pPage->m_pDocument.Get(), usage));
pContext->m_pDevice->SaveState();
pContext->m_pDevice->SetClip_Rect(clipping_rect);
-
pContext->m_pContext = pdfium::MakeUnique<CPDF_RenderContext>(pPage);
pContext->m_pContext->AppendLayer(pPage, &matrix);
@@ -135,9 +133,8 @@
class CPDF_CustomAccess final : public IFX_SeekableReadStream {
public:
- static CFX_RetainPtr<CPDF_CustomAccess> Create(FPDF_FILEACCESS* pFileAccess) {
- return CFX_RetainPtr<CPDF_CustomAccess>(new CPDF_CustomAccess(pFileAccess));
- }
+ template <typename T, typename... Args>
+ friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
// IFX_SeekableReadStream
FX_FILESIZE GetSize() override;
@@ -169,16 +166,16 @@
return false;
}
return !!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,
- reinterpret_cast<uint8_t*>(buffer), size);
+ static_cast<uint8_t*>(buffer), size);
}
#ifdef PDF_ENABLE_XFA
-class CFPDF_FileStream : public IFX_SeekableStream {
+class FPDF_FileHandlerContext : public IFX_SeekableStream {
public:
- static CFX_RetainPtr<CFPDF_FileStream> Create(FPDF_FILEHANDLER* pFS) {
- return CFX_RetainPtr<CFPDF_FileStream>(new CFPDF_FileStream(pFS));
- }
- ~CFPDF_FileStream() override;
+ template <typename T, typename... Args>
+ friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
+
+ ~FPDF_FileHandlerContext() override;
// IFX_SeekableStream:
FX_FILESIZE GetSize() override;
@@ -192,39 +189,39 @@
void SetPosition(FX_FILESIZE pos) { m_nCurPos = pos; }
protected:
- explicit CFPDF_FileStream(FPDF_FILEHANDLER* pFS);
+ explicit FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS);
FPDF_FILEHANDLER* m_pFS;
FX_FILESIZE m_nCurPos;
};
-CFPDF_FileStream::CFPDF_FileStream(FPDF_FILEHANDLER* pFS) {
+FPDF_FileHandlerContext::FPDF_FileHandlerContext(FPDF_FILEHANDLER* pFS) {
m_pFS = pFS;
m_nCurPos = 0;
}
-CFPDF_FileStream::~CFPDF_FileStream() {
+FPDF_FileHandlerContext::~FPDF_FileHandlerContext() {
if (m_pFS && m_pFS->Release)
m_pFS->Release(m_pFS->clientData);
}
-FX_FILESIZE CFPDF_FileStream::GetSize() {
+FX_FILESIZE FPDF_FileHandlerContext::GetSize() {
if (m_pFS && m_pFS->GetSize)
return (FX_FILESIZE)m_pFS->GetSize(m_pFS->clientData);
return 0;
}
-bool CFPDF_FileStream::IsEOF() {
+bool FPDF_FileHandlerContext::IsEOF() {
return m_nCurPos >= GetSize();
}
-FX_FILESIZE CFPDF_FileStream::GetPosition() {
+FX_FILESIZE FPDF_FileHandlerContext::GetPosition() {
return m_nCurPos;
}
-bool CFPDF_FileStream::ReadBlock(void* buffer,
- FX_FILESIZE offset,
- size_t size) {
+bool FPDF_FileHandlerContext::ReadBlock(void* buffer,
+ FX_FILESIZE offset,
+ size_t size) {
if (!buffer || !size || !m_pFS->ReadBlock)
return false;
@@ -236,7 +233,7 @@
return false;
}
-size_t CFPDF_FileStream::ReadBlock(void* buffer, size_t size) {
+size_t FPDF_FileHandlerContext::ReadBlock(void* buffer, size_t size) {
if (!buffer || !size || !m_pFS->ReadBlock)
return 0;
@@ -245,7 +242,7 @@
return 0;
FX_FILESIZE dwAvail = nSize - m_nCurPos;
if (dwAvail < (FX_FILESIZE)size)
- size = (size_t)dwAvail;
+ size = static_cast<size_t>(dwAvail);
if (m_pFS->ReadBlock(m_pFS->clientData, (FPDF_DWORD)m_nCurPos, buffer,
(FPDF_DWORD)size) == 0) {
m_nCurPos += size;
@@ -255,9 +252,9 @@
return 0;
}
-bool CFPDF_FileStream::WriteBlock(const void* buffer,
- FX_FILESIZE offset,
- size_t size) {
+bool FPDF_FileHandlerContext::WriteBlock(const void* buffer,
+ FX_FILESIZE offset,
+ size_t size) {
if (!m_pFS || !m_pFS->WriteBlock)
return false;
@@ -269,7 +266,7 @@
return false;
}
-bool CFPDF_FileStream::Flush() {
+bool FPDF_FileHandlerContext::Flush() {
if (!m_pFS || !m_pFS->Flush)
return true;
@@ -277,6 +274,28 @@
}
#endif // PDF_ENABLE_XFA
+FPDF_DOCUMENT LoadDocumentImpl(
+ const RetainPtr<IFX_SeekableReadStream>& pFileAccess,
+ FPDF_BYTESTRING password) {
+ if (!pFileAccess) {
+ ProcessParseError(CPDF_Parser::FILE_ERROR);
+ return nullptr;
+ }
+
+ auto pParser = pdfium::MakeUnique<CPDF_Parser>();
+ pParser->SetPassword(password);
+
+ auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
+ CPDF_Parser::Error error =
+ pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
+ if (error != CPDF_Parser::SUCCESS) {
+ ProcessParseError(error);
+ return nullptr;
+ }
+ CheckUnSupportError(pDocument.get(), error);
+ return FPDFDocumentFromCPDFDocument(pDocument.release());
+}
+
} // namespace
UnderlyingDocumentType* UnderlyingFromFPDFDocument(FPDF_DOCUMENT doc) {
@@ -317,19 +336,101 @@
#endif // PDF_ENABLE_XFA
}
+CPDF_PathObject* CPDFPathObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) {
+ auto* obj = CPDFPageObjectFromFPDFPageObject(page_object);
+ return obj ? obj->AsPath() : nullptr;
+}
+
+CPDF_PageObject* CPDFPageObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object) {
+ return static_cast<CPDF_PageObject*>(page_object);
+}
+
+CPDF_Object* CPDFObjectFromFPDFAttachment(FPDF_ATTACHMENT attachment) {
+ return static_cast<CPDF_Object*>(attachment);
+}
+
+ByteString CFXByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string) {
+ return WideString::FromUTF16LE(wide_string,
+ WideString::WStringLength(wide_string))
+ .UTF8Encode();
+}
+
CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap) {
return static_cast<CFX_DIBitmap*>(bitmap);
}
-CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
+CFX_FloatRect CFXFloatRectFromFSRECTF(const FS_RECTF& rect) {
+ return CFX_FloatRect(rect.left, rect.bottom, rect.right, rect.top);
+}
+
+void FSRECTFFromCFXFloatRect(const CFX_FloatRect& rect, FS_RECTF* out_rect) {
+ out_rect->left = rect.left;
+ out_rect->top = rect.top;
+ out_rect->right = rect.right;
+ out_rect->bottom = rect.bottom;
+}
+
+const FX_PATHPOINT* FXPathPointFromFPDFPathSegment(FPDF_PATHSEGMENT segment) {
+ return static_cast<const FX_PATHPOINT*>(segment);
+}
+
+unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text,
+ void* buffer,
+ unsigned long buflen) {
+ ByteString encoded_text = text.UTF16LE_Encode();
+ unsigned long len = encoded_text.GetLength();
+ if (buffer && len <= buflen)
+ memcpy(buffer, encoded_text.c_str(), len);
+ return len;
+}
+
+unsigned long DecodeStreamMaybeCopyAndReturnLength(const CPDF_Stream* stream,
+ void* buffer,
+ unsigned long buflen) {
+ ASSERT(stream);
+ uint8_t* data = stream->GetRawData();
+ uint32_t len = stream->GetRawSize();
+ CPDF_Dictionary* dict = stream->GetDict();
+ CPDF_Object* decoder = dict ? dict->GetDirectObjectFor("Filter") : nullptr;
+ if (decoder && (decoder->IsArray() || decoder->IsName())) {
+ // Decode the stream if one or more stream filters are specified.
+ uint8_t* decoded_data = nullptr;
+ uint32_t decoded_len = 0;
+ ByteString dummy_last_decoder;
+ CPDF_Dictionary* dummy_last_param;
+ if (PDF_DataDecode(data, len, dict, dict->GetIntegerFor("DL"), false,
+ &decoded_data, &decoded_len, &dummy_last_decoder,
+ &dummy_last_param)) {
+ if (buffer && buflen >= decoded_len)
+ memcpy(buffer, decoded_data, decoded_len);
+
+ // Free the buffer for the decoded data if it was allocated by
+ // PDF_DataDecode(). Note that for images with a single image-specific
+ // filter, |decoded_data| is directly assigned to be |data|, so
+ // |decoded_data| does not need to be freed.
+ if (decoded_data != data)
+ FX_Free(decoded_data);
+
+ return decoded_len;
+ }
+ }
+ // Copy the raw data and return its length if there is no valid filter
+ // specified or if decoding failed.
+ if (buffer && buflen >= len)
+ memcpy(buffer, data, len);
+
+ return len;
+}
+
+RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
FPDF_FILEACCESS* pFileAccess) {
- return CPDF_CustomAccess::Create(pFileAccess);
+ return pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess);
}
#ifdef PDF_ENABLE_XFA
-CFX_RetainPtr<IFX_SeekableStream> MakeSeekableStream(
+RetainPtr<IFX_SeekableStream> MakeSeekableStream(
FPDF_FILEHANDLER* pFilehandler) {
- return CFPDF_FileStream::Create(pFilehandler);
+ return pdfium::MakeRetain<FPDF_FileHandlerContext>(pFilehandler);
}
#endif // PDF_ENABLE_XFA
@@ -358,72 +459,46 @@
}
}
-DLLEXPORT void STDCALL FPDF_InitLibrary() {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary() {
FPDF_InitLibraryWithConfig(nullptr);
}
-DLLEXPORT void STDCALL
+FPDF_EXPORT void FPDF_CALLCONV
FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* cfg) {
- if (g_pCodecModule)
+ if (g_bLibraryInitialized)
return;
- g_pCodecModule = new CCodec_ModuleMgr();
+ FXMEM_InitializePartitionAlloc();
CFX_GEModule* pModule = CFX_GEModule::Get();
- pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr, g_pCodecModule);
+ pModule->Init(cfg ? cfg->m_pUserFontPaths : nullptr);
CPDF_ModuleMgr* pModuleMgr = CPDF_ModuleMgr::Get();
- pModuleMgr->SetCodecModule(g_pCodecModule);
- pModuleMgr->InitPageModule();
- pModuleMgr->LoadEmbeddedGB1CMaps();
- pModuleMgr->LoadEmbeddedJapan1CMaps();
- pModuleMgr->LoadEmbeddedCNS1CMaps();
- pModuleMgr->LoadEmbeddedKorea1CMaps();
-
-#ifdef PDF_ENABLE_XFA_BMP
- pModuleMgr->GetCodecModule()->SetBmpModule(
- pdfium::MakeUnique<CCodec_BmpModule>());
-#endif
-
-#ifdef PDF_ENABLE_XFA_GIF
- pModuleMgr->GetCodecModule()->SetGifModule(
- pdfium::MakeUnique<CCodec_GifModule>());
-#endif
-
-#ifdef PDF_ENABLE_XFA_PNG
- pModuleMgr->GetCodecModule()->SetPngModule(
- pdfium::MakeUnique<CCodec_PngModule>());
-#endif
-
-#ifdef PDF_ENABLE_XFA_TIFF
- pModuleMgr->GetCodecModule()->SetTiffModule(
- pdfium::MakeUnique<CCodec_TiffModule>());
-#endif
+ pModuleMgr->Init();
#ifdef PDF_ENABLE_XFA
- FXJSE_Initialize();
BC_Library_Init();
#endif // PDF_ENABLE_XFA
if (cfg && cfg->version >= 2)
IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
+
+ g_bLibraryInitialized = true;
}
-DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
- if (!g_pCodecModule)
+FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary() {
+ if (!g_bLibraryInitialized)
return;
#ifdef PDF_ENABLE_XFA
- BC_Library_Destory();
- FXJSE_Finalize();
+ BC_Library_Destroy();
#endif // PDF_ENABLE_XFA
CPDF_ModuleMgr::Destroy();
CFX_GEModule::Destroy();
- delete g_pCodecModule;
- g_pCodecModule = nullptr;
-
IJS_Runtime::Destroy();
+
+ g_bLibraryInitialized = false;
}
#ifndef _WIN32
@@ -460,90 +535,78 @@
SetLastError(err_code);
}
-DLLEXPORT void STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
- FPDF_BOOL enable) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_SetSandBoxPolicy(FPDF_DWORD policy,
+ FPDF_BOOL enable) {
return FSDK_SetSandBoxPolicy(policy, enable);
}
#if defined(_WIN32)
#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
-DLLEXPORT void STDCALL
+FPDF_EXPORT void FPDF_CALLCONV
FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func) {
g_pdfium_typeface_accessible_func = func;
}
-DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
g_pdfium_print_text_with_gdi = !!use_gdi;
}
#endif // PDFIUM_PRINT_TEXT_WITH_GDI
-DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintPostscriptLevel(int postscript_level) {
- if (postscript_level != 0 && postscript_level != 2 && postscript_level != 3)
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDF_SetPrintPostscriptLevel(int postscript_level) {
+ return postscript_level != 1 && FPDF_SetPrintMode(postscript_level);
+}
+
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode) {
+ if (mode < FPDF_PRINTMODE_EMF || mode > FPDF_PRINTMODE_POSTSCRIPT3)
return FALSE;
- g_pdfium_print_postscript_level = postscript_level;
+ g_pdfium_print_mode = mode;
return TRUE;
}
#endif // defined(_WIN32)
-DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path,
- FPDF_BYTESTRING password) {
+FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
+FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password) {
// NOTE: the creation of the file needs to be by the embedder on the
// other side of this API.
- CFX_RetainPtr<IFX_SeekableReadStream> pFileAccess =
- IFX_SeekableReadStream::CreateFromFilename((const FX_CHAR*)file_path);
- if (!pFileAccess)
- return nullptr;
-
- auto pParser = pdfium::MakeUnique<CPDF_Parser>();
- pParser->SetPassword(password);
-
- auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
- CPDF_Parser::Error error =
- pDocument->GetParser()->StartParse(pFileAccess, pDocument.get());
- if (error != CPDF_Parser::SUCCESS) {
- ProcessParseError(error);
- return nullptr;
- }
- return FPDFDocumentFromCPDFDocument(pDocument.release());
+ return LoadDocumentImpl(IFX_SeekableReadStream::CreateFromFilename(file_path),
+ password);
}
-#ifdef PDF_ENABLE_XFA
-DLLEXPORT FPDF_BOOL STDCALL FPDF_HasXFAField(FPDF_DOCUMENT document,
- int* docType) {
+FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document) {
if (!document)
return false;
- CPDF_Document* pdfDoc =
- (static_cast<CPDFXFA_Context*>(document))->GetPDFDoc();
- if (!pdfDoc)
- return false;
+ const CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc)
+ return FORMTYPE_NONE;
- CPDF_Dictionary* pRoot = pdfDoc->GetRoot();
+ const CPDF_Dictionary* pRoot = pDoc->GetRoot();
if (!pRoot)
- return false;
+ return FORMTYPE_NONE;
CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
if (!pAcroForm)
- return false;
+ return FORMTYPE_NONE;
CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
if (!pXFA)
- return false;
+ return FORMTYPE_ACRO_FORM;
- bool bDynamicXFA = pRoot->GetBooleanFor("NeedsRendering", false);
- *docType = bDynamicXFA ? DOCTYPE_DYNAMIC_XFA : DOCTYPE_STATIC_XFA;
- return true;
+ bool needsRendering = pRoot->GetBooleanFor("NeedsRendering", false);
+ return needsRendering ? FORMTYPE_XFA_FULL : FORMTYPE_XFA_FOREGROUND;
}
-DLLEXPORT FPDF_BOOL STDCALL FPDF_LoadXFA(FPDF_DOCUMENT document) {
- return document && (static_cast<CPDFXFA_Context*>(document))->LoadXFADoc();
+#ifdef PDF_ENABLE_XFA
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document) {
+ return document && static_cast<CPDFXFA_Context*>(document)->LoadXFADoc();
}
#endif // PDF_ENABLE_XFA
class CMemFile final : public IFX_SeekableReadStream {
public:
- static CFX_RetainPtr<CMemFile> Create(uint8_t* pBuf, FX_FILESIZE size) {
- return CFX_RetainPtr<CMemFile>(new CMemFile(pBuf, size));
+ static RetainPtr<CMemFile> Create(const uint8_t* pBuf, FX_FILESIZE size) {
+ return RetainPtr<CMemFile>(new CMemFile(pBuf, size));
}
FX_FILESIZE GetSize() override { return m_size; }
@@ -556,56 +619,33 @@
if (!newPos.IsValid() || newPos.ValueOrDie() > m_size)
return false;
- FXSYS_memcpy(buffer, m_pBuf + offset, size);
+ memcpy(buffer, m_pBuf + offset, size);
return true;
}
private:
- CMemFile(uint8_t* pBuf, FX_FILESIZE size) : m_pBuf(pBuf), m_size(size) {}
+ CMemFile(const uint8_t* pBuf, FX_FILESIZE size)
+ : m_pBuf(pBuf), m_size(size) {}
- uint8_t* const m_pBuf;
+ const uint8_t* const m_pBuf;
const FX_FILESIZE m_size;
};
-DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf,
- int size,
- FPDF_BYTESTRING password) {
- CFX_RetainPtr<CMemFile> pMemFile = CMemFile::Create((uint8_t*)data_buf, size);
- auto pParser = pdfium::MakeUnique<CPDF_Parser>();
- pParser->SetPassword(password);
-
- auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
- CPDF_Parser::Error error =
- pDocument->GetParser()->StartParse(pMemFile, pDocument.get());
- if (error != CPDF_Parser::SUCCESS) {
- ProcessParseError(error);
- return nullptr;
- }
- CheckUnSupportError(pDocument.get(), error);
- return FPDFDocumentFromCPDFDocument(pDocument.release());
+FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
+FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password) {
+ return LoadDocumentImpl(
+ CMemFile::Create(static_cast<const uint8_t*>(data_buf), size), password);
}
-DLLEXPORT FPDF_DOCUMENT STDCALL
+FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess,
FPDF_BYTESTRING password) {
- CFX_RetainPtr<CPDF_CustomAccess> pFile =
- CPDF_CustomAccess::Create(pFileAccess);
- auto pParser = pdfium::MakeUnique<CPDF_Parser>();
- pParser->SetPassword(password);
-
- auto pDocument = pdfium::MakeUnique<CPDF_Document>(std::move(pParser));
- CPDF_Parser::Error error =
- pDocument->GetParser()->StartParse(pFile, pDocument.get());
- if (error != CPDF_Parser::SUCCESS) {
- ProcessParseError(error);
- return nullptr;
- }
- CheckUnSupportError(pDocument.get(), error);
- return FPDFDocumentFromCPDFDocument(pDocument.release());
+ return LoadDocumentImpl(pdfium::MakeRetain<CPDF_CustomAccess>(pFileAccess),
+ password);
}
-DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc,
- int* fileVersion) {
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetFileVersion(FPDF_DOCUMENT doc,
+ int* fileVersion) {
if (!fileVersion)
return false;
@@ -614,7 +654,7 @@
if (!pDoc)
return false;
- CPDF_Parser* pParser = pDoc->GetParser();
+ const CPDF_Parser* pParser = pDoc->GetParser();
if (!pParser)
return false;
@@ -624,7 +664,8 @@
// jabdelmalek: changed return type from uint32_t to build on Linux (and match
// header).
-DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDF_GetDocPermissions(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
// https://bugs.chromium.org/p/pdfium/issues/detail?id=499
if (!pDoc) {
@@ -638,7 +679,8 @@
return pDoc->GetUserPermissions();
}
-DLLEXPORT int STDCALL FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
+FPDF_EXPORT int FPDF_CALLCONV
+FPDF_GetSecurityHandlerRevision(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc || !pDoc->GetParser())
return -1;
@@ -647,13 +689,13 @@
return pDict ? pDict->GetIntegerFor("R") : -1;
}
-DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document) {
+FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document) {
UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
return pDoc ? pDoc->GetPageCount() : 0;
}
-DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document,
- int page_index) {
+FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document,
+ int page_index) {
UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
if (!pDoc)
return nullptr;
@@ -662,7 +704,7 @@
return nullptr;
#ifdef PDF_ENABLE_XFA
- return pDoc->GetXFAPage(page_index);
+ return pDoc->GetXFAPage(page_index).Leak();
#else // PDF_ENABLE_XFA
CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
if (!pDict)
@@ -674,64 +716,258 @@
#endif // PDF_ENABLE_XFA
}
-DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page) {
+FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page) {
UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
return pPage ? pPage->GetPageWidth() : 0.0;
}
-DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page) {
+FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page) {
UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
return pPage ? pPage->GetPageHeight() : 0.0;
}
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageBoundingBox(FPDF_PAGE page,
+ FS_RECTF* rect) {
+ if (!rect)
+ return false;
+
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage)
+ return false;
+
+ FSRECTFFromCFXFloatRect(pPage->GetPageBBox(), rect);
+ return true;
+}
+
#if defined(_WIN32)
-DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc,
- FPDF_PAGE page,
- int start_x,
- int start_y,
- int size_x,
- int size_y,
- int rotate,
- int flags) {
+namespace {
+
+const double kEpsilonSize = 0.01f;
+
+void GetScaling(CPDF_Page* pPage,
+ int size_x,
+ int size_y,
+ int rotate,
+ double* scale_x,
+ double* scale_y) {
+ ASSERT(pPage);
+ ASSERT(scale_x);
+ ASSERT(scale_y);
+ double page_width = pPage->GetPageWidth();
+ double page_height = pPage->GetPageHeight();
+ if (page_width < kEpsilonSize || page_height < kEpsilonSize)
+ return;
+
+ if (rotate % 2 == 0) {
+ *scale_x = size_x / page_width;
+ *scale_y = size_y / page_height;
+ } else {
+ *scale_x = size_y / page_width;
+ *scale_y = size_x / page_height;
+ }
+}
+
+FX_RECT GetMaskDimensionsAndOffsets(CPDF_Page* pPage,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ const CFX_FloatRect& mask_box) {
+ double scale_x = 0.0f;
+ double scale_y = 0.0f;
+ GetScaling(pPage, size_x, size_y, rotate, &scale_x, &scale_y);
+ if (scale_x < kEpsilonSize || scale_y < kEpsilonSize)
+ return FX_RECT();
+
+ // Compute sizes in page points. Round down to catch the entire bitmap.
+ int start_x_bm = static_cast<int>(mask_box.left * scale_x);
+ int start_y_bm = static_cast<int>(mask_box.bottom * scale_y);
+ int size_x_bm = static_cast<int>(mask_box.right * scale_x + 1.0f) -
+ static_cast<int>(mask_box.left * scale_x);
+ int size_y_bm = static_cast<int>(mask_box.top * scale_y + 1.0f) -
+ static_cast<int>(mask_box.bottom * scale_y);
+
+ // Get page rotation
+ int page_rotation = pPage->GetPageRotation();
+
+ // Compute offsets
+ int offset_x = 0;
+ int offset_y = 0;
+ if (size_x > size_y)
+ std::swap(size_x_bm, size_y_bm);
+
+ switch ((rotate + page_rotation) % 4) {
+ case 0:
+ offset_x = start_x_bm + start_x;
+ offset_y = start_y + size_y - size_y_bm - start_y_bm;
+ break;
+ case 1:
+ offset_x = start_y_bm + start_x;
+ offset_y = start_x_bm + start_y;
+ break;
+ case 2:
+ offset_x = start_x + size_x - size_x_bm - start_x_bm;
+ offset_y = start_y_bm + start_y;
+ break;
+ case 3:
+ offset_x = start_x + size_x - size_x_bm - start_y_bm;
+ offset_y = start_y + size_y - size_y_bm - start_x_bm;
+ break;
+ }
+ return FX_RECT(offset_x, offset_y, offset_x + size_x_bm,
+ offset_y + size_y_bm);
+}
+
+// Get a bitmap of just the mask section defined by |mask_box| from a full page
+// bitmap |pBitmap|.
+RetainPtr<CFX_DIBitmap> GetMaskBitmap(CPDF_Page* pPage,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ const RetainPtr<CFX_DIBitmap>& pSrc,
+ const CFX_FloatRect& mask_box,
+ FX_RECT* bitmap_area) {
+ ASSERT(bitmap_area);
+ *bitmap_area = GetMaskDimensionsAndOffsets(pPage, start_x, start_y, size_x,
+ size_y, rotate, mask_box);
+ if (bitmap_area->IsEmpty())
+ return nullptr;
+
+ // Create a new bitmap to transfer part of the page bitmap to.
+ RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
+ pDst->Create(bitmap_area->Width(), bitmap_area->Height(), FXDIB_Argb);
+ pDst->Clear(0x00ffffff);
+ pDst->TransferBitmap(0, 0, bitmap_area->Width(), bitmap_area->Height(), pSrc,
+ bitmap_area->left, bitmap_area->top);
+ return pDst;
+}
+
+void RenderBitmap(CFX_RenderDevice* device,
+ const RetainPtr<CFX_DIBitmap>& pSrc,
+ const FX_RECT& mask_area) {
+ int size_x_bm = mask_area.Width();
+ int size_y_bm = mask_area.Height();
+ if (size_x_bm == 0 || size_y_bm == 0)
+ return;
+
+ // Create a new bitmap from the old one
+ RetainPtr<CFX_DIBitmap> pDst = pdfium::MakeRetain<CFX_DIBitmap>();
+ pDst->Create(size_x_bm, size_y_bm, FXDIB_Rgb32);
+ pDst->Clear(0xffffffff);
+ pDst->CompositeBitmap(0, 0, size_x_bm, size_y_bm, pSrc, 0, 0,
+ FXDIB_BLEND_NORMAL, nullptr, false);
+
+ if (device->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
+ device->StretchDIBits(pDst, mask_area.left, mask_area.top, size_x_bm,
+ size_y_bm);
+ } else {
+ device->SetDIBits(pDst, mask_area.left, mask_area.top);
+ }
+}
+
+} // namespace
+
+FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPage(HDC dc,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return;
+ pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
+ CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
- CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
- pPage->SetRenderContext(pdfium::WrapUnique(pContext));
-
- std::unique_ptr<CFX_DIBitmap> pBitmap;
- // TODO: This results in unnecessary rasterization of some PDFs due to
- // HasImageMask() returning true. If any image on the page is a mask, the
- // entire page gets rasterized and the spool size gets huge.
- const bool bNewBitmap =
- pPage->BackgroundAlphaNeeded() || pPage->HasImageMask();
- if (bNewBitmap) {
- pBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
+ RetainPtr<CFX_DIBitmap> pBitmap;
+ // Don't render the full page to bitmap for a mask unless there are a lot
+ // of masks. Full page bitmaps result in large spool sizes, so they should
+ // only be used when necessary. For large numbers of masks, rendering each
+ // individually is inefficient and unlikely to significantly improve spool
+ // size. TODO (rbpotter): Find out why this still breaks printing for some
+ // PDFs (see crbug.com/777837).
+ const bool bEnableImageMasks = false;
+ const bool bNewBitmap = pPage->BackgroundAlphaNeeded() ||
+ (pPage->HasImageMask() && !bEnableImageMasks) ||
+ pPage->GetMaskBoundingBoxes().size() > 100;
+ const bool bHasMask = pPage->HasImageMask() && !bNewBitmap;
+ if (bNewBitmap || bHasMask) {
+ pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
pBitmap->Create(size_x, size_y, FXDIB_Argb);
pBitmap->Clear(0x00ffffff);
- CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
+ CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
pContext->m_pDevice = pdfium::WrapUnique(pDevice);
- pDevice->Attach(pBitmap.get(), false, nullptr, false);
+ pDevice->Attach(pBitmap, false, nullptr, false);
+ if (bHasMask) {
+ pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
+ uint32_t option_flags = pContext->m_pOptions->GetFlags();
+ option_flags |= RENDER_BREAKFORMASKS;
+ pContext->m_pOptions->SetFlags(option_flags);
+ }
} else {
- pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsDevice>(dc);
+ pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
}
FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
rotate, flags, true, nullptr);
- if (bNewBitmap) {
- CFX_WindowsDevice WinDC(dc);
+ if (bHasMask) {
+ // Finish rendering the page to bitmap and copy the correct segments
+ // of the page to individual image mask bitmaps.
+ const std::vector<CFX_FloatRect>& mask_boxes =
+ pPage->GetMaskBoundingBoxes();
+ std::vector<FX_RECT> bitmap_areas(mask_boxes.size());
+ std::vector<RetainPtr<CFX_DIBitmap>> bitmaps(mask_boxes.size());
+ for (size_t i = 0; i < mask_boxes.size(); i++) {
+ bitmaps[i] =
+ GetMaskBitmap(pPage, start_x, start_y, size_x, size_y, rotate,
+ pBitmap, mask_boxes[i], &bitmap_areas[i]);
+ pContext->m_pRenderer->Continue(nullptr);
+ }
+
+ // Reset rendering context
+ pPage->SetRenderContext(nullptr);
+
+ // Begin rendering to the printer. Add flag to indicate the renderer should
+ // pause after each image mask.
+ pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
+ pContext = pPage->GetRenderContext();
+ pContext->m_pDevice = pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc);
+ pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
+
+ uint32_t option_flags = pContext->m_pOptions->GetFlags();
+ option_flags |= RENDER_BREAKFORMASKS;
+ pContext->m_pOptions->SetFlags(option_flags);
+
+ FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
+ rotate, flags, true, nullptr);
+
+ // Render masks
+ for (size_t i = 0; i < mask_boxes.size(); i++) {
+ // Render the bitmap for the mask and free the bitmap.
+ if (bitmaps[i]) { // will be null if mask has zero area
+ RenderBitmap(pContext->m_pDevice.get(), bitmaps[i], bitmap_areas[i]);
+ }
+ // Render the next portion of page.
+ pContext->m_pRenderer->Continue(nullptr);
+ }
+ } else if (bNewBitmap) {
+ CFX_WindowsRenderDevice WinDC(dc);
if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
- std::unique_ptr<CFX_DIBitmap> pDst = pdfium::MakeUnique<CFX_DIBitmap>();
+ auto pDst = pdfium::MakeRetain<CFX_DIBitmap>();
int pitch = pBitmap->GetPitch();
pDst->Create(size_x, size_y, FXDIB_Rgb32);
- FXSYS_memset(pDst->GetBuffer(), -1, pitch * size_y);
- pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap.get(), 0, 0,
- FXDIB_BLEND_NORMAL, nullptr, false, nullptr);
- WinDC.StretchDIBits(pDst.get(), 0, 0, size_x, size_y);
+ memset(pDst->GetBuffer(), -1, pitch * size_y);
+ pDst->CompositeBitmap(0, 0, size_x, size_y, pBitmap, 0, 0,
+ FXDIB_BLEND_NORMAL, nullptr, false);
+ WinDC.StretchDIBits(pDst, 0, 0, size_x, size_y);
} else {
- WinDC.SetDIBits(pBitmap.get(), 0, 0);
+ WinDC.SetDIBits(pBitmap, 0, 0);
}
}
@@ -739,14 +975,14 @@
}
#endif // defined(_WIN32)
-DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
- FPDF_PAGE page,
- int start_x,
- int start_y,
- int size_x,
- int size_y,
- int rotate,
- int flags) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags) {
if (!bitmap)
return;
@@ -756,26 +992,28 @@
CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
pPage->SetRenderContext(pdfium::WrapUnique(pContext));
- CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
- pContext->m_pDevice.reset(pDevice);
- CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
- pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
+ CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
+ pContext->m_pDevice.reset(pDevice);
+
+ RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
+ pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
FPDF_RenderPage_Retail(pContext, page, start_x, start_y, size_x, size_y,
rotate, flags, true, nullptr);
#ifdef _SKIA_SUPPORT_PATHS_
- pDevice->Flush();
+ pDevice->Flush(true);
pBitmap->UnPreMultiply();
#endif
pPage->SetRenderContext(nullptr);
}
-DLLEXPORT void STDCALL FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
- FPDF_PAGE page,
- const FS_MATRIX* matrix,
- const FS_RECTF* clipping,
- int flags) {
+FPDF_EXPORT void FPDF_CALLCONV
+FPDF_RenderPageBitmapWithMatrix(FPDF_BITMAP bitmap,
+ FPDF_PAGE page,
+ const FS_MATRIX* matrix,
+ const FS_RECTF* clipping,
+ int flags) {
if (!bitmap)
return;
@@ -785,41 +1023,42 @@
CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
pPage->SetRenderContext(pdfium::WrapUnique(pContext));
- CFX_FxgeDevice* pDevice = new CFX_FxgeDevice;
+
+ CFX_DefaultRenderDevice* pDevice = new CFX_DefaultRenderDevice;
pContext->m_pDevice.reset(pDevice);
- CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
+
+ RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
pDevice->Attach(pBitmap, !!(flags & FPDF_REVERSE_BYTE_ORDER), nullptr, false);
- CFX_Matrix transform_matrix = pPage->GetPageMatrix();
+ CFX_FloatRect clipping_rect;
+ if (clipping)
+ clipping_rect = CFXFloatRectFromFSRECTF(*clipping);
+ FX_RECT clip_rect = clipping_rect.ToFxRect();
+
+ CFX_Matrix transform_matrix = pPage->GetDisplayMatrix(
+ 0, 0, pPage->GetPageWidth(), pPage->GetPageHeight(), 0);
+
if (matrix) {
transform_matrix.Concat(CFX_Matrix(matrix->a, matrix->b, matrix->c,
matrix->d, matrix->e, matrix->f));
}
-
- CFX_FloatRect clipping_rect;
- if (clipping) {
- clipping_rect.left = clipping->left;
- clipping_rect.bottom = clipping->bottom;
- clipping_rect.right = clipping->right;
- clipping_rect.top = clipping->top;
- }
- RenderPageImpl(pContext, pPage, transform_matrix, clipping_rect.ToFxRect(),
- flags, true, nullptr);
+ RenderPageImpl(pContext, pPage, transform_matrix, clip_rect, flags, true,
+ nullptr);
pPage->SetRenderContext(nullptr);
}
#ifdef _SKIA_SUPPORT_
-DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
- int size_x,
- int size_y) {
+FPDF_EXPORT FPDF_RECORDER FPDF_CALLCONV FPDF_RenderPageSkp(FPDF_PAGE page,
+ int size_x,
+ int size_y) {
CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
if (!pPage)
return nullptr;
CPDF_PageRenderContext* pContext = new CPDF_PageRenderContext;
pPage->SetRenderContext(pdfium::WrapUnique(pContext));
- CFX_FxgeDevice* skDevice = new CFX_FxgeDevice;
+ CFX_DefaultRenderDevice* skDevice = new CFX_DefaultRenderDevice;
FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
pContext->m_pDevice.reset(skDevice);
FPDF_RenderPage_Retail(pContext, page, 0, 0, size_x, size_y, 0, 0, true,
@@ -829,12 +1068,13 @@
}
#endif
-DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_ClosePage(FPDF_PAGE page) {
UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
if (!page)
return;
#ifdef PDF_ENABLE_XFA
- pPage->Release();
+ // Take it back across the API and throw it away.
+ RetainPtr<CPDFXFA_Page>().Unleak(pPage);
#else // PDF_ENABLE_XFA
CPDFSDK_PageView* pPageView =
static_cast<CPDFSDK_PageView*>(pPage->GetView());
@@ -861,24 +1101,24 @@
#endif // PDF_ENABLE_XFA
}
-DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseDocument(FPDF_DOCUMENT document) {
delete UnderlyingFromFPDFDocument(document);
}
-DLLEXPORT unsigned long STDCALL FPDF_GetLastError() {
+FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetLastError() {
return GetLastError();
}
-DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page,
- int start_x,
- int start_y,
- int size_x,
- int size_y,
- int rotate,
- int device_x,
- int device_y,
- double* page_x,
- double* page_y) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_DeviceToPage(FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int device_x,
+ int device_y,
+ double* page_x,
+ double* page_y) {
if (!page || !page_x || !page_y)
return;
UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
@@ -888,27 +1128,25 @@
#else // PDF_ENABLE_XFA
CFX_Matrix page2device =
pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
- CFX_Matrix device2page;
- device2page.SetReverse(page2device);
- CFX_PointF pos = device2page.Transform(CFX_PointF(
- static_cast<FX_FLOAT>(device_x), static_cast<FX_FLOAT>(device_y)));
+ CFX_PointF pos = page2device.GetInverse().Transform(
+ CFX_PointF(static_cast<float>(device_x), static_cast<float>(device_y)));
*page_x = pos.x;
*page_y = pos.y;
#endif // PDF_ENABLE_XFA
}
-DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page,
- int start_x,
- int start_y,
- int size_x,
- int size_y,
- int rotate,
- double page_x,
- double page_y,
- int* device_x,
- int* device_y) {
+FPDF_EXPORT void FPDF_CALLCONV FPDF_PageToDevice(FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ double page_x,
+ double page_y,
+ int* device_x,
+ int* device_y) {
if (!device_x || !device_y)
return;
UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
@@ -921,28 +1159,28 @@
CFX_Matrix page2device =
pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
CFX_PointF pos = page2device.Transform(
- CFX_PointF(static_cast<FX_FLOAT>(page_x), static_cast<FX_FLOAT>(page_y)));
+ CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)));
*device_x = FXSYS_round(pos.x);
*device_y = FXSYS_round(pos.y);
#endif // PDF_ENABLE_XFA
}
-DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width,
- int height,
- int alpha) {
- auto pBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width,
+ int height,
+ int alpha) {
+ auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
if (!pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32))
return nullptr;
- return pBitmap.release();
+ return pBitmap.Leak();
}
-DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width,
- int height,
- int format,
- void* first_scan,
- int stride) {
+FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_CreateEx(int width,
+ int height,
+ int format,
+ void* first_scan,
+ int stride) {
FXDIB_Format fx_format;
switch (format) {
case FPDFBitmap_Gray:
@@ -960,22 +1198,43 @@
default:
return nullptr;
}
- CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
- pBitmap->Create(width, height, fx_format, (uint8_t*)first_scan, stride);
- return pBitmap;
+ auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
+ pBitmap->Create(width, height, fx_format, static_cast<uint8_t*>(first_scan),
+ stride);
+ return pBitmap.Leak();
}
-DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
- int left,
- int top,
- int width,
- int height,
- FPDF_DWORD color) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetFormat(FPDF_BITMAP bitmap) {
+ if (!bitmap)
+ return FPDFBitmap_Unknown;
+
+ FXDIB_Format format = CFXBitmapFromFPDFBitmap(bitmap)->GetFormat();
+ switch (format) {
+ case FXDIB_8bppRgb:
+ case FXDIB_8bppMask:
+ return FPDFBitmap_Gray;
+ case FXDIB_Rgb:
+ return FPDFBitmap_BGR;
+ case FXDIB_Rgb32:
+ return FPDFBitmap_BGRx;
+ case FXDIB_Argb:
+ return FPDFBitmap_BGRA;
+ default:
+ return FPDFBitmap_Unknown;
+ }
+}
+
+FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap,
+ int left,
+ int top,
+ int width,
+ int height,
+ FPDF_DWORD color) {
if (!bitmap)
return;
- CFX_FxgeDevice device;
- CFX_DIBitmap* pBitmap = CFXBitmapFromFPDFBitmap(bitmap);
+ CFX_DefaultRenderDevice device;
+ RetainPtr<CFX_DIBitmap> pBitmap(CFXBitmapFromFPDFBitmap(bitmap));
device.Attach(pBitmap, false, nullptr, false);
if (!pBitmap->HasAlpha())
color |= 0xFF000000;
@@ -983,24 +1242,25 @@
device.FillRect(&rect, color);
}
-DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
+FPDF_EXPORT void* FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap) {
return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetBuffer() : nullptr;
}
-DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap) {
return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetWidth() : 0;
}
-DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap) {
return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetHeight() : 0;
}
-DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
+FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetStride(FPDF_BITMAP bitmap) {
return bitmap ? CFXBitmapFromFPDFBitmap(bitmap)->GetPitch() : 0;
}
-DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
- delete CFXBitmapFromFPDFBitmap(bitmap);
+FPDF_EXPORT void FPDF_CALLCONV FPDFBitmap_Destroy(FPDF_BITMAP bitmap) {
+ RetainPtr<CFX_DIBitmap> destroyer;
+ destroyer.Unleak(CFXBitmapFromFPDFBitmap(bitmap));
}
void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
@@ -1023,10 +1283,10 @@
flags, bNeedToRestore, pause);
}
-DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
- int page_index,
- double* width,
- double* height) {
+FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document,
+ int page_index,
+ double* width,
+ double* height) {
UnderlyingDocumentType* pDoc = UnderlyingFromFPDFDocument(document);
if (!pDoc)
return false;
@@ -1035,7 +1295,7 @@
int count = pDoc->GetPageCount();
if (page_index < 0 || page_index >= count)
return false;
- CPDFXFA_Page* pPage = pDoc->GetXFAPage(page_index);
+ RetainPtr<CPDFXFA_Page> pPage = pDoc->GetXFAPage(page_index);
if (!pPage)
return false;
*width = pPage->GetPageWidth();
@@ -1053,7 +1313,7 @@
return true;
}
-DLLEXPORT FPDF_BOOL STDCALL
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
@@ -1062,7 +1322,8 @@
return viewRef.PrintScaling();
}
-DLLEXPORT int STDCALL FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
+FPDF_EXPORT int FPDF_CALLCONV
+FPDF_VIEWERREF_GetNumCopies(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
return 1;
@@ -1070,7 +1331,7 @@
return viewRef.NumCopies();
}
-DLLEXPORT FPDF_PAGERANGE STDCALL
+FPDF_EXPORT FPDF_PAGERANGE FPDF_CALLCONV
FPDF_VIEWERREF_GetPrintPageRange(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
@@ -1079,13 +1340,13 @@
return viewRef.PrintPageRange();
}
-DLLEXPORT FPDF_DUPLEXTYPE STDCALL
+FPDF_EXPORT FPDF_DUPLEXTYPE FPDF_CALLCONV
FPDF_VIEWERREF_GetDuplex(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
return DuplexUndefined;
CPDF_ViewerPreferences viewRef(pDoc);
- CFX_ByteString duplex = viewRef.Duplex();
+ ByteString duplex = viewRef.Duplex();
if ("Simplex" == duplex)
return Simplex;
if ("DuplexFlipShortEdge" == duplex)
@@ -1095,16 +1356,17 @@
return DuplexUndefined;
}
-DLLEXPORT unsigned long STDCALL FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
- FPDF_BYTESTRING key,
- char* buffer,
- unsigned long length) {
+FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDF_VIEWERREF_GetName(FPDF_DOCUMENT document,
+ FPDF_BYTESTRING key,
+ char* buffer,
+ unsigned long length) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
return 0;
CPDF_ViewerPreferences viewRef(pDoc);
- CFX_ByteString bsVal;
+ ByteString bsVal;
if (!viewRef.GenericName(key, &bsVal))
return 0;
@@ -1114,12 +1376,13 @@
return dwStringLen;
}
-DLLEXPORT FPDF_DWORD STDCALL FPDF_CountNamedDests(FPDF_DOCUMENT document) {
+FPDF_EXPORT FPDF_DWORD FPDF_CALLCONV
+FPDF_CountNamedDests(FPDF_DOCUMENT document) {
CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
if (!pDoc)
return 0;
- CPDF_Dictionary* pRoot = pDoc->GetRoot();
+ const CPDF_Dictionary* pRoot = pDoc->GetRoot();
if (!pRoot)
return 0;
@@ -1135,8 +1398,8 @@
return count.ValueOrDie();
}
-DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,
- FPDF_BYTESTRING name) {
+FPDF_EXPORT FPDF_DEST FPDF_CALLCONV
+FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name) {
if (!name || name[0] == 0)
return nullptr;
@@ -1145,34 +1408,29 @@
return nullptr;
CPDF_NameTree name_tree(pDoc, "Dests");
- return name_tree.LookupNamedDest(pDoc, name);
+ return name_tree.LookupNamedDest(pDoc, PDF_DecodeText(ByteString(name)));
}
#ifdef PDF_ENABLE_XFA
-DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Init(FPDF_BSTR* str) {
+FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Init(FPDF_BSTR* str) {
if (!str)
return -1;
- FXSYS_memset(str, 0, sizeof(FPDF_BSTR));
+ memset(str, 0, sizeof(FPDF_BSTR));
return 0;
}
-DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Set(FPDF_BSTR* str,
- FPDF_LPCSTR bstr,
- int length) {
- if (!str)
+FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Set(FPDF_BSTR* str,
+ FPDF_LPCSTR bstr,
+ int length) {
+ if (!str || !bstr || !length)
return -1;
- if (!bstr || !length)
- return -1;
+
if (length == -1)
- length = FXSYS_strlen(bstr);
+ length = strlen(bstr);
if (length == 0) {
- if (str->str) {
- FX_Free(str->str);
- str->str = nullptr;
- }
- str->len = 0;
+ FPDF_BStr_Clear(str);
return 0;
}
@@ -1182,13 +1440,13 @@
str->str = FX_Alloc(char, length + 1);
str->str[length] = 0;
- FXSYS_memcpy(str->str, bstr, length);
+ memcpy(str->str, bstr, length);
str->len = length;
return 0;
}
-DLLEXPORT FPDF_RESULT STDCALL FPDF_BStr_Clear(FPDF_BSTR* str) {
+FPDF_EXPORT FPDF_RESULT FPDF_CALLCONV FPDF_BStr_Clear(FPDF_BSTR* str) {
if (!str)
return -1;
@@ -1201,10 +1459,10 @@
}
#endif // PDF_ENABLE_XFA
-DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDest(FPDF_DOCUMENT document,
- int index,
- void* buffer,
- long* buflen) {
+FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDF_GetNamedDest(FPDF_DOCUMENT document,
+ int index,
+ void* buffer,
+ long* buflen) {
if (!buffer)
*buflen = 0;
@@ -1215,12 +1473,12 @@
if (!pDoc)
return nullptr;
- CPDF_Dictionary* pRoot = pDoc->GetRoot();
+ const CPDF_Dictionary* pRoot = pDoc->GetRoot();
if (!pRoot)
return nullptr;
CPDF_Object* pDestObj = nullptr;
- CFX_ByteString bsName;
+ WideString wsName;
CPDF_NameTree nameTree(pDoc, "Dests");
int count = nameTree.GetCount();
if (index >= count) {
@@ -1235,6 +1493,7 @@
index -= count;
int i = 0;
+ ByteString bsName;
for (const auto& it : *pDest) {
bsName = it.first;
pDestObj = it.second.get();
@@ -1244,8 +1503,9 @@
break;
i++;
}
+ wsName = PDF_DecodeText(bsName);
} else {
- pDestObj = nameTree.LookupValue(index, bsName);
+ pDestObj = nameTree.LookupValueAndName(index, &wsName);
}
if (!pDestObj)
return nullptr;
@@ -1257,8 +1517,7 @@
if (!pDestObj->IsArray())
return nullptr;
- CFX_WideString wsName = PDF_DecodeText(bsName);
- CFX_ByteString utf16Name = wsName.UTF16LE_Encode();
+ ByteString utf16Name = wsName.UTF16LE_Encode();
int len = utf16Name.GetLength();
if (!buffer) {
*buflen = len;
diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c
index 54a3325..53d8776 100644
--- a/fpdfsdk/fpdfview_c_api_test.c
+++ b/fpdfsdk/fpdfview_c_api_test.c
@@ -9,6 +9,9 @@
#include "fpdfsdk/fpdfview_c_api_test.h"
+#include "public/fpdf_annot.h"
+#include "public/fpdf_attachment.h"
+#include "public/fpdf_catalog.h"
#include "public/fpdf_dataavail.h"
#include "public/fpdf_doc.h"
#include "public/fpdf_edit.h"
@@ -33,6 +36,56 @@
// Function to call from gtest harness to ensure linker resolution.
int CheckPDFiumCApi() {
+ // fpdf_annot.h
+ CHK(FPDFAnnot_IsSupportedSubtype);
+ CHK(FPDFPage_CreateAnnot);
+ CHK(FPDFPage_GetAnnotCount);
+ CHK(FPDFPage_GetAnnot);
+ CHK(FPDFPage_GetAnnotIndex);
+ CHK(FPDFPage_CloseAnnot);
+ CHK(FPDFPage_RemoveAnnot);
+ CHK(FPDFAnnot_GetSubtype);
+ CHK(FPDFAnnot_IsObjectSupportedSubtype);
+ CHK(FPDFAnnot_UpdateObject);
+ CHK(FPDFAnnot_AppendObject);
+ CHK(FPDFAnnot_GetObjectCount);
+ CHK(FPDFAnnot_GetObject);
+ CHK(FPDFAnnot_RemoveObject);
+ CHK(FPDFAnnot_SetColor);
+ CHK(FPDFAnnot_GetColor);
+ CHK(FPDFAnnot_HasAttachmentPoints);
+ CHK(FPDFAnnot_SetAttachmentPoints);
+ CHK(FPDFAnnot_GetAttachmentPoints);
+ CHK(FPDFAnnot_SetRect);
+ CHK(FPDFAnnot_GetRect);
+ CHK(FPDFAnnot_HasKey);
+ CHK(FPDFAnnot_GetValueType);
+ CHK(FPDFAnnot_SetStringValue);
+ CHK(FPDFAnnot_GetStringValue);
+ CHK(FPDFAnnot_SetAP);
+ CHK(FPDFAnnot_GetAP);
+ CHK(FPDFAnnot_GetLinkedAnnot);
+ CHK(FPDFAnnot_GetFlags);
+ CHK(FPDFAnnot_SetFlags);
+ CHK(FPDFAnnot_GetFormFieldFlags);
+ CHK(FPDFAnnot_GetFormFieldAtPoint);
+
+ // fpdf_attachment.h
+ CHK(FPDFDoc_GetAttachmentCount);
+ CHK(FPDFDoc_AddAttachment);
+ CHK(FPDFDoc_GetAttachment);
+ CHK(FPDFDoc_DeleteAttachment);
+ CHK(FPDFAttachment_GetName);
+ CHK(FPDFAttachment_HasKey);
+ CHK(FPDFAttachment_GetValueType);
+ CHK(FPDFAttachment_SetStringValue);
+ CHK(FPDFAttachment_GetStringValue);
+ CHK(FPDFAttachment_SetFile);
+ CHK(FPDFAttachment_GetFile);
+
+ // fpdf_catalog.h
+ CHK(FPDFCatalog_IsTagged);
+
// fpdf_dataavail.h
CHK(FPDFAvail_Create);
CHK(FPDFAvail_Destroy);
@@ -56,6 +109,7 @@
CHK(FPDFAction_GetURIPath);
CHK(FPDFDest_GetPageIndex);
CHK(FPDFDest_GetLocationInPage);
+ CHK(FPDFDest_GetView);
CHK(FPDFLink_GetLinkAtPoint);
CHK(FPDFLink_GetLinkZOrderAtPoint);
CHK(FPDFLink_GetDest);
@@ -75,30 +129,53 @@
CHK(FPDFPage_SetRotation);
CHK(FPDFPage_InsertObject);
CHK(FPDFPage_CountObject);
+ CHK(FPDFPage_CountObjects);
CHK(FPDFPage_GetObject);
CHK(FPDFPage_HasTransparency);
CHK(FPDFPage_GenerateContent);
+ CHK(FPDFPageObj_Destroy);
CHK(FPDFPageObj_HasTransparency);
+ CHK(FPDFPageObj_GetBounds);
+ CHK(FPDFPageObj_GetType);
+ CHK(FPDFPageObj_SetBlendMode);
CHK(FPDFPageObj_Transform);
CHK(FPDFPage_TransformAnnots);
- CHK(FPDFPageObj_NewImgeObj);
+ CHK(FPDFPageObj_NewImageObj);
CHK(FPDFImageObj_LoadJpegFile);
CHK(FPDFImageObj_LoadJpegFileInline);
CHK(FPDFImageObj_SetMatrix);
CHK(FPDFImageObj_SetBitmap);
+ CHK(FPDFImageObj_GetBitmap);
+ CHK(FPDFImageObj_GetImageDataDecoded);
+ CHK(FPDFImageObj_GetImageDataRaw);
+ CHK(FPDFImageObj_GetImageFilterCount);
+ CHK(FPDFImageObj_GetImageFilter);
+ CHK(FPDFImageObj_GetImageMetadata);
CHK(FPDFPageObj_CreateNewPath);
CHK(FPDFPageObj_CreateNewRect);
CHK(FPDFPath_SetStrokeColor);
+ CHK(FPDFPath_GetStrokeColor);
CHK(FPDFPath_SetStrokeWidth);
CHK(FPDFPath_SetFillColor);
+ CHK(FPDFPath_GetFillColor);
+ CHK(FPDFPath_CountSegments);
+ CHK(FPDFPath_GetPathSegment);
+ CHK(FPDFPathSegment_GetPoint);
+ CHK(FPDFPathSegment_GetType);
+ CHK(FPDFPathSegment_GetClose);
CHK(FPDFPath_MoveTo);
CHK(FPDFPath_LineTo);
CHK(FPDFPath_BezierTo);
CHK(FPDFPath_Close);
CHK(FPDFPath_SetDrawMode);
+ CHK(FPDFPath_SetLineCap);
+ CHK(FPDFPath_SetLineJoin);
CHK(FPDFPageObj_NewTextObj);
CHK(FPDFText_SetText);
- CHK(FPDFText_LoadType1Font);
+ CHK(FPDFText_SetFillColor);
+ CHK(FPDFText_LoadFont);
+ CHK(FPDFFont_Close);
+ CHK(FPDFPageObj_CreateTextObj);
// fpdf_ext.h
CHK(FSDK_SetUnSpObjProcessHandler);
@@ -119,6 +196,7 @@
CHK(FORM_DoDocumentAAction);
CHK(FORM_DoPageAAction);
CHK(FORM_OnMouseMove);
+ CHK(FORM_OnFocus);
CHK(FORM_OnLButtonDown);
CHK(FORM_OnLButtonUp);
#ifdef PDF_ENABLE_XFA
@@ -128,16 +206,20 @@
CHK(FORM_OnKeyDown);
CHK(FORM_OnKeyUp);
CHK(FORM_OnChar);
+ CHK(FORM_GetSelectedText);
+ CHK(FORM_ReplaceSelection);
CHK(FORM_ForceToKillFocus);
CHK(FPDFPage_HasFormFieldAtPoint);
- CHK(FPDPage_HasFormFieldAtPoint); // DEPRECATED. Remove in the future.
CHK(FPDFPage_FormFieldZOrderAtPoint);
CHK(FPDF_SetFormFieldHighlightColor);
CHK(FPDF_SetFormFieldHighlightAlpha);
CHK(FPDF_RemoveFormFieldHighlight);
CHK(FPDF_FFLDraw);
+#ifdef _SKIA_SUPPORT_
+ CHK(FPDF_FFLRecord);
+#endif
+ CHK(FPDF_GetFormType);
#ifdef PDF_ENABLE_XFA
- CHK(FPDF_HasXFAField);
CHK(FPDF_LoadXFA);
CHK(FPDF_Widget_Undo);
CHK(FPDF_Widget_Redo);
@@ -168,6 +250,7 @@
// fpdf_searchex.h
CHK(FPDFText_GetCharIndexFromTextIndex);
+ CHK(FPDFText_GetTextIndexFromCharIndex);
// fpdf_structtree.h
CHK(FPDF_StructTree_GetForPage);
@@ -175,6 +258,9 @@
CHK(FPDF_StructTree_CountChildren);
CHK(FPDF_StructTree_GetChildAtIndex);
CHK(FPDF_StructElement_GetAltText);
+ CHK(FPDF_StructElement_GetMarkedContentID);
+ CHK(FPDF_StructElement_GetType);
+ CHK(FPDF_StructElement_GetTitle);
CHK(FPDF_StructElement_CountChildren);
CHK(FPDF_StructElement_GetChildAtIndex);
@@ -192,6 +278,7 @@
CHK(FPDFText_GetUnicode);
CHK(FPDFText_GetFontSize);
CHK(FPDFText_GetCharBox);
+ CHK(FPDFText_GetCharOrigin);
CHK(FPDFText_GetCharIndexAtPos);
CHK(FPDFText_GetText);
CHK(FPDFText_CountRects);
@@ -226,6 +313,14 @@
CHK(FPDF_InitLibraryWithConfig);
CHK(FPDF_DestroyLibrary);
CHK(FPDF_SetSandBoxPolicy);
+#if defined(_WIN32)
+#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
+ CHK(FPDF_SetTypefaceAccessibleFunc);
+ CHK(FPDF_SetPrintTextWithGDI);
+#endif
+ CHK(FPDF_SetPrintPostscriptLevel);
+ CHK(FPDF_SetPrintMode);
+#endif
CHK(FPDF_LoadDocument);
CHK(FPDF_LoadMemDocument);
CHK(FPDF_LoadCustomDocument);
@@ -237,15 +332,23 @@
CHK(FPDF_LoadPage);
CHK(FPDF_GetPageWidth);
CHK(FPDF_GetPageHeight);
+ CHK(FPDF_GetPageBoundingBox);
CHK(FPDF_GetPageSizeByIndex);
+#ifdef _WIN32
+ CHK(FPDF_RenderPage);
+#endif
CHK(FPDF_RenderPageBitmap);
CHK(FPDF_RenderPageBitmapWithMatrix);
+#ifdef _SKIA_SUPPORT_
+ CHK(FPDF_RenderPageSkp);
+#endif
CHK(FPDF_ClosePage);
CHK(FPDF_CloseDocument);
CHK(FPDF_DeviceToPage);
CHK(FPDF_PageToDevice);
CHK(FPDFBitmap_Create);
CHK(FPDFBitmap_CreateEx);
+ CHK(FPDFBitmap_GetFormat);
CHK(FPDFBitmap_FillRect);
CHK(FPDFBitmap_GetBuffer);
CHK(FPDFBitmap_GetWidth);
diff --git a/fpdfsdk/fpdfview_embeddertest.cpp b/fpdfsdk/fpdfview_embeddertest.cpp
index 1d94b72..cca77c9 100644
--- a/fpdfsdk/fpdfview_embeddertest.cpp
+++ b/fpdfsdk/fpdfview_embeddertest.cpp
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <cmath>
#include <limits>
#include <string>
@@ -9,12 +10,38 @@
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/utils/path_service.h"
+
+namespace {
+
+class MockDownloadHints : public FX_DOWNLOADHINTS {
+ public:
+ static void SAddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
+ }
+
+ MockDownloadHints() {
+ FX_DOWNLOADHINTS::version = 1;
+ FX_DOWNLOADHINTS::AddSegment = SAddSegment;
+ }
+
+ ~MockDownloadHints() {}
+};
+
+} // namespace
TEST(fpdf, CApiTest) {
EXPECT_TRUE(CheckPDFiumCApi());
}
-class FPDFViewEmbeddertest : public EmbedderTest {};
+class FPDFViewEmbeddertest : public EmbedderTest {
+ protected:
+ void TestRenderPageBitmapWithMatrix(FPDF_PAGE page,
+ const int bitmap_width,
+ const int bitmap_height,
+ const FS_MATRIX& matrix,
+ const FS_RECTF& rect,
+ const char* expected_md5);
+};
TEST_F(FPDFViewEmbeddertest, Document) {
EXPECT_TRUE(OpenDocument("about_blank.pdf"));
@@ -29,6 +56,12 @@
EXPECT_EQ(-1, FPDF_GetSecurityHandlerRevision(document()));
}
+TEST_F(FPDFViewEmbeddertest, LoadNonexistentDocument) {
+ FPDF_DOCUMENT doc = FPDF_LoadDocument("nonexistent_document.pdf", "");
+ ASSERT_FALSE(doc);
+ EXPECT_EQ(static_cast<int>(FPDF_GetLastError()), FPDF_ERR_FILE);
+}
+
// See bug 465.
TEST_F(FPDFViewEmbeddertest, EmptyDocument) {
EXPECT_TRUE(CreateEmptyDocument());
@@ -63,12 +96,28 @@
EXPECT_EQ(0u, FPDF_CountNamedDests(document()));
}
+TEST_F(FPDFViewEmbeddertest, LinearizedDocument) {
+ EXPECT_TRUE(OpenDocumentLinearized("feature_linearized_loading.pdf"));
+ int version;
+ EXPECT_TRUE(FPDF_GetFileVersion(document(), &version));
+ EXPECT_EQ(16, version);
+}
+
TEST_F(FPDFViewEmbeddertest, Page) {
EXPECT_TRUE(OpenDocument("about_blank.pdf"));
FPDF_PAGE page = LoadPage(0);
EXPECT_NE(nullptr, page);
+
EXPECT_EQ(612.0, FPDF_GetPageWidth(page));
EXPECT_EQ(792.0, FPDF_GetPageHeight(page));
+
+ FS_RECTF rect;
+ EXPECT_TRUE(FPDF_GetPageBoundingBox(page, &rect));
+ EXPECT_EQ(0.0, rect.left);
+ EXPECT_EQ(0.0, rect.bottom);
+ EXPECT_EQ(612.0, rect.right);
+ EXPECT_EQ(792.0, rect.top);
+
UnloadPage(page);
EXPECT_EQ(nullptr, LoadPage(1));
}
@@ -304,6 +353,14 @@
// reference loop. Cross references will be rebuilt successfully.
TEST_F(FPDFViewEmbeddertest, CrossRefV4Loop) {
EXPECT_TRUE(OpenDocument("bug_xrefv4_loop.pdf"));
+ MockDownloadHints hints;
+
+ // Make sure calling FPDFAvail_IsDocAvail() on this file does not infinite
+ // loop either. See bug 875.
+ int ret = PDF_DATA_NOTAVAIL;
+ while (ret == PDF_DATA_NOTAVAIL)
+ ret = FPDFAvail_IsDocAvail(avail_, &hints);
+ EXPECT_EQ(PDF_DATA_AVAIL, ret);
}
// The test should pass when circular references to ParseIndirectObject will not
@@ -328,53 +385,217 @@
EXPECT_FALSE(OpenDocument("bug_360.pdf"));
}
-TEST_F(FPDFViewEmbeddertest, FPDF_RenderPageBitmapWithMatrix) {
- const char kAllBlackMd5sum[] = "5708fc5c4a8bd0abde99c8e8f0390615";
- const char kTopLeftQuarterBlackMd5sum[] = "24e4d1ec06fa0258af758cfc8b2ad50a";
+void FPDFViewEmbeddertest::TestRenderPageBitmapWithMatrix(
+ FPDF_PAGE page,
+ const int bitmap_width,
+ const int bitmap_height,
+ const FS_MATRIX& matrix,
+ const FS_RECTF& rect,
+ const char* expected_md5) {
+ FPDF_BITMAP bitmap = FPDFBitmap_Create(bitmap_width, bitmap_height, 0);
+ FPDFBitmap_FillRect(bitmap, 0, 0, bitmap_width, bitmap_height, 0xFFFFFFFF);
+ FPDF_RenderPageBitmapWithMatrix(bitmap, page, &matrix, &rect, 0);
+ CompareBitmap(bitmap, bitmap_width, bitmap_height, expected_md5);
+ FPDFBitmap_Destroy(bitmap);
+}
- EXPECT_TRUE(OpenDocument("black.pdf"));
+TEST_F(FPDFViewEmbeddertest, FPDF_RenderPageBitmapWithMatrix) {
+ const char kOriginalMD5[] = "0a90de37f52127619c3dfb642b5fa2fe";
+ const char kClippedMD5[] = "a84cab93c102b9b9290fba3047ba702c";
+ const char kTopLeftQuarterMD5[] = "f11a11137c8834389e31cf555a4a6979";
+ const char kHoriStretchedMD5[] = "48ef9205941ed19691ccfa00d717187e";
+ const char kRotated90ClockwiseMD5[] = "d8da2c7bf77521550d0f2752b9cf3482";
+ const char kRotated180ClockwiseMD5[] = "0113386bb0bd45125bacc6dee78bfe78";
+ const char kRotated270ClockwiseMD5[] = "a287e0f74ce203699cda89f9cc97a240";
+ const char kMirrorHoriMD5[] = "6e8d7a6fde39d8e720fb9e620102918c";
+ const char kMirrorVertMD5[] = "8f3a555ef9c0d5031831ae3715273707";
+ const char kLargerTopLeftQuarterMD5[] = "172a2f4adafbadbe98017b1c025b9e27";
+ const char kLargerMD5[] = "c806145641c3e6fc4e022c7065343749";
+ const char kLargerClippedMD5[] = "091d3b1c7933c8f6945eb2cb41e588e9";
+ const char kLargerRotatedMD5[] = "115f13353ebfc82ddb392d1f0059eb12";
+ const char kLargerRotatedLandscapeMD5[] = "c901239d17d84ac84cb6f2124da71b0d";
+ const char kLargerRotatedDiagonalMD5[] = "3d62417468bdaff0eb14391a0c30a3b1";
+ const char kTileMD5[] = "0a190003c97220bf8877684c8d7e89cf";
+
+ EXPECT_TRUE(OpenDocument("rectangles.pdf"));
FPDF_PAGE page = LoadPage(0);
EXPECT_NE(nullptr, page);
- const int width = static_cast<int>(FPDF_GetPageWidth(page));
- const int height = static_cast<int>(FPDF_GetPageHeight(page));
- EXPECT_EQ(612, width);
- EXPECT_EQ(792, height);
+ const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
+ const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
+ EXPECT_EQ(200, page_width);
+ EXPECT_EQ(300, page_height);
FPDF_BITMAP bitmap = RenderPage(page);
- CompareBitmap(bitmap, width, height, kAllBlackMd5sum);
+ CompareBitmap(bitmap, page_width, page_height, kOriginalMD5);
FPDFBitmap_Destroy(bitmap);
+ FS_RECTF page_rect{0, 0, page_width, page_height};
+
// Try rendering with an identity matrix. The output should be the same as
// the RenderPage() output.
- FS_MATRIX matrix;
- matrix.a = 1;
- matrix.b = 0;
- matrix.c = 0;
- matrix.d = 1;
- matrix.e = 0;
- matrix.f = 0;
+ FS_MATRIX identity_matrix{1, 0, 0, 1, 0, 0};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height, identity_matrix,
+ page_rect, kOriginalMD5);
- FS_RECTF rect;
- rect.left = 0;
- rect.top = 0;
- rect.right = width;
- rect.bottom = height;
+ // Again render with an identity matrix but with a smaller clipping rect.
+ FS_RECTF middle_of_page_rect{page_width / 4, page_height / 4,
+ page_width * 3 / 4, page_height * 3 / 4};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height, identity_matrix,
+ middle_of_page_rect, kClippedMD5);
- bitmap = FPDFBitmap_Create(width, height, 0);
- FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);
- FPDF_RenderPageBitmapWithMatrix(bitmap, page, &matrix, &rect, 0);
- CompareBitmap(bitmap, width, height, kAllBlackMd5sum);
- FPDFBitmap_Destroy(bitmap);
+ // Now render again with the image scaled smaller.
+ FS_MATRIX half_scale_matrix{0.5, 0, 0, 0.5, 0, 0};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height,
+ half_scale_matrix, page_rect,
+ kTopLeftQuarterMD5);
- // Now render again with the image scaled.
- matrix.a = 0.5;
- matrix.d = 0.5;
+ // Now render again with the image scaled larger horizontally (the right half
+ // will be clipped).
+ FS_MATRIX stretch_x_matrix{2, 0, 0, 1, 0, 0};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height,
+ stretch_x_matrix, page_rect,
+ kHoriStretchedMD5);
- bitmap = FPDFBitmap_Create(width, height, 0);
- FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);
- FPDF_RenderPageBitmapWithMatrix(bitmap, page, &matrix, &rect, 0);
- CompareBitmap(bitmap, width, height, kTopLeftQuarterBlackMd5sum);
- FPDFBitmap_Destroy(bitmap);
+ // Try a 90 degree rotation clockwise but with the same bitmap size, so part
+ // will be clipped.
+ FS_MATRIX rotate_90_matrix{0, 1, -1, 0, page_width, 0};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height,
+ rotate_90_matrix, page_rect,
+ kRotated90ClockwiseMD5);
+
+ // 180 degree rotation clockwise.
+ FS_MATRIX rotate_180_matrix{-1, 0, 0, -1, page_width, page_height};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height,
+ rotate_180_matrix, page_rect,
+ kRotated180ClockwiseMD5);
+
+ // 270 degree rotation clockwise.
+ FS_MATRIX rotate_270_matrix{0, -1, 1, 0, 0, page_width};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height,
+ rotate_270_matrix, page_rect,
+ kRotated270ClockwiseMD5);
+
+ // Mirror horizontally.
+ FS_MATRIX mirror_hori_matrix{-1, 0, 0, 1, page_width, 0};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height,
+ mirror_hori_matrix, page_rect, kMirrorHoriMD5);
+
+ // Mirror vertically.
+ FS_MATRIX mirror_vert_matrix{1, 0, 0, -1, 0, page_height};
+ TestRenderPageBitmapWithMatrix(page, page_width, page_height,
+ mirror_vert_matrix, page_rect, kMirrorVertMD5);
+
+ // Tests rendering to a larger bitmap
+ const int bitmap_width = page_width * 2;
+ const int bitmap_height = page_height * 2;
+
+ // Render using an identity matrix and the whole bitmap area as clipping rect.
+ FS_RECTF bitmap_rect{0, 0, bitmap_width, bitmap_height};
+ TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height,
+ identity_matrix, bitmap_rect,
+ kLargerTopLeftQuarterMD5);
+
+ // Render using a scaling matrix to fill the larger bitmap.
+ FS_MATRIX double_scale_matrix{2, 0, 0, 2, 0, 0};
+ TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height,
+ double_scale_matrix, bitmap_rect, kLargerMD5);
+
+ // Render the larger image again but with clipping.
+ FS_RECTF middle_of_bitmap_rect{bitmap_width / 4, bitmap_height / 4,
+ bitmap_width * 3 / 4, bitmap_height * 3 / 4};
+ TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height,
+ double_scale_matrix, middle_of_bitmap_rect,
+ kLargerClippedMD5);
+
+ // On the larger bitmap, try a 90 degree rotation but with the same bitmap
+ // size, so part will be clipped.
+ FS_MATRIX rotate_90_scale_2_matrix{0, 2, -2, 0, bitmap_width, 0};
+ TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height,
+ rotate_90_scale_2_matrix, bitmap_rect,
+ kLargerRotatedMD5);
+
+ // On the larger bitmap, apply 90 degree rotation to a bitmap with the
+ // appropriate dimensions.
+ const int landscape_bitmap_width = bitmap_height;
+ const int landscape_bitmap_height = bitmap_width;
+ FS_RECTF landscape_bitmap_rect{0, 0, landscape_bitmap_width,
+ landscape_bitmap_height};
+ FS_MATRIX landscape_rotate_90_scale_2_matrix{
+ 0, 2, -2, 0, landscape_bitmap_width, 0};
+ TestRenderPageBitmapWithMatrix(
+ page, landscape_bitmap_width, landscape_bitmap_height,
+ landscape_rotate_90_scale_2_matrix, landscape_bitmap_rect,
+ kLargerRotatedLandscapeMD5);
+
+ // On the larger bitmap, apply 45 degree rotation to a bitmap with the
+ // appropriate dimensions.
+ const float sqrt2 = 1.41421356f;
+ const int diagonal_bitmap_size = ceil((bitmap_width + bitmap_height) / sqrt2);
+ FS_RECTF diagonal_bitmap_rect{0, 0, diagonal_bitmap_size,
+ diagonal_bitmap_size};
+ FS_MATRIX rotate_45_scale_2_matrix{
+ sqrt2, sqrt2, -sqrt2, sqrt2, bitmap_height / sqrt2, 0};
+ TestRenderPageBitmapWithMatrix(page, diagonal_bitmap_size,
+ diagonal_bitmap_size, rotate_45_scale_2_matrix,
+ diagonal_bitmap_rect,
+ kLargerRotatedDiagonalMD5);
+
+ // Render the (2, 1) tile of the page (third column, second row) when the page
+ // is divided in 50x50 pixel tiles. The tile is scaled by a factor of 7.
+ const float scale = 7.0;
+ const int tile_size = 50;
+ const int tile_x = 2;
+ const int tile_y = 1;
+ int tile_bitmap_size = scale * tile_size;
+ FS_RECTF tile_bitmap_rect{0, 0, tile_bitmap_size, tile_bitmap_size};
+ FS_MATRIX tile_2_1_matrix{scale,
+ 0,
+ 0,
+ scale,
+ -tile_x * tile_bitmap_size,
+ -tile_y * tile_bitmap_size};
+ TestRenderPageBitmapWithMatrix(page, tile_bitmap_size, tile_bitmap_size,
+ tile_2_1_matrix, tile_bitmap_rect, kTileMD5);
UnloadPage(page);
}
+
+class UnSupRecordDelegate : public EmbedderTest::Delegate {
+ public:
+ UnSupRecordDelegate() : type_(-1) {}
+ ~UnSupRecordDelegate() override {}
+
+ void UnsupportedHandler(int type) override { type_ = type; }
+
+ int type_;
+};
+
+TEST_F(FPDFViewEmbeddertest, UnSupportedOperations_NotFound) {
+ UnSupRecordDelegate delegate;
+ SetDelegate(&delegate);
+ ASSERT_TRUE(OpenDocument("hello_world.pdf"));
+ EXPECT_EQ(delegate.type_, -1);
+ SetDelegate(nullptr);
+}
+
+TEST_F(FPDFViewEmbeddertest, UnSupportedOperations_LoadCustomDocument) {
+ UnSupRecordDelegate delegate;
+ SetDelegate(&delegate);
+ ASSERT_TRUE(OpenDocument("unsupported_feature.pdf"));
+ EXPECT_EQ(FPDF_UNSP_DOC_PORTABLECOLLECTION, delegate.type_);
+ SetDelegate(nullptr);
+}
+
+TEST_F(FPDFViewEmbeddertest, UnSupportedOperations_LoadDocument) {
+ std::string file_path;
+ ASSERT_TRUE(
+ PathService::GetTestFilePath("unsupported_feature.pdf", &file_path));
+
+ UnSupRecordDelegate delegate;
+ SetDelegate(&delegate);
+ FPDF_DOCUMENT doc = FPDF_LoadDocument(file_path.c_str(), "");
+ EXPECT_TRUE(doc != nullptr);
+ EXPECT_EQ(FPDF_UNSP_DOC_PORTABLECOLLECTION, delegate.type_);
+ FPDF_CloseDocument(doc);
+ SetDelegate(nullptr);
+}
diff --git a/fpdfsdk/fpdfview_unittest.cpp b/fpdfsdk/fpdfview_unittest.cpp
deleted file mode 100644
index 27680b3..0000000
--- a/fpdfsdk/fpdfview_unittest.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 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.
-
-#include "public/fpdfview.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/test_support.h"
-
-TEST(FPDFView, DoubleInit) {
- FPDF_InitLibrary();
- FPDF_InitLibrary();
- FPDF_DestroyLibrary();
-}
-
-TEST(FPDFView, DoubleDestroy) {
- FPDF_InitLibrary();
- FPDF_DestroyLibrary();
- FPDF_DestroyLibrary();
-}
diff --git a/fpdfsdk/fpdfxfa/DEPS b/fpdfsdk/fpdfxfa/DEPS
index 1687e30..5ba75f2 100644
--- a/fpdfsdk/fpdfxfa/DEPS
+++ b/fpdfsdk/fpdfxfa/DEPS
@@ -1,4 +1,5 @@
include_rules = [
'+fxjs',
- '+xfa/fxbarcode',
+ '+fxbarcode',
+ '+xfa/fgas/font',
]
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
index 88c88a1..d05e2f6 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
@@ -6,6 +6,7 @@
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
+#include <algorithm>
#include <utility>
#include "core/fpdfapi/parser/cpdf_document.h"
@@ -15,18 +16,19 @@
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
#include "fpdfsdk/fsdk_define.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fpdfsdk/javascript/ijs_runtime.h"
+#include "fxjs/cjs_runtime.h"
+#include "fxjs/ijs_runtime.h"
#include "public/fpdf_formfill.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"
+#include "xfa/fgas/font/cfgas_defaultfontmanager.h"
#include "xfa/fxfa/cxfa_eventparam.h"
-#include "xfa/fxfa/xfa_ffapp.h"
-#include "xfa/fxfa/xfa_ffdoc.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffpageview.h"
-#include "xfa/fxfa/xfa_ffwidgethandler.h"
-#include "xfa/fxfa/xfa_fontmgr.h"
+#include "xfa/fxfa/cxfa_ffapp.h"
+#include "xfa/fxfa/cxfa_ffdoc.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffpageview.h"
+#include "xfa/fxfa/cxfa_ffwidgethandler.h"
+#include "xfa/fxfa/cxfa_fontmgr.h"
#ifndef _WIN32
extern void SetLastError(int err);
@@ -34,15 +36,10 @@
#endif
CPDFXFA_Context::CPDFXFA_Context(std::unique_ptr<CPDF_Document> pPDFDoc)
- : m_iDocType(DOCTYPE_PDF),
- m_pPDFDoc(std::move(pPDFDoc)),
- m_pFormFillEnv(nullptr),
- m_pXFADocView(nullptr),
- m_nLoadStatus(FXFA_LOADSTATUS_PRELOAD),
- m_nPageCount(0),
+ : m_pPDFDoc(std::move(pPDFDoc)),
+ m_pXFAApp(pdfium::MakeUnique<CXFA_FFApp>(this)),
m_DocEnv(this) {
- m_pXFAApp = pdfium::MakeUnique<CXFA_FFApp>(this);
- m_pXFAApp->SetDefaultFontMgr(pdfium::MakeUnique<CXFA_DefFontMgr>());
+ m_pXFAApp->SetDefaultFontMgr(pdfium::MakeUnique<CFGAS_DefaultFontManager>());
}
CPDFXFA_Context::~CPDFXFA_Context() {
@@ -56,7 +53,7 @@
// Once we're deleted the FormFillEnvironment will point at a bad underlying
// doc so we need to reset it ...
m_pFormFillEnv->ResetXFADocument();
- m_pFormFillEnv = nullptr;
+ m_pFormFillEnv.Reset();
}
m_nLoadStatus = FXFA_LOADSTATUS_CLOSED;
@@ -65,9 +62,10 @@
void CPDFXFA_Context::CloseXFADoc() {
if (!m_pXFADoc)
return;
+
+ m_pXFADocView = nullptr;
m_pXFADoc->CloseDoc();
m_pXFADoc.reset();
- m_pXFADocView = nullptr;
}
void CPDFXFA_Context::SetFormFillEnv(
@@ -78,7 +76,7 @@
if (m_pXFADoc && m_pXFADoc->GetXFADoc())
m_pXFADoc->GetXFADoc()->ClearLayoutData();
- m_pFormFillEnv = pFormFillEnv;
+ m_pFormFillEnv.Reset(pFormFillEnv);
}
bool CPDFXFA_Context::LoadXFADoc() {
@@ -98,14 +96,8 @@
return false;
}
- CXFA_FFDocHandler* pDocHandler = pApp->GetDocHandler();
- if (!pDocHandler) {
- SetLastError(FPDF_ERR_XFALOAD);
- return false;
- }
-
m_pXFADoc->StartLoad();
- int iStatus = m_pXFADoc->DoLoad(nullptr);
+ int iStatus = m_pXFADoc->DoLoad();
if (iStatus != XFA_PARSESTATUS_Done) {
CloseXFADoc();
SetLastError(FPDF_ERR_XFALOAD);
@@ -114,19 +106,19 @@
m_pXFADoc->StopLoad();
m_pXFADoc->GetXFADoc()->InitScriptContext(GetJSERuntime());
- if (m_pXFADoc->GetDocType() == XFA_DOCTYPE_Dynamic)
- m_iDocType = DOCTYPE_DYNAMIC_XFA;
+ if (m_pXFADoc->GetFormType() == FormType::kXFAFull)
+ m_FormType = FormType::kXFAFull;
else
- m_iDocType = DOCTYPE_STATIC_XFA;
+ m_FormType = FormType::kXFAForeground;
- m_pXFADocView = m_pXFADoc->CreateDocView(XFA_DOCVIEW_View);
+ m_pXFADocView = m_pXFADoc->CreateDocView();
if (m_pXFADocView->StartLayout() < 0) {
CloseXFADoc();
SetLastError(FPDF_ERR_XFALAYOUT);
return false;
}
- m_pXFADocView->DoLayout(nullptr);
+ m_pXFADocView->DoLayout();
m_pXFADocView->StopLayout();
m_nLoadStatus = FXFA_LOADSTATUS_LOADED;
@@ -137,59 +129,53 @@
if (!m_pPDFDoc && !m_pXFADoc)
return 0;
- switch (m_iDocType) {
- case DOCTYPE_PDF:
- case DOCTYPE_STATIC_XFA:
+ switch (m_FormType) {
+ case FormType::kNone:
+ case FormType::kAcroForm:
+ case FormType::kXFAForeground:
if (m_pPDFDoc)
return m_pPDFDoc->GetPageCount();
- case DOCTYPE_DYNAMIC_XFA:
+ case FormType::kXFAFull:
if (m_pXFADoc)
return m_pXFADocView->CountPageViews();
- default:
- return 0;
}
+ return 0;
}
-CPDFXFA_Page* CPDFXFA_Context::GetXFAPage(int page_index) {
+RetainPtr<CPDFXFA_Page> CPDFXFA_Context::GetXFAPage(int page_index) {
if (page_index < 0)
return nullptr;
- CPDFXFA_Page* pPage = nullptr;
- int nCount = pdfium::CollectionSize<int>(m_XFAPageList);
- if (nCount > 0 && page_index < nCount) {
- pPage = m_XFAPageList[page_index];
- if (pPage) {
- pPage->Retain();
- return pPage;
- }
+ if (pdfium::IndexInBounds(m_XFAPageList, page_index)) {
+ if (m_XFAPageList[page_index])
+ return m_XFAPageList[page_index];
} else {
m_nPageCount = GetPageCount();
m_XFAPageList.resize(m_nPageCount);
}
- pPage = new CPDFXFA_Page(this, page_index);
- if (!pPage->LoadPage()) {
- pPage->Release();
+ auto pPage = pdfium::MakeRetain<CPDFXFA_Page>(this, page_index);
+ if (!pPage->LoadPage())
return nullptr;
- }
- if (page_index >= 0 &&
- page_index < pdfium::CollectionSize<int>(m_XFAPageList)) {
+
+ if (pdfium::IndexInBounds(m_XFAPageList, page_index))
m_XFAPageList[page_index] = pPage;
- }
+
return pPage;
}
-CPDFXFA_Page* CPDFXFA_Context::GetXFAPage(CXFA_FFPageView* pPage) const {
+RetainPtr<CPDFXFA_Page> CPDFXFA_Context::GetXFAPage(
+ CXFA_FFPageView* pPage) const {
if (!pPage)
return nullptr;
if (!m_pXFADoc)
return nullptr;
- if (m_iDocType != DOCTYPE_DYNAMIC_XFA)
+ if (m_FormType != FormType::kXFAFull)
return nullptr;
- for (CPDFXFA_Page* pTempPage : m_XFAPageList) {
+ for (auto& pTempPage : m_XFAPageList) {
if (pTempPage && pTempPage->GetXFAPageView() == pPage)
return pTempPage;
}
@@ -203,20 +189,8 @@
if (m_pPDFDoc)
m_pPDFDoc->DeletePage(page_index);
- if (page_index < 0 ||
- page_index >= pdfium::CollectionSize<int>(m_XFAPageList)) {
- return;
- }
- if (CPDFXFA_Page* pPage = m_XFAPageList[page_index])
- pPage->Release();
-}
-
-void CPDFXFA_Context::RemovePage(CPDFXFA_Page* page) {
- int page_index = page->GetPageIndex();
- if (page_index >= 0 &&
- page_index < pdfium::CollectionSize<int>(m_XFAPageList)) {
- m_XFAPageList[page_index] = nullptr;
- }
+ if (pdfium::IndexInBounds(m_XFAPageList, page_index))
+ m_XFAPageList[page_index].Reset();
}
void CPDFXFA_Context::ClearChangeMark() {
@@ -234,19 +208,19 @@
return runtime->GetIsolate();
}
-CFX_WideString CPDFXFA_Context::GetAppTitle() const {
+WideString CPDFXFA_Context::GetAppTitle() const {
return L"PDFium";
}
-CFX_WideString CPDFXFA_Context::GetAppName() {
+WideString CPDFXFA_Context::GetAppName() {
return m_pFormFillEnv ? m_pFormFillEnv->FFI_GetAppName() : L"";
}
-CFX_WideString CPDFXFA_Context::GetLanguage() {
+WideString CPDFXFA_Context::GetLanguage() {
return m_pFormFillEnv ? m_pFormFillEnv->GetLanguage() : L"";
}
-CFX_WideString CPDFXFA_Context::GetPlatform() {
+WideString CPDFXFA_Context::GetPlatform() {
return m_pFormFillEnv ? m_pFormFillEnv->GetPlatform() : L"";
}
@@ -255,8 +229,8 @@
m_pFormFillEnv->JS_appBeep(dwType);
}
-int32_t CPDFXFA_Context::MsgBox(const CFX_WideString& wsMessage,
- const CFX_WideString& wsTitle,
+int32_t CPDFXFA_Context::MsgBox(const WideString& wsMessage,
+ const WideString& wsTitle,
uint32_t dwIconType,
uint32_t dwButtonType) {
if (!m_pFormFillEnv)
@@ -307,43 +281,40 @@
return XFA_IDYes;
}
-CFX_WideString CPDFXFA_Context::Response(const CFX_WideString& wsQuestion,
- const CFX_WideString& wsTitle,
- const CFX_WideString& wsDefaultAnswer,
- bool bMark) {
- CFX_WideString wsAnswer;
+WideString CPDFXFA_Context::Response(const WideString& wsQuestion,
+ const WideString& wsTitle,
+ const WideString& wsDefaultAnswer,
+ bool bMark) {
if (!m_pFormFillEnv)
- return wsAnswer;
+ return WideString();
int nLength = 2048;
- char* pBuff = new char[nLength];
+ std::vector<uint8_t> pBuff(nLength);
nLength = m_pFormFillEnv->JS_appResponse(wsQuestion.c_str(), wsTitle.c_str(),
wsDefaultAnswer.c_str(), nullptr,
- bMark, pBuff, nLength);
- if (nLength > 0) {
- nLength = nLength > 2046 ? 2046 : nLength;
- pBuff[nLength] = 0;
- pBuff[nLength + 1] = 0;
- wsAnswer = CFX_WideString::FromUTF16LE(
- reinterpret_cast<const unsigned short*>(pBuff),
- nLength / sizeof(unsigned short));
- }
- delete[] pBuff;
- return wsAnswer;
+ bMark, pBuff.data(), nLength);
+ if (nLength <= 0)
+ return WideString();
+
+ nLength = std::min(2046, nLength);
+ pBuff[nLength] = 0;
+ pBuff[nLength + 1] = 0;
+ return WideString::FromUTF16LE(reinterpret_cast<uint16_t*>(pBuff.data()),
+ nLength / sizeof(uint16_t));
}
-CFX_RetainPtr<IFX_SeekableReadStream> CPDFXFA_Context::DownloadURL(
- const CFX_WideString& wsURL) {
+RetainPtr<IFX_SeekableReadStream> CPDFXFA_Context::DownloadURL(
+ const WideString& wsURL) {
return m_pFormFillEnv ? m_pFormFillEnv->DownloadFromURL(wsURL.c_str())
: nullptr;
}
-bool CPDFXFA_Context::PostRequestURL(const CFX_WideString& wsURL,
- const CFX_WideString& wsData,
- const CFX_WideString& wsContentType,
- const CFX_WideString& wsEncode,
- const CFX_WideString& wsHeader,
- CFX_WideString& wsResponse) {
+bool CPDFXFA_Context::PostRequestURL(const WideString& wsURL,
+ const WideString& wsData,
+ const WideString& wsContentType,
+ const WideString& wsEncode,
+ const WideString& wsHeader,
+ WideString& wsResponse) {
if (!m_pFormFillEnv)
return false;
@@ -353,9 +324,9 @@
return true;
}
-bool CPDFXFA_Context::PutRequestURL(const CFX_WideString& wsURL,
- const CFX_WideString& wsData,
- const CFX_WideString& wsEncode) {
+bool CPDFXFA_Context::PutRequestURL(const WideString& wsURL,
+ const WideString& wsData,
+ const WideString& wsEncode) {
return m_pFormFillEnv &&
m_pFormFillEnv->PutRequestURL(wsURL.c_str(), wsData.c_str(),
wsEncode.c_str());
@@ -364,6 +335,6 @@
IFWL_AdapterTimerMgr* CPDFXFA_Context::GetTimerMgr() {
CXFA_FWLAdapterTimerMgr* pAdapter = nullptr;
if (m_pFormFillEnv)
- pAdapter = new CXFA_FWLAdapterTimerMgr(m_pFormFillEnv);
+ pAdapter = new CXFA_FWLAdapterTimerMgr(m_pFormFillEnv.Get());
return pAdapter;
}
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.h b/fpdfsdk/fpdfxfa/cpdfxfa_context.h
index 9a2a517..acef8f2 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.h
@@ -10,12 +10,15 @@
#include <memory>
#include <vector>
+#include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/observable.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h"
-#include "xfa/fxfa/xfa_ffdoc.h"
+#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
+#include "xfa/fxfa/cxfa_ffdoc.h"
class CJS_Runtime;
class CPDFSDK_FormFillEnvironment;
-class CPDFXFA_Page;
class CXFA_FFDocHandler;
class IJS_EventContext;
class IJS_Runtime;
@@ -36,50 +39,52 @@
bool LoadXFADoc();
CPDF_Document* GetPDFDoc() { return m_pPDFDoc.get(); }
CXFA_FFDoc* GetXFADoc() { return m_pXFADoc.get(); }
- CXFA_FFDocView* GetXFADocView() { return m_pXFADocView; }
- int GetDocType() const { return m_iDocType; }
+ CXFA_FFDocView* GetXFADocView() { return m_pXFADocView.Get(); }
+ FormType GetFormType() const { return m_FormType; }
+ bool ContainsXFAForm() const {
+ return m_FormType == FormType::kXFAFull ||
+ m_FormType == FormType::kXFAForeground;
+ }
v8::Isolate* GetJSERuntime() const;
CXFA_FFApp* GetXFAApp() { return m_pXFAApp.get(); }
- CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; }
+ CPDFSDK_FormFillEnvironment* GetFormFillEnv() const {
+ return m_pFormFillEnv.Get();
+ }
void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void DeletePage(int page_index);
int GetPageCount() const;
-
- CPDFXFA_Page* GetXFAPage(int page_index);
- CPDFXFA_Page* GetXFAPage(CXFA_FFPageView* pPage) const;
-
- void RemovePage(CPDFXFA_Page* page);
-
+ void DeletePage(int page_index);
+ RetainPtr<CPDFXFA_Page> GetXFAPage(int page_index);
+ RetainPtr<CPDFXFA_Page> GetXFAPage(CXFA_FFPageView* pPage) const;
void ClearChangeMark();
// IFXA_AppProvider:
- CFX_WideString GetLanguage() override;
- CFX_WideString GetPlatform() override;
- CFX_WideString GetAppName() override;
- CFX_WideString GetAppTitle() const override;
+ WideString GetLanguage() override;
+ WideString GetPlatform() override;
+ WideString GetAppName() override;
+ WideString GetAppTitle() const override;
void Beep(uint32_t dwType) override;
- int32_t MsgBox(const CFX_WideString& wsMessage,
- const CFX_WideString& wsTitle,
+ int32_t MsgBox(const WideString& wsMessage,
+ const WideString& wsTitle,
uint32_t dwIconType,
uint32_t dwButtonType) override;
- CFX_WideString Response(const CFX_WideString& wsQuestion,
- const CFX_WideString& wsTitle,
- const CFX_WideString& wsDefaultAnswer,
- bool bMark) override;
- CFX_RetainPtr<IFX_SeekableReadStream> DownloadURL(
- const CFX_WideString& wsURL) override;
- bool PostRequestURL(const CFX_WideString& wsURL,
- const CFX_WideString& wsData,
- const CFX_WideString& wsContentType,
- const CFX_WideString& wsEncode,
- const CFX_WideString& wsHeader,
- CFX_WideString& wsResponse) override;
- bool PutRequestURL(const CFX_WideString& wsURL,
- const CFX_WideString& wsData,
- const CFX_WideString& wsEncode) override;
+ WideString Response(const WideString& wsQuestion,
+ const WideString& wsTitle,
+ const WideString& wsDefaultAnswer,
+ bool bMark) override;
+ RetainPtr<IFX_SeekableReadStream> DownloadURL(
+ const WideString& wsURL) override;
+ bool PostRequestURL(const WideString& wsURL,
+ const WideString& wsData,
+ const WideString& wsContentType,
+ const WideString& wsEncode,
+ const WideString& wsHeader,
+ WideString& wsResponse) override;
+ bool PutRequestURL(const WideString& wsURL,
+ const WideString& wsData,
+ const WideString& wsEncode) override;
IFWL_AdapterTimerMgr* GetTimerMgr() override;
@@ -93,22 +98,23 @@
}
LoadStatus GetLoadStatus() const { return m_nLoadStatus; }
- std::vector<CPDFXFA_Page*>* GetXFAPageList() { return &m_XFAPageList; }
+ std::vector<RetainPtr<CPDFXFA_Page>>* GetXFAPageList() {
+ return &m_XFAPageList;
+ }
private:
void CloseXFADoc();
- int m_iDocType;
-
+ FormType m_FormType = FormType::kNone;
std::unique_ptr<CPDF_Document> m_pPDFDoc;
std::unique_ptr<CXFA_FFDoc> m_pXFADoc;
- CPDFSDK_FormFillEnvironment* m_pFormFillEnv; // not owned.
- CXFA_FFDocView* m_pXFADocView; // not owned.
+ Observable<CPDFSDK_FormFillEnvironment>::ObservedPtr m_pFormFillEnv;
+ UnownedPtr<CXFA_FFDocView> m_pXFADocView;
std::unique_ptr<CXFA_FFApp> m_pXFAApp;
std::unique_ptr<CJS_Runtime> m_pRuntime;
- std::vector<CPDFXFA_Page*> m_XFAPageList;
- LoadStatus m_nLoadStatus;
- int m_nPageCount;
+ std::vector<RetainPtr<CPDFXFA_Page>> m_XFAPageList;
+ LoadStatus m_nLoadStatus = FXFA_LOADSTATUS_PRELOAD;
+ int m_nPageCount = 0;
// Must be destroyed before |m_pFormFillEnv|.
CPDFXFA_DocEnvironment m_DocEnv;
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
index 731b0cc..4ebe8f9 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
@@ -11,16 +11,18 @@
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fpdfapi/parser/cpdf_string.h"
-#include "core/fxcrt/cfx_retain_ptr.h"
+#include "core/fxcrt/retain_ptr.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_interform.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
-#include "fpdfsdk/javascript/ijs_runtime.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffwidget.h"
-#include "xfa/fxfa/xfa_ffwidgethandler.h"
+#include "fxjs/ijs_runtime.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
+#include "xfa/fxfa/cxfa_ffwidgethandler.h"
+#include "xfa/fxfa/cxfa_widgetacciterator.h"
+#include "xfa/fxfa/parser/cxfa_submit.h"
#define IDS_XFA_Validate_Input \
"At least one required field was empty. Please fill in the required " \
@@ -38,16 +40,11 @@
#define FXFA_XFA_ALL 0x01111111
CPDFXFA_DocEnvironment::CPDFXFA_DocEnvironment(CPDFXFA_Context* pContext)
- : m_pContext(pContext), m_pJSEventContext(nullptr) {
+ : m_pContext(pContext) {
ASSERT(m_pContext);
}
-CPDFXFA_DocEnvironment::~CPDFXFA_DocEnvironment() {
- if (m_pJSEventContext && m_pContext->GetFormFillEnv()) {
- m_pContext->GetFormFillEnv()->GetJSRuntime()->ReleaseEventContext(
- m_pJSEventContext);
- }
-}
+CPDFXFA_DocEnvironment::~CPDFXFA_DocEnvironment() {}
void CPDFXFA_DocEnvironment::SetChangeMark(CXFA_FFDoc* hDoc) {
if (hDoc == m_pContext->GetXFADoc() && m_pContext->GetFormFillEnv())
@@ -55,15 +52,14 @@
}
void CPDFXFA_DocEnvironment::InvalidateRect(CXFA_FFPageView* pPageView,
- const CFX_RectF& rt,
- uint32_t dwFlags /* = 0 */) {
+ const CFX_RectF& rt) {
if (!m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
return;
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA)
+ if (m_pContext->GetFormType() != FormType::kXFAFull)
return;
- CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pPageView);
+ RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pPageView);
if (!pPage)
return;
@@ -71,8 +67,7 @@
if (!pFormFillEnv)
return;
- pFormFillEnv->Invalidate(static_cast<FPDF_PAGE>(pPage),
- CFX_FloatRect::FromCFXRectF(rt).ToFxRect());
+ pFormFillEnv->Invalidate(pPage.Get(), rt.ToFloatRect().ToFxRect());
}
void CPDFXFA_DocEnvironment::DisplayCaret(CXFA_FFWidget* hWidget,
@@ -82,7 +77,7 @@
!m_pContext->GetFormFillEnv() || !m_pContext->GetXFADocView())
return;
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA)
+ if (m_pContext->GetFormType() != FormType::kXFAFull)
return;
CXFA_FFWidgetHandler* pWidgetHandler =
@@ -94,7 +89,7 @@
if (!pPageView)
return;
- CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pPageView);
+ RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pPageView);
if (!pPage)
return;
@@ -102,14 +97,14 @@
if (!pFormFillEnv)
return;
- CFX_FloatRect rcCaret = CFX_FloatRect::FromCFXRectF(*pRtAnchor);
- pFormFillEnv->DisplayCaret((FPDF_PAGE)pPage, bVisible, rcCaret.left,
- rcCaret.top, rcCaret.right, rcCaret.bottom);
+ CFX_FloatRect rcCaret = pRtAnchor->ToFloatRect();
+ pFormFillEnv->DisplayCaret(pPage.Get(), bVisible, rcCaret.left, rcCaret.top,
+ rcCaret.right, rcCaret.bottom);
}
bool CPDFXFA_DocEnvironment::GetPopupPos(CXFA_FFWidget* hWidget,
- FX_FLOAT fMinPopup,
- FX_FLOAT fMaxPopup,
+ float fMinPopup,
+ float fMaxPopup,
const CFX_RectF& rtAnchor,
CFX_RectF& rtPopup) {
if (!hWidget)
@@ -119,22 +114,21 @@
if (!pXFAPageView)
return false;
- CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pXFAPageView);
+ RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pXFAPageView);
if (!pPage)
return false;
- CXFA_WidgetAcc* pWidgetAcc = hWidget->GetDataAcc();
- int nRotate = pWidgetAcc->GetRotate();
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return false;
FS_RECTF pageViewRect = {0.0f, 0.0f, 0.0f, 0.0f};
- pFormFillEnv->GetPageViewRect(pPage, pageViewRect);
+ pFormFillEnv->GetPageViewRect(pPage.Get(), pageViewRect);
int t1;
int t2;
- CFX_FloatRect rcAnchor = CFX_FloatRect::FromCFXRectF(rtAnchor);
+ CFX_FloatRect rcAnchor = rtAnchor.ToFloatRect();
+ int nRotate = hWidget->GetNode()->GetRotate();
switch (nRotate) {
case 90: {
t1 = (int)(pageViewRect.right - rcAnchor.right);
@@ -185,13 +179,13 @@
dwPos = 1;
}
- FX_FLOAT fPopupHeight;
+ float fPopupHeight;
if (t < fMinPopup)
fPopupHeight = fMinPopup;
else if (t > fMaxPopup)
fPopupHeight = fMaxPopup;
else
- fPopupHeight = static_cast<FX_FLOAT>(t);
+ fPopupHeight = static_cast<float>(t);
switch (nRotate) {
case 0:
@@ -232,7 +226,7 @@
if (!pXFAPageView)
return false;
- CPDFXFA_Page* pPage = m_pContext->GetXFAPage(pXFAPageView);
+ RetainPtr<CPDFXFA_Page> pPage = m_pContext->GetXFAPage(pXFAPageView);
if (!pPage)
return false;
@@ -254,7 +248,7 @@
if (hWidget->CanSelectAll())
menuFlag |= FXFA_MENU_SELECTALL;
- return pFormFillEnv->PopupMenu(pPage, hWidget, menuFlag, ptPopup);
+ return pFormFillEnv->PopupMenu(pPage.Get(), hWidget, menuFlag, ptPopup);
}
void CPDFXFA_DocEnvironment::PageViewEvent(CXFA_FFPageView* pPageView,
@@ -278,54 +272,57 @@
for (int iPageIter = 0; iPageIter < m_pContext->GetOriginalPageCount();
iPageIter++) {
- CPDFXFA_Page* pPage = (*m_pContext->GetXFAPageList())[iPageIter];
+ RetainPtr<CPDFXFA_Page> pPage = (*m_pContext->GetXFAPageList())[iPageIter];
if (!pPage)
continue;
- m_pContext->GetFormFillEnv()->RemovePageView(pPage);
+ m_pContext->GetFormFillEnv()->RemovePageView(pPage.Get());
pPage->SetXFAPageView(pXFADocView->GetPageView(iPageIter));
}
int flag = (nNewCount < m_pContext->GetOriginalPageCount())
? FXFA_PAGEVIEWEVENT_POSTREMOVED
: FXFA_PAGEVIEWEVENT_POSTADDED;
- int count = FXSYS_abs(nNewCount - m_pContext->GetOriginalPageCount());
+ int count = abs(nNewCount - m_pContext->GetOriginalPageCount());
m_pContext->SetOriginalPageCount(nNewCount);
pFormFillEnv->PageEvent(count, flag);
}
void CPDFXFA_DocEnvironment::WidgetPostAdd(CXFA_FFWidget* hWidget,
- CXFA_WidgetAcc* pWidgetData) {
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || !hWidget)
+ CXFA_WidgetAcc* pWidgetAcc) {
+ if (m_pContext->GetFormType() != FormType::kXFAFull || !hWidget)
return;
CXFA_FFPageView* pPageView = hWidget->GetPageView();
if (!pPageView)
return;
- CPDFXFA_Page* pXFAPage = m_pContext->GetXFAPage(pPageView);
+ RetainPtr<CPDFXFA_Page> pXFAPage = m_pContext->GetXFAPage(pPageView);
if (!pXFAPage)
return;
- m_pContext->GetFormFillEnv()->GetPageView(pXFAPage, true)->AddAnnot(hWidget);
+ m_pContext->GetFormFillEnv()
+ ->GetPageView(pXFAPage.Get(), true)
+ ->AddAnnot(hWidget);
}
void CPDFXFA_DocEnvironment::WidgetPreRemove(CXFA_FFWidget* hWidget,
- CXFA_WidgetAcc* pWidgetData) {
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || !hWidget)
+ CXFA_WidgetAcc* pWidgetAcc) {
+ if (m_pContext->GetFormType() != FormType::kXFAFull || !hWidget)
return;
CXFA_FFPageView* pPageView = hWidget->GetPageView();
if (!pPageView)
return;
- CPDFXFA_Page* pXFAPage = m_pContext->GetXFAPage(pPageView);
+ RetainPtr<CPDFXFA_Page> pXFAPage = m_pContext->GetXFAPage(pPageView);
if (!pXFAPage)
return;
CPDFSDK_PageView* pSdkPageView =
- m_pContext->GetFormFillEnv()->GetPageView(pXFAPage, true);
- if (CPDFSDK_Annot* pAnnot = pSdkPageView->GetAnnotByXFAWidget(hWidget))
+ m_pContext->GetFormFillEnv()->GetPageView(pXFAPage.Get(), true);
+ CPDFSDK_Annot* pAnnot = pSdkPageView->GetAnnotByXFAWidget(hWidget);
+ if (pAnnot)
pSdkPageView->DeleteAnnot(pAnnot);
}
@@ -338,20 +335,20 @@
int32_t CPDFXFA_DocEnvironment::GetCurrentPage(CXFA_FFDoc* hDoc) {
if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv())
return -1;
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA)
+ if (m_pContext->GetFormType() != FormType::kXFAFull)
return -1;
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return -1;
- return pFormFillEnv->GetCurrentPageIndex(this);
+ return pFormFillEnv->GetCurrentPageIndex(m_pContext.Get());
}
void CPDFXFA_DocEnvironment::SetCurrentPage(CXFA_FFDoc* hDoc,
int32_t iCurPage) {
if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetFormFillEnv() ||
- m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA || iCurPage < 0 ||
+ m_pContext->GetFormType() != FormType::kXFAFull || iCurPage < 0 ||
iCurPage >= m_pContext->GetFormFillEnv()->GetPageCount()) {
return;
}
@@ -359,7 +356,7 @@
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return;
- pFormFillEnv->SetCurrentPage(this, iCurPage);
+ pFormFillEnv->SetCurrentPage(m_pContext.Get(), iCurPage);
}
bool CPDFXFA_DocEnvironment::IsCalculationsEnabled(CXFA_FFDoc* hDoc) {
@@ -382,53 +379,51 @@
}
}
-void CPDFXFA_DocEnvironment::GetTitle(CXFA_FFDoc* hDoc,
- CFX_WideString& wsTitle) {
+void CPDFXFA_DocEnvironment::GetTitle(CXFA_FFDoc* hDoc, WideString& wsTitle) {
if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetPDFDoc())
return;
- CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo();
+ const CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo();
if (!pInfoDict)
return;
- CFX_ByteString csTitle = pInfoDict->GetStringFor("Title");
+ ByteString csTitle = pInfoDict->GetStringFor("Title");
wsTitle = wsTitle.FromLocal(csTitle.GetBuffer(csTitle.GetLength()));
csTitle.ReleaseBuffer(csTitle.GetLength());
}
void CPDFXFA_DocEnvironment::SetTitle(CXFA_FFDoc* hDoc,
- const CFX_WideString& wsTitle) {
+ const WideString& wsTitle) {
if (hDoc != m_pContext->GetXFADoc() || !m_pContext->GetPDFDoc())
return;
- if (CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo())
+ CPDF_Dictionary* pInfoDict = m_pContext->GetPDFDoc()->GetInfo();
+ if (pInfoDict)
pInfoDict->SetNewFor<CPDF_String>("Title", wsTitle);
}
void CPDFXFA_DocEnvironment::ExportData(CXFA_FFDoc* hDoc,
- const CFX_WideString& wsFilePath,
+ const WideString& wsFilePath,
bool bXDP) {
if (hDoc != m_pContext->GetXFADoc())
return;
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
- m_pContext->GetDocType() != DOCTYPE_STATIC_XFA) {
+ if (!m_pContext->ContainsXFAForm())
return;
- }
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return;
int fileType = bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML;
- CFX_ByteString bs = wsFilePath.UTF16LE_Encode();
+ ByteString bs = wsFilePath.UTF16LE_Encode();
if (wsFilePath.IsEmpty()) {
if (!pFormFillEnv->GetFormFillInfo() ||
!pFormFillEnv->GetFormFillInfo()->m_pJsPlatform) {
return;
}
- CFX_WideString filepath = pFormFillEnv->JS_fieldBrowse();
+ WideString filepath = pFormFillEnv->JS_fieldBrowse();
bs = filepath.UTF16LE_Encode();
}
int len = bs.GetLength();
@@ -439,20 +434,20 @@
if (!pFileHandler)
return;
- CFX_RetainPtr<IFX_SeekableStream> fileWrite =
- MakeSeekableStream(pFileHandler);
- CFX_ByteString content;
+ RetainPtr<IFX_SeekableStream> fileWrite = MakeSeekableStream(pFileHandler);
if (fileType == FXFA_SAVEAS_XML) {
- content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
+ ByteString content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
fileWrite->WriteBlock(content.c_str(), fileWrite->GetSize(),
content.GetLength());
- m_pContext->GetXFADocView()->GetDoc()->SavePackage(XFA_HASHCODE_Data,
- fileWrite, nullptr);
+ CXFA_FFDoc* ffdoc = m_pContext->GetXFADocView()->GetDoc();
+ ffdoc->SavePackage(
+ ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Data)), fileWrite,
+ nullptr);
} else if (fileType == FXFA_SAVEAS_XDP) {
if (!m_pContext->GetPDFDoc())
return;
- CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot();
+ const CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot();
if (!pRoot)
return;
@@ -477,28 +472,32 @@
if (!pStream)
continue;
if (pPrePDFObj->GetString() == "form") {
- m_pContext->GetXFADocView()->GetDoc()->SavePackage(XFA_HASHCODE_Form,
- fileWrite, nullptr);
+ CXFA_FFDoc* ffdoc = m_pContext->GetXFADocView()->GetDoc();
+ ffdoc->SavePackage(
+ ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)),
+ fileWrite, nullptr);
continue;
}
if (pPrePDFObj->GetString() == "datasets") {
- m_pContext->GetXFADocView()->GetDoc()->SavePackage(
- XFA_HASHCODE_Datasets, fileWrite, nullptr);
+ CXFA_FFDoc* ffdoc = m_pContext->GetXFADocView()->GetDoc();
+ ffdoc->SavePackage(
+ ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Datasets)),
+ fileWrite, nullptr);
continue;
}
if (i == size - 1) {
- CFX_WideString wPath = CFX_WideString::FromUTF16LE(
+ WideString wPath = WideString::FromUTF16LE(
reinterpret_cast<const unsigned short*>(bs.c_str()),
bs.GetLength() / sizeof(unsigned short));
- CFX_ByteString bPath = wPath.UTF8Encode();
+ ByteString bPath = wPath.UTF8Encode();
const char* szFormat =
"\n<pdf href=\"%s\" xmlns=\"http://ns.adobe.com/xdp/pdf/\"/>";
- content.Format(szFormat, bPath.c_str());
+ ByteString content = ByteString::Format(szFormat, bPath.c_str());
fileWrite->WriteBlock(content.c_str(), fileWrite->GetSize(),
content.GetLength());
}
- std::unique_ptr<CPDF_StreamAcc> pAcc(new CPDF_StreamAcc);
- pAcc->LoadAllData(pStream);
+ auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
+ pAcc->LoadAllDataFiltered();
fileWrite->WriteBlock(pAcc->GetData(), fileWrite->GetSize(),
pAcc->GetSize());
}
@@ -507,19 +506,19 @@
}
void CPDFXFA_DocEnvironment::GotoURL(CXFA_FFDoc* hDoc,
- const CFX_WideString& bsURL) {
+ const WideString& bsURL) {
if (hDoc != m_pContext->GetXFADoc())
return;
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA)
+ if (m_pContext->GetFormType() != FormType::kXFAFull)
return;
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return;
- CFX_WideStringC str(bsURL.c_str());
- pFormFillEnv->GotoURL(this, str);
+ WideStringView str(bsURL.c_str());
+ pFormFillEnv->GotoURL(m_pContext.Get(), str);
}
bool CPDFXFA_DocEnvironment::IsValidationsEnabled(CXFA_FFDoc* hDoc) {
@@ -599,7 +598,7 @@
return 0;
return ArgbEncode(pInterForm->GetHighlightAlpha(),
- pInterForm->GetHighlightColor(FPDF_FORMFIELD_XFA));
+ pInterForm->GetHighlightColor(FormFieldType::kXFA));
}
bool CPDFXFA_DocEnvironment::NotifySubmit(bool bPrevOrPost) {
@@ -611,21 +610,19 @@
}
bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() {
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
- m_pContext->GetDocType() != DOCTYPE_STATIC_XFA) {
- return true;
- }
-
- if (!m_pContext->GetXFADocView())
+ if (!m_pContext->ContainsXFAForm())
return true;
- CXFA_FFWidgetHandler* pWidgetHandler =
- m_pContext->GetXFADocView()->GetWidgetHandler();
+ CXFA_FFDocView* docView = m_pContext->GetXFADocView();
+ if (!docView)
+ return true;
+
+ CXFA_FFWidgetHandler* pWidgetHandler = docView->GetWidgetHandler();
if (!pWidgetHandler)
return true;
- std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator(
- m_pContext->GetXFADocView()->CreateWidgetAccIterator());
+ std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator =
+ docView->CreateWidgetAccIterator();
if (pWidgetAccIterator) {
CXFA_EventParam Param;
Param.m_eType = XFA_EVENT_PreSubmit;
@@ -633,23 +630,21 @@
pWidgetHandler->ProcessEvent(pWidgetAcc, &Param);
}
- pWidgetAccIterator.reset(
- m_pContext->GetXFADocView()->CreateWidgetAccIterator());
+ pWidgetAccIterator = docView->CreateWidgetAccIterator();
if (!pWidgetAccIterator)
return true;
CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext();
pWidgetAcc = pWidgetAccIterator->MoveToNext();
while (pWidgetAcc) {
- int fRet = pWidgetAcc->ProcessValidate(-1);
+ int fRet = pWidgetAcc->GetNode()->ProcessValidate(docView, -1);
if (fRet == XFA_EVENTERROR_Error) {
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return false;
- CFX_WideString ws;
- ws.FromLocal(IDS_XFA_Validate_Input);
- CFX_ByteString bs = ws.UTF16LE_Encode();
+ WideString ws = WideString::FromLocal(IDS_XFA_Validate_Input);
+ ByteString bs = ws.UTF16LE_Encode();
int len = bs.GetLength();
pFormFillEnv->Alert((FPDF_WIDESTRING)bs.GetBuffer(len),
(FPDF_WIDESTRING)L"", 0, 1);
@@ -658,14 +653,13 @@
}
pWidgetAcc = pWidgetAccIterator->MoveToNext();
}
- m_pContext->GetXFADocView()->UpdateDocView();
+ docView->UpdateDocView();
return true;
}
void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() {
- if (m_pContext->GetDocType() != DOCTYPE_DYNAMIC_XFA &&
- m_pContext->GetDocType() != DOCTYPE_STATIC_XFA)
+ if (!m_pContext->ContainsXFAForm())
return;
if (!m_pContext->GetXFADocView())
@@ -676,8 +670,8 @@
if (!pWidgetHandler)
return;
- std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator(
- m_pContext->GetXFADocView()->CreateWidgetAccIterator());
+ std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator =
+ m_pContext->GetXFADocView()->CreateWidgetAccIterator();
if (!pWidgetAccIterator)
return;
@@ -691,24 +685,24 @@
m_pContext->GetXFADocView()->UpdateDocView();
}
-bool CPDFXFA_DocEnvironment::SubmitData(CXFA_FFDoc* hDoc, CXFA_Submit submit) {
+bool CPDFXFA_DocEnvironment::Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) {
if (!NotifySubmit(true) || !m_pContext->GetXFADocView())
return false;
m_pContext->GetXFADocView()->UpdateDocView();
- bool ret = SubmitDataInternal(hDoc, submit);
+ bool ret = SubmitInternal(hDoc, submit);
NotifySubmit(false);
return ret;
}
-CFX_RetainPtr<IFX_SeekableReadStream> CPDFXFA_DocEnvironment::OpenLinkedFile(
+RetainPtr<IFX_SeekableReadStream> CPDFXFA_DocEnvironment::OpenLinkedFile(
CXFA_FFDoc* hDoc,
- const CFX_WideString& wsLink) {
+ const WideString& wsLink) {
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return nullptr;
- CFX_ByteString bs = wsLink.UTF16LE_Encode();
+ ByteString bs = wsLink.UTF16LE_Encode();
int len = bs.GetLength();
FPDF_FILEHANDLER* pFileHandler =
pFormFillEnv->OpenFile(0, (FPDF_WIDESTRING)bs.GetBuffer(len), "rb");
@@ -726,19 +720,20 @@
if (!m_pContext->GetXFADocView())
return false;
- CFX_ByteString content;
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return false;
- CFX_RetainPtr<IFX_SeekableStream> fileStream =
- MakeSeekableStream(pFileHandler);
-
+ CXFA_FFDoc* ffdoc = m_pContext->GetXFADocView()->GetDoc();
+ RetainPtr<IFX_SeekableStream> fileStream = MakeSeekableStream(pFileHandler);
if (fileType == FXFA_SAVEAS_XML) {
- const char kContent[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
+ static constexpr char kContent[] =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n";
fileStream->WriteBlock(kContent, 0, strlen(kContent));
- m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Data, fileStream,
- nullptr);
+
+ ffdoc->SavePackage(
+ ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Data)), fileStream,
+ nullptr);
return true;
}
@@ -754,7 +749,7 @@
return false;
}
- CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot();
+ const CPDF_Dictionary* pRoot = m_pContext->GetPDFDoc()->GetRoot();
if (!pRoot) {
fileStream->Flush();
return false;
@@ -798,34 +793,35 @@
continue;
if (pPrePDFObj->GetString() == "form" && !(flag & FXFA_FORM))
continue;
+
if (pPrePDFObj->GetString() == "form") {
- m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Form, fileStream,
- nullptr);
+ ffdoc->SavePackage(
+ ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)),
+ fileStream, nullptr);
} else if (pPrePDFObj->GetString() == "datasets") {
- m_pContext->GetXFADoc()->SavePackage(XFA_HASHCODE_Datasets, fileStream,
- nullptr);
- } else {
- // PDF,creator.
+ ffdoc->SavePackage(
+ ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Datasets)),
+ fileStream, nullptr);
}
}
return true;
}
-void CPDFXFA_DocEnvironment::ToXFAContentFlags(CFX_WideString csSrcContent,
+void CPDFXFA_DocEnvironment::ToXFAContentFlags(WideString csSrcContent,
FPDF_DWORD& flag) {
- if (csSrcContent.Find(L" config ", 0) != -1)
+ if (csSrcContent.Contains(L" config "))
flag |= FXFA_CONFIG;
- if (csSrcContent.Find(L" template ", 0) != -1)
+ if (csSrcContent.Contains(L" template "))
flag |= FXFA_TEMPLATE;
- if (csSrcContent.Find(L" localeSet ", 0) != -1)
+ if (csSrcContent.Contains(L" localeSet "))
flag |= FXFA_LOCALESET;
- if (csSrcContent.Find(L" datasets ", 0) != -1)
+ if (csSrcContent.Contains(L" datasets "))
flag |= FXFA_DATASETS;
- if (csSrcContent.Find(L" xmpmeta ", 0) != -1)
+ if (csSrcContent.Contains(L" xmpmeta "))
flag |= FXFA_XMPMETA;
- if (csSrcContent.Find(L" xfdf ", 0) != -1)
+ if (csSrcContent.Contains(L" xfdf "))
flag |= FXFA_XFDF;
- if (csSrcContent.Find(L" form ", 0) != -1)
+ if (csSrcContent.Contains(L" form "))
flag |= FXFA_FORM;
if (flag == 0) {
flag = FXFA_CONFIG | FXFA_TEMPLATE | FXFA_LOCALESET | FXFA_DATASETS |
@@ -833,43 +829,40 @@
}
}
-bool CPDFXFA_DocEnvironment::MailToInfo(CFX_WideString& csURL,
- CFX_WideString& csToAddress,
- CFX_WideString& csCCAddress,
- CFX_WideString& csBCCAddress,
- CFX_WideString& csSubject,
- CFX_WideString& csMsg) {
- CFX_WideString srcURL = csURL;
+bool CPDFXFA_DocEnvironment::MailToInfo(WideString& csURL,
+ WideString& csToAddress,
+ WideString& csCCAddress,
+ WideString& csBCCAddress,
+ WideString& csSubject,
+ WideString& csMsg) {
+ WideString srcURL = csURL;
srcURL.TrimLeft();
if (srcURL.Left(7).CompareNoCase(L"mailto:") != 0)
return false;
- int pos = srcURL.Find(L'?', 0);
- CFX_WideString tmp;
- if (pos == -1) {
- pos = srcURL.Find(L'@', 0);
- if (pos == -1)
+ auto pos = srcURL.Find(L'?');
+ WideString tmp;
+ if (!pos.has_value()) {
+ pos = srcURL.Find(L'@');
+ if (!pos.has_value())
return false;
tmp = srcURL.Right(csURL.GetLength() - 7);
} else {
- tmp = srcURL.Left(pos);
+ tmp = srcURL.Left(pos.value());
tmp = tmp.Right(tmp.GetLength() - 7);
}
- tmp.TrimLeft();
- tmp.TrimRight();
+ tmp.Trim();
csToAddress = tmp;
- srcURL = srcURL.Right(srcURL.GetLength() - (pos + 1));
+ srcURL = srcURL.Right(srcURL.GetLength() - (pos.value() + 1));
while (!srcURL.IsEmpty()) {
- srcURL.TrimLeft();
- srcURL.TrimRight();
- pos = srcURL.Find(L'&', 0);
+ srcURL.Trim();
+ pos = srcURL.Find(L'&');
- tmp = (pos == -1) ? srcURL : srcURL.Left(pos);
- tmp.TrimLeft();
- tmp.TrimRight();
+ tmp = (!pos.has_value()) ? srcURL : srcURL.Left(pos.value());
+ tmp.Trim();
if (tmp.GetLength() >= 3 && tmp.Left(3).CompareNoCase(L"cc=") == 0) {
tmp = tmp.Right(tmp.GetLength() - 3);
if (!csCCAddress.IsEmpty())
@@ -890,7 +883,9 @@
tmp = tmp.Right(tmp.GetLength() - 5);
csMsg += tmp;
}
- srcURL = (pos == -1) ? L"" : srcURL.Right(csURL.GetLength() - (pos + 1));
+ srcURL = !pos.has_value()
+ ? L""
+ : srcURL.Right(csURL.GetLength() - (pos.value() + 1));
}
csToAddress.Replace(L",", L";");
csCCAddress.Replace(L",", L";");
@@ -898,41 +893,34 @@
return true;
}
-bool CPDFXFA_DocEnvironment::SubmitDataInternal(CXFA_FFDoc* hDoc,
- CXFA_Submit submit) {
+bool CPDFXFA_DocEnvironment::SubmitInternal(CXFA_FFDoc* hDoc,
+ CXFA_Submit* submit) {
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
if (!pFormFillEnv)
return false;
- CFX_WideStringC csURLC;
- submit.GetSubmitTarget(csURLC);
- CFX_WideString csURL(csURLC);
+ WideString csURL = submit->GetSubmitTarget();
if (csURL.IsEmpty()) {
- CFX_WideString ws;
- ws.FromLocal("Submit cancelled.");
- CFX_ByteString bs = ws.UTF16LE_Encode();
+ WideString ws = WideString::FromLocal("Submit cancelled.");
+ ByteString bs = ws.UTF16LE_Encode();
int len = bs.GetLength();
- pFormFillEnv->Alert((FPDF_WIDESTRING)bs.GetBuffer(len),
- (FPDF_WIDESTRING)L"", 0, 4);
+ pFormFillEnv->Alert(reinterpret_cast<FPDF_WIDESTRING>(bs.GetBuffer(len)),
+ reinterpret_cast<FPDF_WIDESTRING>(L""), 0, 4);
bs.ReleaseBuffer(len);
return false;
}
FPDF_FILEHANDLER* pFileHandler = nullptr;
int fileFlag = -1;
- switch (submit.GetSubmitFormat()) {
- case XFA_ATTRIBUTEENUM_Xdp: {
- CFX_WideStringC csContentC;
- submit.GetSubmitXDPContent(csContentC);
- CFX_WideString csContent;
- csContent = csContentC;
- csContent.TrimLeft();
- csContent.TrimRight();
- CFX_WideString space;
- space.FromLocal(" ");
+ switch (submit->GetSubmitFormat()) {
+ case XFA_AttributeEnum::Xdp: {
+ WideString csContent = submit->GetSubmitXDPContent();
+ csContent.Trim();
+
+ WideString space = WideString::FromLocal(" ");
csContent = space + csContent + space;
FPDF_DWORD flag = 0;
- if (submit.IsSubmitEmbedPDF())
+ if (submit->IsSubmitEmbedPDF())
flag |= FXFA_PDF;
ToXFAContentFlags(csContent, flag);
@@ -941,14 +929,14 @@
ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XDP, 0, flag);
break;
}
- case XFA_ATTRIBUTEENUM_Xml:
+ case XFA_AttributeEnum::Xml:
pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XML, nullptr, "wb");
fileFlag = FXFA_SAVEAS_XML;
ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0, FXFA_XFA_ALL);
break;
- case XFA_ATTRIBUTEENUM_Pdf:
+ case XFA_AttributeEnum::Pdf:
break;
- case XFA_ATTRIBUTEENUM_Urlencoded:
+ case XFA_AttributeEnum::Urlencoded:
pFileHandler = pFormFillEnv->OpenFile(FXFA_SAVEAS_XML, nullptr, "wb");
fileFlag = FXFA_SAVEAS_XML;
ExportSubmitFile(pFileHandler, FXFA_SAVEAS_XML, 0, FXFA_XFA_ALL);
@@ -958,21 +946,22 @@
}
if (!pFileHandler)
return false;
+
if (csURL.Left(7).CompareNoCase(L"mailto:") == 0) {
- CFX_WideString csToAddress;
- CFX_WideString csCCAddress;
- CFX_WideString csBCCAddress;
- CFX_WideString csSubject;
- CFX_WideString csMsg;
+ WideString csToAddress;
+ WideString csCCAddress;
+ WideString csBCCAddress;
+ WideString csSubject;
+ WideString csMsg;
if (!MailToInfo(csURL, csToAddress, csCCAddress, csBCCAddress, csSubject,
csMsg)) {
return false;
}
- CFX_ByteString bsTo = CFX_WideString(csToAddress).UTF16LE_Encode();
- CFX_ByteString bsCC = CFX_WideString(csCCAddress).UTF16LE_Encode();
- CFX_ByteString bsBcc = CFX_WideString(csBCCAddress).UTF16LE_Encode();
- CFX_ByteString bsSubject = CFX_WideString(csSubject).UTF16LE_Encode();
- CFX_ByteString bsMsg = CFX_WideString(csMsg).UTF16LE_Encode();
+ ByteString bsTo = WideString(csToAddress).UTF16LE_Encode();
+ ByteString bsCC = WideString(csCCAddress).UTF16LE_Encode();
+ ByteString bsBcc = WideString(csBCCAddress).UTF16LE_Encode();
+ ByteString bsSubject = WideString(csSubject).UTF16LE_Encode();
+ ByteString bsMsg = WideString(csMsg).UTF16LE_Encode();
FPDF_WIDESTRING pTo = (FPDF_WIDESTRING)bsTo.GetBuffer(bsTo.GetLength());
FPDF_WIDESTRING pCC = (FPDF_WIDESTRING)bsCC.GetBuffer(bsCC.GetLength());
FPDF_WIDESTRING pBcc = (FPDF_WIDESTRING)bsBcc.GetBuffer(bsBcc.GetLength());
@@ -980,15 +969,15 @@
(FPDF_WIDESTRING)bsSubject.GetBuffer(bsSubject.GetLength());
FPDF_WIDESTRING pMsg = (FPDF_WIDESTRING)bsMsg.GetBuffer(bsMsg.GetLength());
pFormFillEnv->EmailTo(pFileHandler, pTo, pSubject, pCC, pBcc, pMsg);
- bsTo.ReleaseBuffer();
- bsCC.ReleaseBuffer();
- bsBcc.ReleaseBuffer();
- bsSubject.ReleaseBuffer();
- bsMsg.ReleaseBuffer();
+ bsTo.ReleaseBuffer(bsTo.GetStringLength());
+ bsCC.ReleaseBuffer(bsCC.GetStringLength());
+ bsBcc.ReleaseBuffer(bsBcc.GetStringLength());
+ bsSubject.ReleaseBuffer(bsSubject.GetStringLength());
+ bsMsg.ReleaseBuffer(bsMsg.GetStringLength());
} else {
// HTTP or FTP
- CFX_WideString ws;
- CFX_ByteString bs = csURL.UTF16LE_Encode();
+ WideString ws;
+ ByteString bs = csURL.UTF16LE_Encode();
int len = bs.GetLength();
pFormFillEnv->UploadTo(pFileHandler, fileFlag,
(FPDF_WIDESTRING)bs.GetBuffer(len));
@@ -997,35 +986,34 @@
return true;
}
-bool CPDFXFA_DocEnvironment::SetGlobalProperty(
- CXFA_FFDoc* hDoc,
- const CFX_ByteStringC& szPropName,
- CFXJSE_Value* pValue) {
- if (hDoc != m_pContext->GetXFADoc())
- return false;
-
- if (m_pContext->GetFormFillEnv() &&
- m_pContext->GetFormFillEnv()->GetJSRuntime()) {
- return m_pContext->GetFormFillEnv()->GetJSRuntime()->SetValueByName(
- szPropName, pValue);
- }
- return false;
-}
-
-bool CPDFXFA_DocEnvironment::GetGlobalProperty(
- CXFA_FFDoc* hDoc,
- const CFX_ByteStringC& szPropName,
- CFXJSE_Value* pValue) {
+bool CPDFXFA_DocEnvironment::SetGlobalProperty(CXFA_FFDoc* hDoc,
+ const ByteStringView& szPropName,
+ CFXJSE_Value* pValue) {
if (hDoc != m_pContext->GetXFADoc())
return false;
if (!m_pContext->GetFormFillEnv() ||
!m_pContext->GetFormFillEnv()->GetJSRuntime()) {
return false;
}
-
CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
- if (!m_pJSEventContext)
- m_pJSEventContext = pFormFillEnv->GetJSRuntime()->NewEventContext();
+ IJS_EventContext* pContext = pFormFillEnv->GetJSRuntime()->NewEventContext();
+ bool bRet = pFormFillEnv->GetJSRuntime()->SetValueByName(szPropName, pValue);
+ pFormFillEnv->GetJSRuntime()->ReleaseEventContext(pContext);
+ return bRet;
+}
- return pFormFillEnv->GetJSRuntime()->GetValueByName(szPropName, pValue);
+bool CPDFXFA_DocEnvironment::GetGlobalProperty(CXFA_FFDoc* hDoc,
+ const ByteStringView& szPropName,
+ CFXJSE_Value* pValue) {
+ if (hDoc != m_pContext->GetXFADoc())
+ return false;
+ if (!m_pContext->GetFormFillEnv() ||
+ !m_pContext->GetFormFillEnv()->GetJSRuntime()) {
+ return false;
+ }
+ CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
+ IJS_EventContext* pContext = pFormFillEnv->GetJSRuntime()->NewEventContext();
+ bool bRet = pFormFillEnv->GetJSRuntime()->GetValueByName(szPropName, pValue);
+ pFormFillEnv->GetJSRuntime()->ReleaseEventContext(pContext);
+ return bRet;
}
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h
index dc18d9a..9eabf8d 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h
@@ -7,7 +7,8 @@
#ifndef FPDFSDK_FPDFXFA_CPDFXFA_DOCENVIRONMENT_H_
#define FPDFSDK_FPDFXFA_CPDFXFA_DOCENVIRONMENT_H_
-#include "core/fxcrt/cfx_retain_ptr.h"
+#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "public/fpdfview.h"
#include "xfa/fxfa/fxfa.h"
@@ -21,18 +22,16 @@
// IXFA_DocEnvironment
void SetChangeMark(CXFA_FFDoc* hDoc) override;
- // used in dynamic xfa, dwFlags refer to XFA_INVALIDATE_XXX macros.
- void InvalidateRect(CXFA_FFPageView* pPageView,
- const CFX_RectF& rt,
- uint32_t dwFlags) override;
- // show or hide caret
+ // Used in dynamic xfa.
+ void InvalidateRect(CXFA_FFPageView* pPageView, const CFX_RectF& rt) override;
+ // Show or hide caret.
void DisplayCaret(CXFA_FFWidget* hWidget,
bool bVisible,
const CFX_RectF* pRtAnchor) override;
// dwPos: (0:bottom 1:top)
bool GetPopupPos(CXFA_FFWidget* hWidget,
- FX_FLOAT fMinPopup,
- FX_FLOAT fMaxPopup,
+ float fMinPopup,
+ float fMaxPopup,
const CFX_RectF& rtAnchor,
CFX_RectF& rtPopup) override;
bool PopupMenu(CXFA_FFWidget* hWidget, CFX_PointF ptPopup) override;
@@ -40,9 +39,9 @@
// dwFlags XFA_PAGEVIEWEVENT_Added, XFA_PAGEVIEWEVENT_Removing
void PageViewEvent(CXFA_FFPageView* pPageView, uint32_t dwFlags) override;
void WidgetPostAdd(CXFA_FFWidget* hWidget,
- CXFA_WidgetAcc* pWidgetData) override;
+ CXFA_WidgetAcc* pWidgetAcc) override;
void WidgetPreRemove(CXFA_FFWidget* hWidget,
- CXFA_WidgetAcc* pWidgetData) override;
+ CXFA_WidgetAcc* pWidgetAcc) override;
// Host method
int32_t CountPages(CXFA_FFDoc* hDoc) override;
@@ -50,12 +49,12 @@
void SetCurrentPage(CXFA_FFDoc* hDoc, int32_t iCurPage) override;
bool IsCalculationsEnabled(CXFA_FFDoc* hDoc) override;
void SetCalculationsEnabled(CXFA_FFDoc* hDoc, bool bEnabled) override;
- void GetTitle(CXFA_FFDoc* hDoc, CFX_WideString& wsTitle) override;
- void SetTitle(CXFA_FFDoc* hDoc, const CFX_WideString& wsTitle) override;
+ void GetTitle(CXFA_FFDoc* hDoc, WideString& wsTitle) override;
+ void SetTitle(CXFA_FFDoc* hDoc, const WideString& wsTitle) override;
void ExportData(CXFA_FFDoc* hDoc,
- const CFX_WideString& wsFilePath,
+ const WideString& wsFilePath,
bool bXDP) override;
- void GotoURL(CXFA_FFDoc* hDoc, const CFX_WideString& bsURL) override;
+ void GotoURL(CXFA_FFDoc* hDoc, const WideString& bsURL) override;
bool IsValidationsEnabled(CXFA_FFDoc* hDoc) override;
void SetValidationsEnabled(CXFA_FFDoc* hDoc, bool bEnabled) override;
void SetFocusWidget(CXFA_FFDoc* hDoc, CXFA_FFWidget* hWidget) override;
@@ -65,50 +64,37 @@
uint32_t dwOptions) override;
FX_ARGB GetHighlightColor(CXFA_FFDoc* hDoc) override;
- /**
- *Submit data to email, http, ftp.
- * @param[in] hDoc The document handler.
- * @param[in] eFormat Determines the format in which the data will be
- *submitted. XFA_ATTRIBUTEENUM_Xdp, XFA_ATTRIBUTEENUM_Xml...
- * @param[in] wsTarget The URL to which the data will be submitted.
- * @param[in] eEncoding The encoding of text content.
- * @param[in] pXDPContent Controls what subset of the data is submitted, used
- *only when the format property is xdp.
- * @param[in] bEmbedPDF, specifies whether PDF is embedded in the submitted
- *content or not.
- */
- bool SubmitData(CXFA_FFDoc* hDoc, CXFA_Submit submit) override;
+ bool Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) override;
bool GetGlobalProperty(CXFA_FFDoc* hDoc,
- const CFX_ByteStringC& szPropName,
+ const ByteStringView& szPropName,
CFXJSE_Value* pValue) override;
bool SetGlobalProperty(CXFA_FFDoc* hDoc,
- const CFX_ByteStringC& szPropName,
+ const ByteStringView& szPropName,
CFXJSE_Value* pValue) override;
- CFX_RetainPtr<IFX_SeekableReadStream> OpenLinkedFile(
+ RetainPtr<IFX_SeekableReadStream> OpenLinkedFile(
CXFA_FFDoc* hDoc,
- const CFX_WideString& wsLink) override;
+ const WideString& wsLink) override;
private:
bool OnBeforeNotifySubmit();
void OnAfterNotifySubmit();
bool NotifySubmit(bool bPrevOrPost);
- bool SubmitDataInternal(CXFA_FFDoc* hDoc, CXFA_Submit submit);
- bool MailToInfo(CFX_WideString& csURL,
- CFX_WideString& csToAddress,
- CFX_WideString& csCCAddress,
- CFX_WideString& csBCCAddress,
- CFX_WideString& csSubject,
- CFX_WideString& csMsg);
+ bool SubmitInternal(CXFA_FFDoc* hDoc, CXFA_Submit* submit);
+ bool MailToInfo(WideString& csURL,
+ WideString& csToAddress,
+ WideString& csCCAddress,
+ WideString& csBCCAddress,
+ WideString& csSubject,
+ WideString& csMsg);
bool ExportSubmitFile(FPDF_FILEHANDLER* ppFileHandler,
int fileType,
FPDF_DWORD encodeType,
FPDF_DWORD flag);
- void ToXFAContentFlags(CFX_WideString csSrcContent, FPDF_DWORD& flag);
+ void ToXFAContentFlags(WideString csSrcContent, FPDF_DWORD& flag);
- CPDFXFA_Context* const m_pContext; // Not owned.
- IJS_EventContext* m_pJSEventContext; // Not owned.
+ UnownedPtr<CPDFXFA_Context> const m_pContext;
};
#endif // FPDFSDK_FPDFXFA_CPDFXFA_DOCENVIRONMENT_H_
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
index 8b5bb3d..fbea90d 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
@@ -13,19 +13,13 @@
#include "fpdfsdk/fsdk_define.h"
#include "public/fpdf_formfill.h"
#include "third_party/base/ptr_util.h"
-#include "xfa/fxfa/xfa_ffdocview.h"
-#include "xfa/fxfa/xfa_ffpageview.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
+#include "xfa/fxfa/cxfa_ffpageview.h"
CPDFXFA_Page::CPDFXFA_Page(CPDFXFA_Context* pContext, int page_index)
- : m_pXFAPageView(nullptr),
- m_pContext(pContext),
- m_iPageIndex(page_index),
- m_iRef(1) {}
+ : m_pXFAPageView(nullptr), m_pContext(pContext), m_iPageIndex(page_index) {}
-CPDFXFA_Page::~CPDFXFA_Page() {
- if (m_pContext)
- m_pContext->RemovePage(this);
-}
+CPDFXFA_Page::~CPDFXFA_Page() {}
bool CPDFXFA_Page::LoadPDFPage() {
if (!m_pContext)
@@ -70,18 +64,15 @@
if (!m_pContext || m_iPageIndex < 0)
return false;
- int iDocType = m_pContext->GetDocType();
- switch (iDocType) {
- case DOCTYPE_PDF:
- case DOCTYPE_STATIC_XFA: {
+ switch (m_pContext->GetFormType()) {
+ case FormType::kNone:
+ case FormType::kAcroForm:
+ case FormType::kXFAForeground:
return LoadPDFPage();
- }
- case DOCTYPE_DYNAMIC_XFA: {
+ case FormType::kXFAFull:
return LoadXFAPageView();
- }
- default:
- return false;
}
+ return false;
}
bool CPDFXFA_Page::LoadPDFPage(CPDF_Dictionary* pageDict) {
@@ -94,49 +85,37 @@
return true;
}
-FX_FLOAT CPDFXFA_Page::GetPageWidth() const {
+float CPDFXFA_Page::GetPageWidth() const {
if (!m_pPDFPage && !m_pXFAPageView)
return 0.0f;
- int nDocType = m_pContext->GetDocType();
- switch (nDocType) {
- case DOCTYPE_DYNAMIC_XFA: {
- if (m_pXFAPageView)
- return m_pXFAPageView->GetPageViewRect().width;
- break;
- }
- case DOCTYPE_STATIC_XFA:
- case DOCTYPE_PDF: {
+ switch (m_pContext->GetFormType()) {
+ case FormType::kNone:
+ case FormType::kAcroForm:
+ case FormType::kXFAForeground:
if (m_pPDFPage)
return m_pPDFPage->GetPageWidth();
- break;
- }
- default:
- return 0.0f;
+ case FormType::kXFAFull:
+ if (m_pXFAPageView)
+ return m_pXFAPageView->GetPageViewRect().width;
}
return 0.0f;
}
-FX_FLOAT CPDFXFA_Page::GetPageHeight() const {
+float CPDFXFA_Page::GetPageHeight() const {
if (!m_pPDFPage && !m_pXFAPageView)
return 0.0f;
- int nDocType = m_pContext->GetDocType();
- switch (nDocType) {
- case DOCTYPE_PDF:
- case DOCTYPE_STATIC_XFA: {
+ switch (m_pContext->GetFormType()) {
+ case FormType::kNone:
+ case FormType::kAcroForm:
+ case FormType::kXFAForeground:
if (m_pPDFPage)
return m_pPDFPage->GetPageHeight();
- break;
- }
- case DOCTYPE_DYNAMIC_XFA: {
+ case FormType::kXFAFull:
if (m_pXFAPageView)
return m_pXFAPageView->GetPageViewRect().height;
- break;
- }
- default:
- return 0.0f;
}
return 0.0f;
@@ -154,12 +133,10 @@
if (!m_pPDFPage && !m_pXFAPageView)
return;
- CFX_Matrix device2page;
- device2page.SetReverse(
- GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate));
-
- CFX_PointF pos = device2page.Transform(CFX_PointF(
- static_cast<FX_FLOAT>(device_x), static_cast<FX_FLOAT>(device_y)));
+ CFX_PointF pos = GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate)
+ .GetInverse()
+ .Transform(CFX_PointF(static_cast<float>(device_x),
+ static_cast<float>(device_y)));
*page_x = pos.x;
*page_y = pos.y;
@@ -181,7 +158,7 @@
GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
CFX_PointF pos = page2device.Transform(
- CFX_PointF(static_cast<FX_FLOAT>(page_x), static_cast<FX_FLOAT>(page_y)));
+ CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)));
*device_x = FXSYS_round(pos.x);
*device_y = FXSYS_round(pos.y);
@@ -195,23 +172,17 @@
if (!m_pPDFPage && !m_pXFAPageView)
return CFX_Matrix();
- int nDocType = m_pContext->GetDocType();
- switch (nDocType) {
- case DOCTYPE_DYNAMIC_XFA: {
- if (m_pXFAPageView) {
- return m_pXFAPageView->GetDisplayMatrix(
- CFX_Rect(xPos, yPos, xSize, ySize), iRotate);
- }
- break;
- }
- case DOCTYPE_PDF:
- case DOCTYPE_STATIC_XFA: {
+ switch (m_pContext->GetFormType()) {
+ case FormType::kNone:
+ case FormType::kAcroForm:
+ case FormType::kXFAForeground:
if (m_pPDFPage)
return m_pPDFPage->GetDisplayMatrix(xPos, yPos, xSize, ySize, iRotate);
- break;
- }
- default:
- return CFX_Matrix();
+ case FormType::kXFAFull:
+ if (m_pXFAPageView)
+ return m_pXFAPageView->GetDisplayMatrix(
+ CFX_Rect(xPos, yPos, xSize, ySize), iRotate);
}
+
return CFX_Matrix();
}
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_page.h b/fpdfsdk/fpdfxfa/cpdfxfa_page.h
index 993885d..f64d66b 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_page.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_page.h
@@ -10,6 +10,8 @@
#include <memory>
#include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/retain_ptr.h"
+#include "core/fxcrt/unowned_ptr.h"
class CFX_Matrix;
class CPDFXFA_Context;
@@ -17,19 +19,14 @@
class CPDF_Page;
class CXFA_FFPageView;
-class CPDFXFA_Page {
+class CPDFXFA_Page : public Retainable {
public:
- CPDFXFA_Page(CPDFXFA_Context* pContext, int page_index);
-
- void Retain() { m_iRef++; }
- void Release() {
- if (--m_iRef <= 0)
- delete this;
- }
+ template <typename T, typename... Args>
+ friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
bool LoadPage();
bool LoadPDFPage(CPDF_Dictionary* pageDict);
- CPDFXFA_Context* GetContext() const { return m_pContext; }
+ CPDFXFA_Context* GetContext() const { return m_pContext.Get(); }
int GetPageIndex() const { return m_iPageIndex; }
CPDF_Page* GetPDFPage() const { return m_pPDFPage.get(); }
CXFA_FFPageView* GetXFAPageView() const { return m_pXFAPageView; }
@@ -38,8 +35,8 @@
m_pXFAPageView = pPageView;
}
- FX_FLOAT GetPageWidth() const;
- FX_FLOAT GetPageHeight() const;
+ float GetPageWidth() const;
+ float GetPageHeight() const;
void DeviceToPage(int start_x,
int start_y,
@@ -68,7 +65,8 @@
protected:
// Refcounted class.
- ~CPDFXFA_Page();
+ CPDFXFA_Page(CPDFXFA_Context* pContext, int page_index);
+ ~CPDFXFA_Page() override;
bool LoadPDFPage();
bool LoadXFAPageView();
@@ -76,9 +74,8 @@
private:
std::unique_ptr<CPDF_Page> m_pPDFPage;
CXFA_FFPageView* m_pXFAPageView;
- CPDFXFA_Context* const m_pContext;
+ UnownedPtr<CPDFXFA_Context> const m_pContext;
const int m_iPageIndex;
- int m_iRef;
};
#endif // FPDFSDK_FPDFXFA_CPDFXFA_PAGE_H_
diff --git a/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.cpp b/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.cpp
index 39aa72b..c7201c3 100644
--- a/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.cpp
+++ b/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.cpp
@@ -29,6 +29,12 @@
std::vector<CFWL_TimerInfo*>* CXFA_FWLAdapterTimerMgr::s_TimerArray = nullptr;
+CXFA_FWLAdapterTimerMgr::CXFA_FWLAdapterTimerMgr(
+ CPDFSDK_FormFillEnvironment* pFormFillEnv)
+ : m_pFormFillEnv(pFormFillEnv) {}
+
+CXFA_FWLAdapterTimerMgr::~CXFA_FWLAdapterTimerMgr() {}
+
void CXFA_FWLAdapterTimerMgr::Start(CFWL_Timer* pTimer,
uint32_t dwElapse,
bool bImmediately,
@@ -66,7 +72,7 @@
if (!s_TimerArray)
return;
- for (const auto info : *s_TimerArray) {
+ for (auto* info : *s_TimerArray) {
CFWL_FWLAdapterTimerInfo* pInfo =
static_cast<CFWL_FWLAdapterTimerInfo*>(info);
if (pInfo->idEvent == idEvent) {
diff --git a/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h b/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h
index fdb5635..d763f02 100644
--- a/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h
+++ b/fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h
@@ -10,14 +10,15 @@
#include <memory>
#include <vector>
+#include "core/fxcrt/unowned_ptr.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "xfa/fwl/cfwl_timerinfo.h"
#include "xfa/fwl/ifwl_adaptertimermgr.h"
class CXFA_FWLAdapterTimerMgr : public IFWL_AdapterTimerMgr {
public:
- explicit CXFA_FWLAdapterTimerMgr(CPDFSDK_FormFillEnvironment* pFormFillEnv)
- : m_pFormFillEnv(pFormFillEnv) {}
+ explicit CXFA_FWLAdapterTimerMgr(CPDFSDK_FormFillEnvironment* pFormFillEnv);
+ ~CXFA_FWLAdapterTimerMgr();
void Start(CFWL_Timer* pTimer,
uint32_t dwElapse,
@@ -29,7 +30,7 @@
static void TimerProc(int32_t idEvent);
static std::vector<CFWL_TimerInfo*>* s_TimerArray;
- CPDFSDK_FormFillEnvironment* const m_pFormFillEnv;
+ UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
};
#endif // FPDFSDK_FPDFXFA_CXFA_FWLADAPTERTIMERMGR_H_
diff --git a/fpdfsdk/fsdk_actionhandler.cpp b/fpdfsdk/fsdk_actionhandler.cpp
index dc99f32..de5c931 100644
--- a/fpdfsdk/fsdk_actionhandler.cpp
+++ b/fpdfsdk/fsdk_actionhandler.cpp
@@ -7,6 +7,7 @@
#include "fpdfsdk/fsdk_actionhandler.h"
#include <set>
+#include <vector>
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfdoc/cpdf_formfield.h"
@@ -14,8 +15,9 @@
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_interform.h"
#include "fpdfsdk/fsdk_define.h"
-#include "fpdfsdk/javascript/ijs_event_context.h"
-#include "fpdfsdk/javascript/ijs_runtime.h"
+#include "fxjs/ijs_event_context.h"
+#include "fxjs/ijs_runtime.h"
+#include "third_party/base/logging.h"
#include "third_party/base/stl_util.h"
bool CPDFSDK_ActionHandler::DoAction_DocOpen(
@@ -27,10 +29,10 @@
bool CPDFSDK_ActionHandler::DoAction_JavaScript(
const CPDF_Action& JsAction,
- CFX_WideString csJSName,
+ WideString csJSName,
CPDFSDK_FormFillEnvironment* pFormFillEnv) {
if (JsAction.GetType() == CPDF_Action::JavaScript) {
- CFX_WideString swJS = JsAction.GetJavaScript();
+ WideString swJS = JsAction.GetJavaScript();
if (!swJS.IsEmpty()) {
RunDocumentOpenJavaScript(pFormFillEnv, csJSName, swJS);
return true;
@@ -49,7 +51,7 @@
ASSERT(pFormFillEnv);
if (pFormFillEnv->IsJSInitiated() &&
JsAction.GetType() == CPDF_Action::JavaScript) {
- CFX_WideString swJS = JsAction.GetJavaScript();
+ WideString swJS = JsAction.GetJavaScript();
if (!swJS.IsEmpty()) {
RunFieldJavaScript(pFormFillEnv, pFormField, type, data, swJS);
return true;
@@ -123,7 +125,7 @@
ASSERT(pFormFillEnv);
if (action.GetType() == CPDF_Action::JavaScript) {
if (pFormFillEnv->IsJSInitiated()) {
- CFX_WideString swJS = action.GetJavaScript();
+ WideString swJS = action.GetJavaScript();
if (!swJS.IsEmpty()) {
RunDocumentOpenJavaScript(pFormFillEnv, L"", swJS);
}
@@ -154,13 +156,13 @@
ASSERT(pFormFillEnv);
if (action.GetType() == CPDF_Action::JavaScript) {
if (pFormFillEnv->IsJSInitiated()) {
- CFX_WideString swJS = action.GetJavaScript();
+ WideString swJS = action.GetJavaScript();
if (!swJS.IsEmpty()) {
IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
IJS_EventContext* pContext = pRuntime->NewEventContext();
pContext->OnLink_MouseUp(pFormFillEnv);
- CFX_WideString csInfo;
+ WideString csInfo;
bool bRet = pContext->RunScript(swJS, &csInfo);
pRuntime->ReleaseEventContext(pContext);
if (!bRet) {
@@ -195,7 +197,7 @@
ASSERT(pFormFillEnv);
if (action.GetType() == CPDF_Action::JavaScript) {
if (pFormFillEnv->IsJSInitiated()) {
- CFX_WideString swJS = action.GetJavaScript();
+ WideString swJS = action.GetJavaScript();
if (!swJS.IsEmpty()) {
RunDocumentPageJavaScript(pFormFillEnv, type, swJS);
}
@@ -242,7 +244,7 @@
ASSERT(pFormFillEnv);
if (action.GetType() == CPDF_Action::JavaScript) {
if (pFormFillEnv->IsJSInitiated()) {
- CFX_WideString swJS = action.GetJavaScript();
+ WideString swJS = action.GetJavaScript();
if (!swJS.IsEmpty()) {
RunFieldJavaScript(pFormFillEnv, pFormField, type, data, swJS);
if (!IsValidField(pFormFillEnv, pFormField->GetFieldDict()))
@@ -278,11 +280,11 @@
ASSERT(pFormFillEnv);
if (action.GetType() == CPDF_Action::JavaScript) {
if (pFormFillEnv->IsJSInitiated()) {
- CFX_WideString swJS = action.GetJavaScript();
+ WideString swJS = action.GetJavaScript();
if (!swJS.IsEmpty()) {
IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
IJS_EventContext* pContext = pRuntime->NewEventContext();
- CFX_WideString csInfo;
+ WideString csInfo;
bool bRet = pContext->RunScript(swJS, &csInfo);
pRuntime->ReleaseEventContext(pContext);
if (!bRet) {
@@ -317,13 +319,13 @@
ASSERT(pFormFillEnv);
if (action.GetType() == CPDF_Action::JavaScript) {
if (pFormFillEnv->IsJSInitiated()) {
- CFX_WideString swJS = action.GetJavaScript();
+ WideString swJS = action.GetJavaScript();
if (!swJS.IsEmpty()) {
IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
IJS_EventContext* pContext = pRuntime->NewEventContext();
pContext->OnBookmark_MouseUp(pBookmark);
- CFX_WideString csInfo;
+ WideString csInfo;
bool bRet = pContext->RunScript(swJS, &csInfo);
pRuntime->ReleaseEventContext(pContext);
if (!bRet) {
@@ -386,7 +388,7 @@
DoAction_ImportData(action, pFormFillEnv);
break;
case CPDF_Action::JavaScript:
- ASSERT(false);
+ NOTREACHED();
break;
case CPDF_Action::SetOCGState:
DoAction_SetOCGState(pFormFillEnv, action);
@@ -420,19 +422,13 @@
int nPageIndex = MyDest.GetPageIndex(pPDFDocument);
int nFitType = MyDest.GetZoomMode();
const CPDF_Array* pMyArray = ToArray(MyDest.GetObject());
- float* pPosAry = nullptr;
- int sizeOfAry = 0;
+ std::vector<float> posArray;
if (pMyArray) {
- pPosAry = new float[pMyArray->GetCount()];
- int j = 0;
- for (size_t i = 2; i < pMyArray->GetCount(); i++) {
- pPosAry[j++] = pMyArray->GetFloatAt(i);
- }
- sizeOfAry = j;
+ for (size_t i = 2; i < pMyArray->GetCount(); i++)
+ posArray.push_back(pMyArray->GetFloatAt(i));
}
-
- pFormFillEnv->DoGoToAction(nPageIndex, nFitType, pPosAry, sizeOfAry);
- delete[] pPosAry;
+ pFormFillEnv->DoGoToAction(nPageIndex, nFitType, posArray.data(),
+ posArray.size());
}
void CPDFSDK_ActionHandler::DoAction_GoToR(
@@ -448,7 +444,7 @@
const CPDF_Action& action) {
ASSERT(action.GetDict());
- CFX_ByteString sURI = action.GetURI(pFormFillEnv->GetPDFDocument());
+ ByteString sURI = action.GetURI(pFormFillEnv->GetPDFDocument());
pFormFillEnv->DoURIAction(sURI.c_str());
}
@@ -457,7 +453,7 @@
const CPDF_Action& action) {
ASSERT(action.GetDict());
- CFX_ByteString csName = action.GetNamedAction();
+ ByteString csName = action.GetNamedAction();
pFormFillEnv->ExecuteNamedAction(csName.c_str());
}
@@ -470,7 +466,7 @@
CPDF_FormField* pFormField,
CPDF_AAction::AActionType type,
PDFSDK_FieldAction& data,
- const CFX_WideString& script) {
+ const WideString& script) {
ASSERT(type != CPDF_AAction::Calculate);
ASSERT(type != CPDF_AAction::Format);
@@ -509,11 +505,11 @@
data.sValue, data.bRC);
break;
default:
- ASSERT(false);
+ NOTREACHED();
break;
}
- CFX_WideString csInfo;
+ WideString csInfo;
bool bRet = pContext->RunScript(script, &csInfo);
pRuntime->ReleaseEventContext(pContext);
if (!bRet) {
@@ -523,13 +519,13 @@
void CPDFSDK_ActionHandler::RunDocumentOpenJavaScript(
CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& sScriptName,
- const CFX_WideString& script) {
+ const WideString& sScriptName,
+ const WideString& script) {
IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
IJS_EventContext* pContext = pRuntime->NewEventContext();
pContext->OnDoc_Open(pFormFillEnv, sScriptName);
- CFX_WideString csInfo;
+ WideString csInfo;
bool bRet = pContext->RunScript(script, &csInfo);
pRuntime->ReleaseEventContext(pContext);
if (!bRet) {
@@ -540,7 +536,7 @@
void CPDFSDK_ActionHandler::RunDocumentPageJavaScript(
CPDFSDK_FormFillEnvironment* pFormFillEnv,
CPDF_AAction::AActionType type,
- const CFX_WideString& script) {
+ const WideString& script) {
IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
IJS_EventContext* pContext = pRuntime->NewEventContext();
switch (type) {
@@ -572,11 +568,11 @@
pContext->OnPage_OutView(pFormFillEnv);
break;
default:
- ASSERT(false);
+ NOTREACHED();
break;
}
- CFX_WideString csInfo;
+ WideString csInfo;
bool bRet = pContext->RunScript(script, &csInfo);
pRuntime->ReleaseEventContext(pContext);
if (!bRet) {
diff --git a/fpdfsdk/fsdk_actionhandler.h b/fpdfsdk/fsdk_actionhandler.h
index 1c8dede..7457b4e 100644
--- a/fpdfsdk/fsdk_actionhandler.h
+++ b/fpdfsdk/fsdk_actionhandler.h
@@ -26,7 +26,7 @@
bool DoAction_DocOpen(const CPDF_Action& action,
CPDFSDK_FormFillEnvironment* pFormFillEnv);
bool DoAction_JavaScript(const CPDF_Action& JsAction,
- CFX_WideString csJSName,
+ WideString csJSName,
CPDFSDK_FormFillEnvironment* pFormFillEnv);
bool DoAction_Page(const CPDF_Action& action,
enum CPDF_AAction::AActionType eType,
@@ -86,15 +86,15 @@
CPDFSDK_FormFillEnvironment* pFormFillEnv);
void RunDocumentPageJavaScript(CPDFSDK_FormFillEnvironment* pFormFillEnv,
CPDF_AAction::AActionType type,
- const CFX_WideString& script);
+ const WideString& script);
void RunDocumentOpenJavaScript(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& sScriptName,
- const CFX_WideString& script);
+ const WideString& sScriptName,
+ const WideString& script);
void RunFieldJavaScript(CPDFSDK_FormFillEnvironment* pFormFillEnv,
CPDF_FormField* pFormField,
CPDF_AAction::AActionType type,
PDFSDK_FieldAction& data,
- const CFX_WideString& script);
+ const WideString& script);
bool IsValidField(CPDFSDK_FormFillEnvironment* pFormFillEnv,
CPDF_Dictionary* pFieldDict);
diff --git a/fpdfsdk/fsdk_common.h b/fpdfsdk/fsdk_common.h
index d803026..78ecd98 100644
--- a/fpdfsdk/fsdk_common.h
+++ b/fpdfsdk/fsdk_common.h
@@ -10,7 +10,6 @@
// for all fields
#define FIELDFLAG_READONLY 1
#define FIELDFLAG_REQUIRED 2
-#define FIELDFLAG_NOEXPORT 4
// for text fields
#define FIELDFLAG_MULTILINE (1 << 12)
#define FIELDFLAG_PASSWORD (1 << 13)
@@ -20,14 +19,9 @@
#define FIELDFLAG_COMB (1 << 24)
#define FIELDFLAG_RICHTEXT (1 << 25)
// for button fileds
-#define FIELDFLAG_NOTOGGLETOOFF (1 << 14)
-#define FIELDFLAG_RADIO (1 << 15)
-#define FIELDFLAG_PUSHBUTTON (1 << 16)
#define FIELDFLAG_RADIOSINUNISON (1 << 27)
// for choice fields
-#define FIELDFLAG_COMBO (1 << 17)
#define FIELDFLAG_EDIT (1 << 18)
-#define FIELDFLAG_SORT (1 << 19)
#define FIELDFLAG_MULTISELECT (1 << 21)
#define FIELDFLAG_COMMITONSELCHANGE (1 << 26)
diff --git a/fpdfsdk/fsdk_define.h b/fpdfsdk/fsdk_define.h
index 9a11596..77c2315 100644
--- a/fpdfsdk/fsdk_define.h
+++ b/fpdfsdk/fsdk_define.h
@@ -8,6 +8,7 @@
#define FPDFSDK_FSDK_DEFINE_H_
#include "core/fpdfapi/parser/cpdf_parser.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/fx_dib.h"
#include "public/fpdfview.h"
@@ -22,18 +23,22 @@
class CPDF_Annot;
class CPDF_Page;
+class CPDF_PageObject;
class CPDF_PageRenderContext;
+class CPDF_PathObject;
+class CPDF_Stream;
class IFSDK_PAUSE_Adapter;
+class FX_PATHPOINT;
// Layering prevents fxcrt from knowing about FPDF_FILEACCESS, so this can't
// be a static method of IFX_SeekableReadStream.
-CFX_RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
+RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
FPDF_FILEACCESS* pFileAccess);
#ifdef PDF_ENABLE_XFA
// Layering prevents fxcrt from knowing about FPDF_FILEHANDLER, so this can't
// be a static method of IFX_SeekableStream.
-CFX_RetainPtr<IFX_SeekableStream> MakeSeekableStream(
+RetainPtr<IFX_SeekableStream> MakeSeekableStream(
FPDF_FILEHANDLER* pFileHandler);
#endif // PDF_ENABLE_XFA
@@ -60,8 +65,29 @@
CPDF_Page* CPDFPageFromFPDFPage(FPDF_PAGE page);
+CPDF_PathObject* CPDFPathObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object);
+
+CPDF_PageObject* CPDFPageObjectFromFPDFPageObject(FPDF_PAGEOBJECT page_object);
+
+CPDF_Object* CPDFObjectFromFPDFAttachment(FPDF_ATTACHMENT attachment);
+
+ByteString CFXByteStringFromFPDFWideString(FPDF_WIDESTRING wide_string);
+
CFX_DIBitmap* CFXBitmapFromFPDFBitmap(FPDF_BITMAP bitmap);
+CFX_FloatRect CFXFloatRectFromFSRECTF(const FS_RECTF& rect);
+void FSRECTFFromCFXFloatRect(const CFX_FloatRect& rect, FS_RECTF* out_rect);
+
+const FX_PATHPOINT* FXPathPointFromFPDFPathSegment(FPDF_PATHSEGMENT segment);
+
+unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString& text,
+ void* buffer,
+ unsigned long buflen);
+
+unsigned long DecodeStreamMaybeCopyAndReturnLength(const CPDF_Stream* stream,
+ void* buffer,
+ unsigned long buflen);
+
void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable);
FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy);
void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext,
@@ -78,5 +104,10 @@
void CheckUnSupportError(CPDF_Document* pDoc, uint32_t err_code);
void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot);
void ProcessParseError(CPDF_Parser::Error err);
+FPDF_BOOL FPDFPageObj_SetFillColor(FPDF_PAGEOBJECT page_object,
+ unsigned int R,
+ unsigned int G,
+ unsigned int B,
+ unsigned int A);
#endif // FPDFSDK_FSDK_DEFINE_H_
diff --git a/fpdfsdk/fsdk_filewriteadapter.cpp b/fpdfsdk/fsdk_filewriteadapter.cpp
new file mode 100644
index 0000000..fad058f
--- /dev/null
+++ b/fpdfsdk/fsdk_filewriteadapter.cpp
@@ -0,0 +1,22 @@
+// 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/fsdk_filewriteadapter.h"
+
+FSDK_FileWriteAdapter::FSDK_FileWriteAdapter(FPDF_FILEWRITE* fileWriteStruct)
+ : fileWriteStruct_(fileWriteStruct) {
+ ASSERT(fileWriteStruct_);
+}
+
+FSDK_FileWriteAdapter::~FSDK_FileWriteAdapter() {}
+
+bool FSDK_FileWriteAdapter::WriteBlock(const void* data, size_t size) {
+ return fileWriteStruct_->WriteBlock(fileWriteStruct_, data, size) != 0;
+}
+
+bool FSDK_FileWriteAdapter::WriteString(const ByteStringView& str) {
+ return WriteBlock(str.unterminated_c_str(), str.GetLength());
+}
diff --git a/fpdfsdk/fsdk_filewriteadapter.h b/fpdfsdk/fsdk_filewriteadapter.h
new file mode 100644
index 0000000..6bba1da
--- /dev/null
+++ b/fpdfsdk/fsdk_filewriteadapter.h
@@ -0,0 +1,29 @@
+// 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_FSDK_FILEWRITEADAPTER_H_
+#define FPDFSDK_FSDK_FILEWRITEADAPTER_H_
+
+#include "core/fxcrt/fx_stream.h"
+#include "core/fxcrt/retain_ptr.h"
+#include "public/fpdf_save.h"
+
+class FSDK_FileWriteAdapter : public IFX_WriteStream {
+ public:
+ template <typename T, typename... Args>
+ friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
+
+ bool WriteBlock(const void* data, size_t size) override;
+ bool WriteString(const ByteStringView& str) override;
+
+ private:
+ explicit FSDK_FileWriteAdapter(FPDF_FILEWRITE* fileWriteStruct);
+ ~FSDK_FileWriteAdapter() override;
+
+ FPDF_FILEWRITE* fileWriteStruct_;
+};
+
+#endif // FPDFSDK_FSDK_FILEWRITEADAPTER_H_
diff --git a/fpdfsdk/fsdk_pauseadapter.cpp b/fpdfsdk/fsdk_pauseadapter.cpp
index 237266b..cf99253 100644
--- a/fpdfsdk/fsdk_pauseadapter.cpp
+++ b/fpdfsdk/fsdk_pauseadapter.cpp
@@ -12,5 +12,5 @@
IFSDK_PAUSE_Adapter::~IFSDK_PAUSE_Adapter() {}
bool IFSDK_PAUSE_Adapter::NeedToPauseNow() {
- return m_IPause->NeedToPauseNow && m_IPause->NeedToPauseNow(m_IPause);
+ return m_IPause->NeedToPauseNow && m_IPause->NeedToPauseNow(m_IPause.Get());
}
diff --git a/fpdfsdk/fsdk_pauseadapter.h b/fpdfsdk/fsdk_pauseadapter.h
index bd302f2..a0d0098 100644
--- a/fpdfsdk/fsdk_pauseadapter.h
+++ b/fpdfsdk/fsdk_pauseadapter.h
@@ -7,11 +7,12 @@
#ifndef FPDFSDK_FSDK_PAUSEADAPTER_H_
#define FPDFSDK_FSDK_PAUSEADAPTER_H_
-#include "core/fxcrt/fx_basic.h"
#include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/ifx_pauseindicator.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "public/fpdf_progressive.h"
-class IFSDK_PAUSE_Adapter : public IFX_Pause {
+class IFSDK_PAUSE_Adapter : public IFX_PauseIndicator {
public:
explicit IFSDK_PAUSE_Adapter(IFSDK_PAUSE* IPause);
~IFSDK_PAUSE_Adapter() override;
@@ -19,7 +20,7 @@
bool NeedToPauseNow() override;
private:
- IFSDK_PAUSE* const m_IPause;
+ UnownedPtr<IFSDK_PAUSE> const m_IPause;
};
#endif // FPDFSDK_FSDK_PAUSEADAPTER_H_
diff --git a/fpdfsdk/fxedit/fx_edit.h b/fpdfsdk/fxedit/fx_edit.h
deleted file mode 100644
index 6c91667..0000000
--- a/fpdfsdk/fxedit/fx_edit.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 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_FXEDIT_FX_EDIT_H_
-#define FPDFSDK_FXEDIT_FX_EDIT_H_
-
-#include "core/fxcrt/fx_basic.h"
-
-class IPVT_FontMap;
-
-#define FX_EDIT_ISLATINWORD(u) \
- (u == 0x2D || (u <= 0x005A && u >= 0x0041) || \
- (u <= 0x007A && u >= 0x0061) || (u <= 0x02AF && u >= 0x00C0))
-
-CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap,
- int32_t nFontIndex,
- uint16_t Word,
- uint16_t SubWord);
-
-#endif // FPDFSDK_FXEDIT_FX_EDIT_H_
diff --git a/fpdfsdk/fxedit/fxet_ap.cpp b/fpdfsdk/fxedit/fxet_ap.cpp
deleted file mode 100644
index 448a539..0000000
--- a/fpdfsdk/fxedit/fxet_ap.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 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 "core/fpdfapi/font/cpdf_font.h"
-#include "core/fpdfapi/parser/fpdf_parser_decode.h"
-#include "core/fpdfdoc/cpvt_word.h"
-#include "core/fpdfdoc/ipvt_fontmap.h"
-#include "fpdfsdk/fxedit/fx_edit.h"
-#include "fpdfsdk/fxedit/fxet_edit.h"
-
-CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap,
- int32_t nFontIndex,
- uint16_t Word,
- uint16_t SubWord) {
- CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex);
- if (!pPDFFont)
- return CFX_ByteString();
-
- CFX_ByteString sWord;
- if (SubWord > 0) {
- Word = SubWord;
- } else {
- uint32_t dwCharCode = pPDFFont->IsUnicodeCompatible()
- ? pPDFFont->CharCodeFromUnicode(Word)
- : pFontMap->CharCodeFromUnicode(nFontIndex, Word);
-
- if (dwCharCode > 0) {
- pPDFFont->AppendChar(sWord, dwCharCode);
- return sWord;
- }
- }
-
- pPDFFont->AppendChar(sWord, Word);
- return sWord;
-}
diff --git a/fpdfsdk/fxedit/fxet_edit.cpp b/fpdfsdk/fxedit/fxet_edit.cpp
deleted file mode 100644
index 1acc577..0000000
--- a/fpdfsdk/fxedit/fxet_edit.cpp
+++ /dev/null
@@ -1,2307 +0,0 @@
-// Copyright 2014 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/fxedit/fxet_edit.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "core/fpdfapi/font/cpdf_font.h"
-#include "core/fpdfapi/page/cpdf_pageobject.h"
-#include "core/fpdfapi/page/cpdf_pageobjectholder.h"
-#include "core/fpdfapi/page/cpdf_pathobject.h"
-#include "core/fpdfapi/page/cpdf_textobject.h"
-#include "core/fpdfapi/parser/fpdf_parser_decode.h"
-#include "core/fpdfapi/render/cpdf_renderoptions.h"
-#include "core/fpdfapi/render/cpdf_textrenderer.h"
-#include "core/fpdfdoc/cpvt_section.h"
-#include "core/fpdfdoc/cpvt_word.h"
-#include "core/fpdfdoc/ipvt_fontmap.h"
-#include "core/fxge/cfx_graphstatedata.h"
-#include "core/fxge/cfx_pathdata.h"
-#include "core/fxge/cfx_renderdevice.h"
-#include "fpdfsdk/cfx_systemhandler.h"
-#include "fpdfsdk/fxedit/fx_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_Edit.h"
-#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h"
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
-
-namespace {
-
-const int kEditUndoMaxItems = 10000;
-
-CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) {
- if (strWords.GetLength() > 0)
- return PDF_EncodeString(strWords) + " Tj\n";
- return CFX_ByteString();
-}
-
-CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap,
- int32_t nFontIndex,
- FX_FLOAT fFontSize) {
- if (!pFontMap)
- return CFX_ByteString();
-
- CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
- if (sFontAlias.GetLength() <= 0 || fFontSize <= 0)
- return CFX_ByteString();
-
- CFX_ByteTextBuf sRet;
- sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n";
- return sRet.MakeString();
-}
-
-void DrawTextString(CFX_RenderDevice* pDevice,
- const CFX_PointF& pt,
- CPDF_Font* pFont,
- FX_FLOAT fFontSize,
- CFX_Matrix* pUser2Device,
- const CFX_ByteString& str,
- FX_ARGB crTextFill,
- int32_t nHorzScale) {
- CFX_PointF pos = pUser2Device->Transform(pt);
-
- if (pFont) {
- if (nHorzScale != 100) {
- CFX_Matrix mt(nHorzScale / 100.0f, 0, 0, 1, 0, 0);
- mt.Concat(*pUser2Device);
-
- CPDF_RenderOptions ro;
- ro.m_Flags = RENDER_CLEARTYPE;
- ro.m_ColorMode = RENDER_COLOR_NORMAL;
-
- CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize,
- &mt, str, crTextFill, nullptr, &ro);
- } else {
- CPDF_RenderOptions ro;
- ro.m_Flags = RENDER_CLEARTYPE;
- ro.m_ColorMode = RENDER_COLOR_NORMAL;
-
- CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize,
- pUser2Device, str, crTextFill, nullptr,
- &ro);
- }
- }
-}
-
-} // namespace
-
-CFX_Edit_Iterator::CFX_Edit_Iterator(CFX_Edit* pEdit,
- CPDF_VariableText::Iterator* pVTIterator)
- : m_pEdit(pEdit), m_pVTIterator(pVTIterator) {}
-
-CFX_Edit_Iterator::~CFX_Edit_Iterator() {}
-
-bool CFX_Edit_Iterator::NextWord() {
- return m_pVTIterator->NextWord();
-}
-
-bool CFX_Edit_Iterator::PrevWord() {
- return m_pVTIterator->PrevWord();
-}
-
-bool CFX_Edit_Iterator::GetWord(CPVT_Word& word) const {
- ASSERT(m_pEdit);
-
- if (m_pVTIterator->GetWord(word)) {
- word.ptWord = m_pEdit->VTToEdit(word.ptWord);
- return true;
- }
- return false;
-}
-
-bool CFX_Edit_Iterator::GetLine(CPVT_Line& line) const {
- ASSERT(m_pEdit);
-
- if (m_pVTIterator->GetLine(line)) {
- line.ptLine = m_pEdit->VTToEdit(line.ptLine);
- return true;
- }
- return false;
-}
-
-bool CFX_Edit_Iterator::GetSection(CPVT_Section& section) const {
- ASSERT(m_pEdit);
-
- if (m_pVTIterator->GetSection(section)) {
- section.rcSection = m_pEdit->VTToEdit(section.rcSection);
- return true;
- }
- return false;
-}
-
-void CFX_Edit_Iterator::SetAt(int32_t nWordIndex) {
- m_pVTIterator->SetAt(nWordIndex);
-}
-
-void CFX_Edit_Iterator::SetAt(const CPVT_WordPlace& place) {
- m_pVTIterator->SetAt(place);
-}
-
-const CPVT_WordPlace& CFX_Edit_Iterator::GetAt() const {
- return m_pVTIterator->GetAt();
-}
-
-CFX_Edit_Provider::CFX_Edit_Provider(IPVT_FontMap* pFontMap)
- : CPDF_VariableText::Provider(pFontMap), m_pFontMap(pFontMap) {
- ASSERT(m_pFontMap);
-}
-
-CFX_Edit_Provider::~CFX_Edit_Provider() {}
-
-IPVT_FontMap* CFX_Edit_Provider::GetFontMap() {
- return m_pFontMap;
-}
-
-int32_t CFX_Edit_Provider::GetCharWidth(int32_t nFontIndex, uint16_t word) {
- if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
- uint32_t charcode = word;
-
- if (pPDFFont->IsUnicodeCompatible())
- charcode = pPDFFont->CharCodeFromUnicode(word);
- else
- charcode = m_pFontMap->CharCodeFromUnicode(nFontIndex, word);
-
- if (charcode != CPDF_Font::kInvalidCharCode)
- return pPDFFont->GetCharWidthF(charcode);
- }
-
- return 0;
-}
-
-int32_t CFX_Edit_Provider::GetTypeAscent(int32_t nFontIndex) {
- if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
- return pPDFFont->GetTypeAscent();
-
- return 0;
-}
-
-int32_t CFX_Edit_Provider::GetTypeDescent(int32_t nFontIndex) {
- if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
- return pPDFFont->GetTypeDescent();
-
- return 0;
-}
-
-int32_t CFX_Edit_Provider::GetWordFontIndex(uint16_t word,
- int32_t charset,
- int32_t nFontIndex) {
- return m_pFontMap->GetWordFontIndex(word, charset, nFontIndex);
-}
-
-int32_t CFX_Edit_Provider::GetDefaultFontIndex() {
- return 0;
-}
-
-bool CFX_Edit_Provider::IsLatinWord(uint16_t word) {
- return FX_EDIT_ISLATINWORD(word);
-}
-
-CFX_Edit_Refresh::CFX_Edit_Refresh() {}
-
-CFX_Edit_Refresh::~CFX_Edit_Refresh() {}
-
-void CFX_Edit_Refresh::BeginRefresh() {
- m_RefreshRects.Clear();
- m_OldLineRects = std::move(m_NewLineRects);
-}
-
-void CFX_Edit_Refresh::Push(const CPVT_WordRange& linerange,
- const CFX_FloatRect& rect) {
- m_NewLineRects.Add(linerange, rect);
-}
-
-void CFX_Edit_Refresh::NoAnalyse() {
- {
- for (int32_t i = 0, sz = m_OldLineRects.GetSize(); i < sz; i++)
- if (CFX_Edit_LineRect* pOldRect = m_OldLineRects.GetAt(i))
- m_RefreshRects.Add(pOldRect->m_rcLine);
- }
-
- {
- for (int32_t i = 0, sz = m_NewLineRects.GetSize(); i < sz; i++)
- if (CFX_Edit_LineRect* pNewRect = m_NewLineRects.GetAt(i))
- m_RefreshRects.Add(pNewRect->m_rcLine);
- }
-}
-
-void CFX_Edit_Refresh::AddRefresh(const CFX_FloatRect& rect) {
- m_RefreshRects.Add(rect);
-}
-
-const CFX_Edit_RectArray* CFX_Edit_Refresh::GetRefreshRects() const {
- return &m_RefreshRects;
-}
-
-void CFX_Edit_Refresh::EndRefresh() {
- m_RefreshRects.Clear();
-}
-
-CFX_Edit_Undo::CFX_Edit_Undo(int32_t nBufsize)
- : m_nCurUndoPos(0),
- m_nBufSize(nBufsize),
- m_bModified(false),
- m_bVirgin(true),
- m_bWorking(false) {}
-
-CFX_Edit_Undo::~CFX_Edit_Undo() {
- Reset();
-}
-
-bool CFX_Edit_Undo::CanUndo() const {
- return m_nCurUndoPos > 0;
-}
-
-void CFX_Edit_Undo::Undo() {
- m_bWorking = true;
- if (m_nCurUndoPos > 0) {
- m_UndoItemStack[m_nCurUndoPos - 1]->Undo();
- m_nCurUndoPos--;
- m_bModified = (m_nCurUndoPos != 0);
- }
- m_bWorking = false;
-}
-
-bool CFX_Edit_Undo::CanRedo() const {
- return m_nCurUndoPos < m_UndoItemStack.size();
-}
-
-void CFX_Edit_Undo::Redo() {
- m_bWorking = true;
- if (m_nCurUndoPos < m_UndoItemStack.size()) {
- m_UndoItemStack[m_nCurUndoPos]->Redo();
- m_nCurUndoPos++;
- m_bModified = true;
- }
- m_bWorking = false;
-}
-
-void CFX_Edit_Undo::AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem) {
- ASSERT(!m_bWorking);
- ASSERT(pItem);
- ASSERT(m_nBufSize > 1);
- if (m_nCurUndoPos < m_UndoItemStack.size())
- RemoveTails();
-
- if (m_UndoItemStack.size() >= m_nBufSize) {
- RemoveHeads();
- m_bVirgin = false;
- }
-
- m_UndoItemStack.push_back(std::move(pItem));
- m_nCurUndoPos = m_UndoItemStack.size();
- m_bModified = true;
-}
-
-bool CFX_Edit_Undo::IsModified() const {
- return m_bVirgin ? m_bModified : true;
-}
-
-void CFX_Edit_Undo::RemoveHeads() {
- ASSERT(m_UndoItemStack.size() > 1);
- m_UndoItemStack.pop_front();
-}
-
-void CFX_Edit_Undo::RemoveTails() {
- while (m_UndoItemStack.size() > m_nCurUndoPos)
- m_UndoItemStack.pop_back();
-}
-
-void CFX_Edit_Undo::Reset() {
- m_UndoItemStack.clear();
- m_nCurUndoPos = 0;
-}
-
-CFX_Edit_UndoItem::CFX_Edit_UndoItem() : m_bFirst(true), m_bLast(true) {}
-
-CFX_Edit_UndoItem::~CFX_Edit_UndoItem() {}
-
-CFX_WideString CFX_Edit_UndoItem::GetUndoTitle() const {
- return CFX_WideString();
-}
-
-void CFX_Edit_UndoItem::SetFirst(bool bFirst) {
- m_bFirst = bFirst;
-}
-
-void CFX_Edit_UndoItem::SetLast(bool bLast) {
- m_bLast = bLast;
-}
-
-bool CFX_Edit_UndoItem::IsLast() {
- return m_bLast;
-}
-
-CFX_Edit_GroupUndoItem::CFX_Edit_GroupUndoItem(const CFX_WideString& sTitle)
- : m_sTitle(sTitle) {}
-
-CFX_Edit_GroupUndoItem::~CFX_Edit_GroupUndoItem() {}
-
-void CFX_Edit_GroupUndoItem::AddUndoItem(
- std::unique_ptr<CFX_Edit_UndoItem> pUndoItem) {
- pUndoItem->SetFirst(false);
- pUndoItem->SetLast(false);
- if (m_sTitle.IsEmpty())
- m_sTitle = pUndoItem->GetUndoTitle();
-
- m_Items.push_back(std::move(pUndoItem));
-}
-
-void CFX_Edit_GroupUndoItem::UpdateItems() {
- if (!m_Items.empty()) {
- m_Items.front()->SetFirst(true);
- m_Items.back()->SetLast(true);
- }
-}
-
-void CFX_Edit_GroupUndoItem::Undo() {
- for (auto iter = m_Items.rbegin(); iter != m_Items.rend(); ++iter)
- (*iter)->Undo();
-}
-
-void CFX_Edit_GroupUndoItem::Redo() {
- for (auto iter = m_Items.begin(); iter != m_Items.end(); ++iter)
- (*iter)->Redo();
-}
-
-CFX_WideString CFX_Edit_GroupUndoItem::GetUndoTitle() const {
- return m_sTitle;
-}
-
-CFXEU_InsertWord::CFXEU_InsertWord(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- uint16_t word,
- int32_t charset,
- const CPVT_WordProps* pWordProps)
- : m_pEdit(pEdit),
- m_wpOld(wpOldPlace),
- m_wpNew(wpNewPlace),
- m_Word(word),
- m_nCharset(charset),
- m_WordProps() {
- if (pWordProps)
- m_WordProps = *pWordProps;
-}
-
-CFXEU_InsertWord::~CFXEU_InsertWord() {}
-
-void CFXEU_InsertWord::Redo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpOld);
- m_pEdit->InsertWord(m_Word, m_nCharset, &m_WordProps, false, true);
- }
-}
-
-void CFXEU_InsertWord::Undo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpNew);
- m_pEdit->Backspace(false, true);
- }
-}
-
-CFXEU_InsertReturn::CFXEU_InsertReturn(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- const CPVT_SecProps* pSecProps,
- const CPVT_WordProps* pWordProps)
- : m_pEdit(pEdit),
- m_wpOld(wpOldPlace),
- m_wpNew(wpNewPlace),
- m_SecProps(),
- m_WordProps() {
- if (pSecProps)
- m_SecProps = *pSecProps;
- if (pWordProps)
- m_WordProps = *pWordProps;
-}
-
-CFXEU_InsertReturn::~CFXEU_InsertReturn() {}
-
-void CFXEU_InsertReturn::Redo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpOld);
- m_pEdit->InsertReturn(&m_SecProps, &m_WordProps, false, true);
- }
-}
-
-void CFXEU_InsertReturn::Undo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpNew);
- m_pEdit->Backspace(false, true);
- }
-}
-
-CFXEU_Backspace::CFXEU_Backspace(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- uint16_t word,
- int32_t charset,
- const CPVT_SecProps& SecProps,
- const CPVT_WordProps& WordProps)
- : m_pEdit(pEdit),
- m_wpOld(wpOldPlace),
- m_wpNew(wpNewPlace),
- m_Word(word),
- m_nCharset(charset),
- m_SecProps(SecProps),
- m_WordProps(WordProps) {}
-
-CFXEU_Backspace::~CFXEU_Backspace() {}
-
-void CFXEU_Backspace::Redo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpOld);
- m_pEdit->Backspace(false, true);
- }
-}
-
-void CFXEU_Backspace::Undo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpNew);
- if (m_wpNew.SecCmp(m_wpOld) != 0) {
- m_pEdit->InsertReturn(&m_SecProps, &m_WordProps, false, true);
- } else {
- m_pEdit->InsertWord(m_Word, m_nCharset, &m_WordProps, false, true);
- }
- }
-}
-
-CFXEU_Delete::CFXEU_Delete(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- uint16_t word,
- int32_t charset,
- const CPVT_SecProps& SecProps,
- const CPVT_WordProps& WordProps,
- bool bSecEnd)
- : m_pEdit(pEdit),
- m_wpOld(wpOldPlace),
- m_wpNew(wpNewPlace),
- m_Word(word),
- m_nCharset(charset),
- m_SecProps(SecProps),
- m_WordProps(WordProps),
- m_bSecEnd(bSecEnd) {}
-
-CFXEU_Delete::~CFXEU_Delete() {}
-
-void CFXEU_Delete::Redo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpOld);
- m_pEdit->Delete(false, true);
- }
-}
-
-void CFXEU_Delete::Undo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpNew);
- if (m_bSecEnd) {
- m_pEdit->InsertReturn(&m_SecProps, &m_WordProps, false, true);
- } else {
- m_pEdit->InsertWord(m_Word, m_nCharset, &m_WordProps, false, true);
- }
- }
-}
-
-CFXEU_Clear::CFXEU_Clear(CFX_Edit* pEdit,
- const CPVT_WordRange& wrSel,
- const CFX_WideString& swText)
- : m_pEdit(pEdit), m_wrSel(wrSel), m_swText(swText) {}
-
-CFXEU_Clear::~CFXEU_Clear() {}
-
-void CFXEU_Clear::Redo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetSel(m_wrSel.BeginPos, m_wrSel.EndPos);
- m_pEdit->Clear(false, true);
- }
-}
-
-void CFXEU_Clear::Undo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wrSel.BeginPos);
- m_pEdit->InsertText(m_swText, FXFONT_DEFAULT_CHARSET, false, true);
- m_pEdit->SetSel(m_wrSel.BeginPos, m_wrSel.EndPos);
- }
-}
-
-CFXEU_InsertText::CFXEU_InsertText(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- const CFX_WideString& swText,
- int32_t charset)
- : m_pEdit(pEdit),
- m_wpOld(wpOldPlace),
- m_wpNew(wpNewPlace),
- m_swText(swText),
- m_nCharset(charset) {}
-
-CFXEU_InsertText::~CFXEU_InsertText() {}
-
-void CFXEU_InsertText::Redo() {
- if (m_pEdit && IsLast()) {
- m_pEdit->SelectNone();
- m_pEdit->SetCaret(m_wpOld);
- m_pEdit->InsertText(m_swText, m_nCharset, false, true);
- }
-}
-
-void CFXEU_InsertText::Undo() {
- if (m_pEdit) {
- m_pEdit->SelectNone();
- m_pEdit->SetSel(m_wpOld, m_wpNew);
- m_pEdit->Clear(false, true);
- }
-}
-
-// static
-CFX_ByteString CFX_Edit::GetEditAppearanceStream(CFX_Edit* pEdit,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange,
- bool bContinuous,
- uint16_t SubWord) {
- CFX_Edit_Iterator* pIterator = pEdit->GetIterator();
- if (pRange)
- pIterator->SetAt(pRange->BeginPos);
- else
- pIterator->SetAt(0);
-
- CFX_ByteTextBuf sEditStream;
- CFX_ByteTextBuf sWords;
- int32_t nCurFontIndex = -1;
- CFX_PointF ptOld;
- CFX_PointF ptNew;
- CPVT_WordPlace oldplace;
-
- while (pIterator->NextWord()) {
- CPVT_WordPlace place = pIterator->GetAt();
- if (pRange && place.WordCmp(pRange->EndPos) > 0)
- break;
-
- if (bContinuous) {
- if (place.LineCmp(oldplace) != 0) {
- if (sWords.GetSize() > 0) {
- sEditStream << GetWordRenderString(sWords.MakeString());
- sWords.Clear();
- }
-
- CPVT_Word word;
- if (pIterator->GetWord(word)) {
- ptNew = CFX_PointF(word.ptWord.x + ptOffset.x,
- word.ptWord.y + ptOffset.y);
- } else {
- CPVT_Line line;
- pIterator->GetLine(line);
- ptNew = CFX_PointF(line.ptLine.x + ptOffset.x,
- line.ptLine.y + ptOffset.y);
- }
-
- if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
- sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
- << " Td\n";
-
- ptOld = ptNew;
- }
- }
-
- CPVT_Word word;
- if (pIterator->GetWord(word)) {
- if (word.nFontIndex != nCurFontIndex) {
- if (sWords.GetSize() > 0) {
- sEditStream << GetWordRenderString(sWords.MakeString());
- sWords.Clear();
- }
- sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex,
- word.fFontSize);
- nCurFontIndex = word.nFontIndex;
- }
-
- sWords << GetPDFWordString(pEdit->GetFontMap(), nCurFontIndex,
- word.Word, SubWord);
- }
-
- oldplace = place;
- } else {
- CPVT_Word word;
- if (pIterator->GetWord(word)) {
- ptNew =
- CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
-
- if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
- sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
- << " Td\n";
- ptOld = ptNew;
- }
-
- if (word.nFontIndex != nCurFontIndex) {
- sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex,
- word.fFontSize);
- nCurFontIndex = word.nFontIndex;
- }
-
- sEditStream << GetWordRenderString(GetPDFWordString(
- pEdit->GetFontMap(), nCurFontIndex, word.Word, SubWord));
- }
- }
- }
-
- if (sWords.GetSize() > 0) {
- sEditStream << GetWordRenderString(sWords.MakeString());
- sWords.Clear();
- }
-
- CFX_ByteTextBuf sAppStream;
- if (sEditStream.GetSize() > 0) {
- int32_t nHorzScale = pEdit->GetHorzScale();
- if (nHorzScale != 100) {
- sAppStream << nHorzScale << " Tz\n";
- }
-
- FX_FLOAT fCharSpace = pEdit->GetCharSpace();
- if (!IsFloatZero(fCharSpace)) {
- sAppStream << fCharSpace << " Tc\n";
- }
-
- sAppStream << sEditStream;
- }
-
- return sAppStream.MakeString();
-}
-
-// static
-CFX_ByteString CFX_Edit::GetSelectAppearanceStream(
- CFX_Edit* pEdit,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange) {
- if (!pRange || !pRange->IsExist())
- return CFX_ByteString();
-
- CFX_Edit_Iterator* pIterator = pEdit->GetIterator();
- pIterator->SetAt(pRange->BeginPos);
-
- CFX_ByteTextBuf sRet;
- while (pIterator->NextWord()) {
- CPVT_WordPlace place = pIterator->GetAt();
- if (place.WordCmp(pRange->EndPos) > 0)
- break;
-
- CPVT_Word word;
- CPVT_Line line;
- if (pIterator->GetWord(word) && pIterator->GetLine(line)) {
- sRet << word.ptWord.x + ptOffset.x << " "
- << line.ptLine.y + line.fLineDescent << " " << word.fWidth << " "
- << line.fLineAscent - line.fLineDescent << " re\nf\n";
- }
- }
-
- return sRet.MakeString();
-}
-
-// static
-void CFX_Edit::DrawEdit(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- CFX_Edit* pEdit,
- FX_COLORREF crTextFill,
- const CFX_FloatRect& rcClip,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange,
- CFX_SystemHandler* pSystemHandler,
- CFFL_FormFiller* pFFLData) {
- const bool bContinuous =
- pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f;
- uint16_t SubWord = pEdit->GetPasswordChar();
- FX_FLOAT fFontSize = pEdit->GetFontSize();
- CPVT_WordRange wrSelect = pEdit->GetSelectWordRange();
- int32_t nHorzScale = pEdit->GetHorzScale();
-
- FX_COLORREF crCurFill = crTextFill;
- FX_COLORREF crOldFill = crCurFill;
-
- bool bSelect = false;
- const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255);
- const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113);
-
- CFX_ByteTextBuf sTextBuf;
- int32_t nFontIndex = -1;
- CFX_PointF ptBT;
- pDevice->SaveState();
- if (!rcClip.IsEmpty()) {
- CFX_FloatRect rcTemp = rcClip;
- pUser2Device->TransformRect(rcTemp);
- pDevice->SetClip_Rect(rcTemp.ToFxRect());
- }
-
- CFX_Edit_Iterator* pIterator = pEdit->GetIterator();
- if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) {
- if (pRange)
- pIterator->SetAt(pRange->BeginPos);
- else
- pIterator->SetAt(0);
-
- CPVT_WordPlace oldplace;
- while (pIterator->NextWord()) {
- CPVT_WordPlace place = pIterator->GetAt();
- if (pRange && place.WordCmp(pRange->EndPos) > 0)
- break;
-
- if (wrSelect.IsExist()) {
- bSelect = place.WordCmp(wrSelect.BeginPos) > 0 &&
- place.WordCmp(wrSelect.EndPos) <= 0;
- crCurFill = bSelect ? crWhite : crTextFill;
- }
- if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) {
- crCurFill = crTextFill;
- crOldFill = crCurFill;
- }
- CPVT_Word word;
- if (pIterator->GetWord(word)) {
- if (bSelect) {
- CPVT_Line line;
- pIterator->GetLine(line);
-
- if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) {
- CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent,
- word.ptWord.x + word.fWidth,
- line.ptLine.y + line.fLineAscent);
- rc.Intersect(rcClip);
- pSystemHandler->OutputSelectedRect(pFFLData, rc);
- } else {
- CFX_PathData pathSelBK;
- pathSelBK.AppendRect(
- word.ptWord.x, line.ptLine.y + line.fLineDescent,
- word.ptWord.x + word.fWidth, line.ptLine.y + line.fLineAscent);
-
- pDevice->DrawPath(&pathSelBK, pUser2Device, nullptr, crSelBK, 0,
- FXFILL_WINDING);
- }
- }
-
- if (bContinuous) {
- if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex ||
- crOldFill != crCurFill) {
- if (sTextBuf.GetLength() > 0) {
- DrawTextString(
- pDevice, CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
- pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device,
- sTextBuf.MakeString(), crOldFill, nHorzScale);
-
- sTextBuf.Clear();
- }
- nFontIndex = word.nFontIndex;
- ptBT = word.ptWord;
- crOldFill = crCurFill;
- }
-
- sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word,
- SubWord)
- .AsStringC();
- } else {
- DrawTextString(
- pDevice, CFX_PointF(word.ptWord.x + ptOffset.x,
- word.ptWord.y + ptOffset.y),
- pFontMap->GetPDFFont(word.nFontIndex), fFontSize, pUser2Device,
- GetPDFWordString(pFontMap, word.nFontIndex, word.Word, SubWord),
- crCurFill, nHorzScale);
- }
- oldplace = place;
- }
- }
-
- if (sTextBuf.GetLength() > 0) {
- DrawTextString(pDevice,
- CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
- pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device,
- sTextBuf.MakeString(), crOldFill, nHorzScale);
- }
- }
-
- pDevice->RestoreState(false);
-}
-
-CFX_Edit::CFX_Edit()
- : m_pVT(new CPDF_VariableText),
- m_pNotify(nullptr),
- m_pOprNotify(nullptr),
- m_wpCaret(-1, -1, -1),
- m_wpOldCaret(-1, -1, -1),
- m_SelState(),
- m_bEnableScroll(false),
- m_Undo(kEditUndoMaxItems),
- m_nAlignment(0),
- m_bNotifyFlag(false),
- m_bEnableOverflow(false),
- m_bEnableRefresh(true),
- m_rcOldContent(0.0f, 0.0f, 0.0f, 0.0f),
- m_bEnableUndo(true),
- m_bOprNotify(false),
- m_pGroupUndoItem(nullptr) {}
-
-CFX_Edit::~CFX_Edit() {
- ASSERT(!m_pGroupUndoItem);
-}
-
-void CFX_Edit::Initialize() {
- m_pVT->Initialize();
- SetCaret(m_pVT->GetBeginWordPlace());
- SetCaretOrigin();
-}
-
-void CFX_Edit::SetFontMap(IPVT_FontMap* pFontMap) {
- m_pVTProvider = pdfium::MakeUnique<CFX_Edit_Provider>(pFontMap);
- m_pVT->SetProvider(m_pVTProvider.get());
-}
-
-void CFX_Edit::SetNotify(CPWL_EditCtrl* pNotify) {
- m_pNotify = pNotify;
-}
-
-void CFX_Edit::SetOprNotify(CPWL_Edit* pOprNotify) {
- m_pOprNotify = pOprNotify;
-}
-
-CFX_Edit_Iterator* CFX_Edit::GetIterator() {
- if (!m_pIterator) {
- m_pIterator =
- pdfium::MakeUnique<CFX_Edit_Iterator>(this, m_pVT->GetIterator());
- }
- return m_pIterator.get();
-}
-
-IPVT_FontMap* CFX_Edit::GetFontMap() {
- return m_pVTProvider ? m_pVTProvider->GetFontMap() : nullptr;
-}
-
-void CFX_Edit::SetPlateRect(const CFX_FloatRect& rect) {
- m_pVT->SetPlateRect(rect);
- m_ptScrollPos = CFX_PointF(rect.left, rect.top);
- Paint();
-}
-
-void CFX_Edit::SetAlignmentH(int32_t nFormat, bool bPaint) {
- m_pVT->SetAlignment(nFormat);
- if (bPaint)
- Paint();
-}
-
-void CFX_Edit::SetAlignmentV(int32_t nFormat, bool bPaint) {
- m_nAlignment = nFormat;
- if (bPaint)
- Paint();
-}
-
-void CFX_Edit::SetPasswordChar(uint16_t wSubWord, bool bPaint) {
- m_pVT->SetPasswordChar(wSubWord);
- if (bPaint)
- Paint();
-}
-
-void CFX_Edit::SetLimitChar(int32_t nLimitChar) {
- m_pVT->SetLimitChar(nLimitChar);
- Paint();
-}
-
-void CFX_Edit::SetCharArray(int32_t nCharArray) {
- m_pVT->SetCharArray(nCharArray);
- Paint();
-}
-
-void CFX_Edit::SetCharSpace(FX_FLOAT fCharSpace) {
- m_pVT->SetCharSpace(fCharSpace);
- Paint();
-}
-
-void CFX_Edit::SetMultiLine(bool bMultiLine, bool bPaint) {
- m_pVT->SetMultiLine(bMultiLine);
- if (bPaint)
- Paint();
-}
-
-void CFX_Edit::SetAutoReturn(bool bAuto, bool bPaint) {
- m_pVT->SetAutoReturn(bAuto);
- if (bPaint)
- Paint();
-}
-
-void CFX_Edit::SetAutoFontSize(bool bAuto, bool bPaint) {
- m_pVT->SetAutoFontSize(bAuto);
- if (bPaint)
- Paint();
-}
-
-void CFX_Edit::SetFontSize(FX_FLOAT fFontSize) {
- m_pVT->SetFontSize(fFontSize);
- Paint();
-}
-
-void CFX_Edit::SetAutoScroll(bool bAuto, bool bPaint) {
- m_bEnableScroll = bAuto;
- if (bPaint)
- Paint();
-}
-
-void CFX_Edit::SetTextOverflow(bool bAllowed, bool bPaint) {
- m_bEnableOverflow = bAllowed;
- if (bPaint)
- Paint();
-}
-
-void CFX_Edit::SetSel(int32_t nStartChar, int32_t nEndChar) {
- if (m_pVT->IsValid()) {
- if (nStartChar == 0 && nEndChar < 0) {
- SelectAll();
- } else if (nStartChar < 0) {
- SelectNone();
- } else {
- if (nStartChar < nEndChar) {
- SetSel(m_pVT->WordIndexToWordPlace(nStartChar),
- m_pVT->WordIndexToWordPlace(nEndChar));
- } else {
- SetSel(m_pVT->WordIndexToWordPlace(nEndChar),
- m_pVT->WordIndexToWordPlace(nStartChar));
- }
- }
- }
-}
-
-void CFX_Edit::SetSel(const CPVT_WordPlace& begin, const CPVT_WordPlace& end) {
- if (m_pVT->IsValid()) {
- SelectNone();
-
- m_SelState.Set(begin, end);
-
- SetCaret(m_SelState.EndPos);
-
- if (m_SelState.IsExist()) {
- ScrollToCaret();
- Refresh();
- SetCaretInfo();
- } else {
- ScrollToCaret();
- SetCaretInfo();
- }
- }
-}
-
-void CFX_Edit::GetSel(int32_t& nStartChar, int32_t& nEndChar) const {
- nStartChar = -1;
- nEndChar = -1;
-
- if (m_pVT->IsValid()) {
- if (m_SelState.IsExist()) {
- if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) < 0) {
- nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
- nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
- } else {
- nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
- nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
- }
- } else {
- nStartChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
- nEndChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
- }
- }
-}
-
-int32_t CFX_Edit::GetCaret() const {
- if (m_pVT->IsValid())
- return m_pVT->WordPlaceToWordIndex(m_wpCaret);
-
- return -1;
-}
-
-CPVT_WordPlace CFX_Edit::GetCaretWordPlace() const {
- return m_wpCaret;
-}
-
-CFX_WideString CFX_Edit::GetText() const {
- CFX_WideString swRet;
-
- if (!m_pVT->IsValid())
- return swRet;
-
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- pIterator->SetAt(0);
-
- CPVT_Word wordinfo;
- CPVT_WordPlace oldplace = pIterator->GetAt();
- while (pIterator->NextWord()) {
- CPVT_WordPlace place = pIterator->GetAt();
-
- if (pIterator->GetWord(wordinfo))
- swRet += wordinfo.Word;
-
- if (oldplace.SecCmp(place) != 0)
- swRet += L"\r\n";
-
- oldplace = place;
- }
-
- return swRet;
-}
-
-CFX_WideString CFX_Edit::GetRangeText(const CPVT_WordRange& range) const {
- CFX_WideString swRet;
-
- if (!m_pVT->IsValid())
- return swRet;
-
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- CPVT_WordRange wrTemp = range;
- m_pVT->UpdateWordPlace(wrTemp.BeginPos);
- m_pVT->UpdateWordPlace(wrTemp.EndPos);
- pIterator->SetAt(wrTemp.BeginPos);
-
- CPVT_Word wordinfo;
- CPVT_WordPlace oldplace = wrTemp.BeginPos;
- while (pIterator->NextWord()) {
- CPVT_WordPlace place = pIterator->GetAt();
- if (place.WordCmp(wrTemp.EndPos) > 0)
- break;
-
- if (pIterator->GetWord(wordinfo))
- swRet += wordinfo.Word;
-
- if (oldplace.SecCmp(place) != 0)
- swRet += L"\r\n";
-
- oldplace = place;
- }
-
- return swRet;
-}
-
-CFX_WideString CFX_Edit::GetSelText() const {
- return GetRangeText(m_SelState.ConvertToWordRange());
-}
-
-int32_t CFX_Edit::GetTotalWords() const {
- return m_pVT->GetTotalWords();
-}
-
-int32_t CFX_Edit::GetTotalLines() const {
- int32_t nLines = 1;
-
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- pIterator->SetAt(0);
- while (pIterator->NextLine())
- ++nLines;
-
- return nLines;
-}
-
-CPVT_WordRange CFX_Edit::GetSelectWordRange() const {
- return m_SelState.ConvertToWordRange();
-}
-
-void CFX_Edit::SetText(const CFX_WideString& sText) {
- Empty();
- DoInsertText(CPVT_WordPlace(0, 0, -1), sText, FXFONT_DEFAULT_CHARSET);
- Paint();
-}
-
-bool CFX_Edit::InsertWord(uint16_t word, int32_t charset) {
- return InsertWord(word, charset, nullptr, true, true);
-}
-
-bool CFX_Edit::InsertReturn() {
- return InsertReturn(nullptr, nullptr, true, true);
-}
-
-bool CFX_Edit::Backspace() {
- return Backspace(true, true);
-}
-
-bool CFX_Edit::Delete() {
- return Delete(true, true);
-}
-
-bool CFX_Edit::Clear() {
- return Clear(true, true);
-}
-
-bool CFX_Edit::InsertText(const CFX_WideString& sText, int32_t charset) {
- return InsertText(sText, charset, true, true);
-}
-
-FX_FLOAT CFX_Edit::GetFontSize() const {
- return m_pVT->GetFontSize();
-}
-
-uint16_t CFX_Edit::GetPasswordChar() const {
- return m_pVT->GetPasswordChar();
-}
-
-int32_t CFX_Edit::GetCharArray() const {
- return m_pVT->GetCharArray();
-}
-
-CFX_FloatRect CFX_Edit::GetContentRect() const {
- return VTToEdit(m_pVT->GetContentRect());
-}
-
-int32_t CFX_Edit::GetHorzScale() const {
- return m_pVT->GetHorzScale();
-}
-
-FX_FLOAT CFX_Edit::GetCharSpace() const {
- return m_pVT->GetCharSpace();
-}
-
-CPVT_WordRange CFX_Edit::GetWholeWordRange() const {
- if (m_pVT->IsValid())
- return CPVT_WordRange(m_pVT->GetBeginWordPlace(), m_pVT->GetEndWordPlace());
-
- return CPVT_WordRange();
-}
-
-CPVT_WordRange CFX_Edit::GetVisibleWordRange() const {
- if (m_bEnableOverflow)
- return GetWholeWordRange();
-
- if (m_pVT->IsValid()) {
- CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
-
- CPVT_WordPlace place1 =
- m_pVT->SearchWordPlace(EditToVT(CFX_PointF(rcPlate.left, rcPlate.top)));
- CPVT_WordPlace place2 = m_pVT->SearchWordPlace(
- EditToVT(CFX_PointF(rcPlate.right, rcPlate.bottom)));
-
- return CPVT_WordRange(place1, place2);
- }
-
- return CPVT_WordRange();
-}
-
-CPVT_WordPlace CFX_Edit::SearchWordPlace(const CFX_PointF& point) const {
- if (m_pVT->IsValid()) {
- return m_pVT->SearchWordPlace(EditToVT(point));
- }
-
- return CPVT_WordPlace();
-}
-
-void CFX_Edit::Paint() {
- if (m_pVT->IsValid()) {
- RearrangeAll();
- ScrollToCaret();
- Refresh();
- SetCaretOrigin();
- SetCaretInfo();
- }
-}
-
-void CFX_Edit::RearrangeAll() {
- if (m_pVT->IsValid()) {
- m_pVT->UpdateWordPlace(m_wpCaret);
- m_pVT->RearrangeAll();
- m_pVT->UpdateWordPlace(m_wpCaret);
- SetScrollInfo();
- SetContentChanged();
- }
-}
-
-void CFX_Edit::RearrangePart(const CPVT_WordRange& range) {
- if (m_pVT->IsValid()) {
- m_pVT->UpdateWordPlace(m_wpCaret);
- m_pVT->RearrangePart(range);
- m_pVT->UpdateWordPlace(m_wpCaret);
- SetScrollInfo();
- SetContentChanged();
- }
-}
-
-void CFX_Edit::SetContentChanged() {
- if (m_pNotify) {
- CFX_FloatRect rcContent = m_pVT->GetContentRect();
- if (rcContent.Width() != m_rcOldContent.Width() ||
- rcContent.Height() != m_rcOldContent.Height()) {
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- m_pNotify->IOnContentChange(rcContent);
- m_bNotifyFlag = false;
- }
- m_rcOldContent = rcContent;
- }
- }
-}
-
-void CFX_Edit::SelectAll() {
- if (m_pVT->IsValid()) {
- m_SelState = CFX_Edit_Select(GetWholeWordRange());
- SetCaret(m_SelState.EndPos);
-
- ScrollToCaret();
- Refresh();
- SetCaretInfo();
- }
-}
-
-void CFX_Edit::SelectNone() {
- if (m_pVT->IsValid()) {
- if (m_SelState.IsExist()) {
- m_SelState.Default();
- Refresh();
- }
- }
-}
-
-bool CFX_Edit::IsSelected() const {
- return m_SelState.IsExist();
-}
-
-CFX_PointF CFX_Edit::VTToEdit(const CFX_PointF& point) const {
- CFX_FloatRect rcContent = m_pVT->GetContentRect();
- CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
-
- FX_FLOAT fPadding = 0.0f;
-
- switch (m_nAlignment) {
- case 0:
- fPadding = 0.0f;
- break;
- case 1:
- fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
- break;
- case 2:
- fPadding = rcPlate.Height() - rcContent.Height();
- break;
- }
-
- return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left),
- point.y - (m_ptScrollPos.y + fPadding - rcPlate.top));
-}
-
-CFX_PointF CFX_Edit::EditToVT(const CFX_PointF& point) const {
- CFX_FloatRect rcContent = m_pVT->GetContentRect();
- CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
-
- FX_FLOAT fPadding = 0.0f;
-
- switch (m_nAlignment) {
- case 0:
- fPadding = 0.0f;
- break;
- case 1:
- fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
- break;
- case 2:
- fPadding = rcPlate.Height() - rcContent.Height();
- break;
- }
-
- return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left),
- point.y + (m_ptScrollPos.y + fPadding - rcPlate.top));
-}
-
-CFX_FloatRect CFX_Edit::VTToEdit(const CFX_FloatRect& rect) const {
- CFX_PointF ptLeftBottom = VTToEdit(CFX_PointF(rect.left, rect.bottom));
- CFX_PointF ptRightTop = VTToEdit(CFX_PointF(rect.right, rect.top));
-
- return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
- ptRightTop.y);
-}
-
-void CFX_Edit::SetScrollInfo() {
- if (m_pNotify) {
- CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
- CFX_FloatRect rcContent = m_pVT->GetContentRect();
-
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top,
- rcContent.bottom, rcContent.top,
- rcPlate.Height() / 3, rcPlate.Height());
- m_bNotifyFlag = false;
- }
- }
-}
-
-void CFX_Edit::SetScrollPosX(FX_FLOAT fx) {
- if (!m_bEnableScroll)
- return;
-
- if (m_pVT->IsValid()) {
- if (!IsFloatEqual(m_ptScrollPos.x, fx)) {
- m_ptScrollPos.x = fx;
- Refresh();
- }
- }
-}
-
-void CFX_Edit::SetScrollPosY(FX_FLOAT fy) {
- if (!m_bEnableScroll)
- return;
-
- if (m_pVT->IsValid()) {
- if (!IsFloatEqual(m_ptScrollPos.y, fy)) {
- m_ptScrollPos.y = fy;
- Refresh();
-
- if (m_pNotify) {
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- m_pNotify->IOnSetScrollPosY(fy);
- m_bNotifyFlag = false;
- }
- }
- }
- }
-}
-
-void CFX_Edit::SetScrollPos(const CFX_PointF& point) {
- SetScrollPosX(point.x);
- SetScrollPosY(point.y);
- SetScrollLimit();
- SetCaretInfo();
-}
-
-CFX_PointF CFX_Edit::GetScrollPos() const {
- return m_ptScrollPos;
-}
-
-void CFX_Edit::SetScrollLimit() {
- if (m_pVT->IsValid()) {
- CFX_FloatRect rcContent = m_pVT->GetContentRect();
- CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
-
- if (rcPlate.Width() > rcContent.Width()) {
- SetScrollPosX(rcPlate.left);
- } else {
- if (IsFloatSmaller(m_ptScrollPos.x, rcContent.left)) {
- SetScrollPosX(rcContent.left);
- } else if (IsFloatBigger(m_ptScrollPos.x,
- rcContent.right - rcPlate.Width())) {
- SetScrollPosX(rcContent.right - rcPlate.Width());
- }
- }
-
- if (rcPlate.Height() > rcContent.Height()) {
- SetScrollPosY(rcPlate.top);
- } else {
- if (IsFloatSmaller(m_ptScrollPos.y,
- rcContent.bottom + rcPlate.Height())) {
- SetScrollPosY(rcContent.bottom + rcPlate.Height());
- } else if (IsFloatBigger(m_ptScrollPos.y, rcContent.top)) {
- SetScrollPosY(rcContent.top);
- }
- }
- }
-}
-
-void CFX_Edit::ScrollToCaret() {
- SetScrollLimit();
-
- if (!m_pVT->IsValid())
- return;
-
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- pIterator->SetAt(m_wpCaret);
-
- CFX_PointF ptHead;
- CFX_PointF ptFoot;
- CPVT_Word word;
- CPVT_Line line;
- if (pIterator->GetWord(word)) {
- ptHead.x = word.ptWord.x + word.fWidth;
- ptHead.y = word.ptWord.y + word.fAscent;
- ptFoot.x = word.ptWord.x + word.fWidth;
- ptFoot.y = word.ptWord.y + word.fDescent;
- } else if (pIterator->GetLine(line)) {
- ptHead.x = line.ptLine.x;
- ptHead.y = line.ptLine.y + line.fLineAscent;
- ptFoot.x = line.ptLine.x;
- ptFoot.y = line.ptLine.y + line.fLineDescent;
- }
-
- CFX_PointF ptHeadEdit = VTToEdit(ptHead);
- CFX_PointF ptFootEdit = VTToEdit(ptFoot);
- CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
- if (!IsFloatEqual(rcPlate.left, rcPlate.right)) {
- if (IsFloatSmaller(ptHeadEdit.x, rcPlate.left) ||
- IsFloatEqual(ptHeadEdit.x, rcPlate.left)) {
- SetScrollPosX(ptHead.x);
- } else if (IsFloatBigger(ptHeadEdit.x, rcPlate.right)) {
- SetScrollPosX(ptHead.x - rcPlate.Width());
- }
- }
-
- if (!IsFloatEqual(rcPlate.top, rcPlate.bottom)) {
- if (IsFloatSmaller(ptFootEdit.y, rcPlate.bottom) ||
- IsFloatEqual(ptFootEdit.y, rcPlate.bottom)) {
- if (IsFloatSmaller(ptHeadEdit.y, rcPlate.top)) {
- SetScrollPosY(ptFoot.y + rcPlate.Height());
- }
- } else if (IsFloatBigger(ptHeadEdit.y, rcPlate.top)) {
- if (IsFloatBigger(ptFootEdit.y, rcPlate.bottom)) {
- SetScrollPosY(ptHead.y);
- }
- }
- }
-}
-
-void CFX_Edit::Refresh() {
- if (m_bEnableRefresh && m_pVT->IsValid()) {
- m_Refresh.BeginRefresh();
- RefreshPushLineRects(GetVisibleWordRange());
-
- m_Refresh.NoAnalyse();
- m_ptRefreshScrollPos = m_ptScrollPos;
-
- if (m_pNotify) {
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- if (const CFX_Edit_RectArray* pRects = m_Refresh.GetRefreshRects()) {
- for (int32_t i = 0, sz = pRects->GetSize(); i < sz; i++)
- m_pNotify->IOnInvalidateRect(pRects->GetAt(i));
- }
- m_bNotifyFlag = false;
- }
- }
-
- m_Refresh.EndRefresh();
- }
-}
-
-void CFX_Edit::RefreshPushLineRects(const CPVT_WordRange& wr) {
- if (!m_pVT->IsValid())
- return;
-
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- CPVT_WordPlace wpBegin = wr.BeginPos;
- m_pVT->UpdateWordPlace(wpBegin);
- CPVT_WordPlace wpEnd = wr.EndPos;
- m_pVT->UpdateWordPlace(wpEnd);
- pIterator->SetAt(wpBegin);
-
- CPVT_Line lineinfo;
- do {
- if (!pIterator->GetLine(lineinfo))
- break;
- if (lineinfo.lineplace.LineCmp(wpEnd) > 0)
- break;
-
- CFX_FloatRect rcLine(lineinfo.ptLine.x,
- lineinfo.ptLine.y + lineinfo.fLineDescent,
- lineinfo.ptLine.x + lineinfo.fLineWidth,
- lineinfo.ptLine.y + lineinfo.fLineAscent);
-
- m_Refresh.Push(CPVT_WordRange(lineinfo.lineplace, lineinfo.lineEnd),
- VTToEdit(rcLine));
- } while (pIterator->NextLine());
-}
-
-void CFX_Edit::RefreshWordRange(const CPVT_WordRange& wr) {
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- CPVT_WordRange wrTemp = wr;
-
- m_pVT->UpdateWordPlace(wrTemp.BeginPos);
- m_pVT->UpdateWordPlace(wrTemp.EndPos);
- pIterator->SetAt(wrTemp.BeginPos);
-
- CPVT_Word wordinfo;
- CPVT_Line lineinfo;
- CPVT_WordPlace place;
-
- while (pIterator->NextWord()) {
- place = pIterator->GetAt();
- if (place.WordCmp(wrTemp.EndPos) > 0)
- break;
-
- pIterator->GetWord(wordinfo);
- pIterator->GetLine(lineinfo);
-
- if (place.LineCmp(wrTemp.BeginPos) == 0 ||
- place.LineCmp(wrTemp.EndPos) == 0) {
- CFX_FloatRect rcWord(wordinfo.ptWord.x,
- lineinfo.ptLine.y + lineinfo.fLineDescent,
- wordinfo.ptWord.x + wordinfo.fWidth,
- lineinfo.ptLine.y + lineinfo.fLineAscent);
-
- if (m_pNotify) {
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- CFX_FloatRect rcRefresh = VTToEdit(rcWord);
- m_pNotify->IOnInvalidateRect(&rcRefresh);
- m_bNotifyFlag = false;
- }
- }
- } else {
- CFX_FloatRect rcLine(lineinfo.ptLine.x,
- lineinfo.ptLine.y + lineinfo.fLineDescent,
- lineinfo.ptLine.x + lineinfo.fLineWidth,
- lineinfo.ptLine.y + lineinfo.fLineAscent);
-
- if (m_pNotify) {
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- CFX_FloatRect rcRefresh = VTToEdit(rcLine);
- m_pNotify->IOnInvalidateRect(&rcRefresh);
- m_bNotifyFlag = false;
- }
- }
-
- pIterator->NextLine();
- }
- }
-}
-
-void CFX_Edit::SetCaret(const CPVT_WordPlace& place) {
- m_wpOldCaret = m_wpCaret;
- m_wpCaret = place;
-}
-
-void CFX_Edit::SetCaretInfo() {
- if (m_pNotify) {
- if (!m_bNotifyFlag) {
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- pIterator->SetAt(m_wpCaret);
-
- CFX_PointF ptHead;
- CFX_PointF ptFoot;
- CPVT_Word word;
- CPVT_Line line;
- if (pIterator->GetWord(word)) {
- ptHead.x = word.ptWord.x + word.fWidth;
- ptHead.y = word.ptWord.y + word.fAscent;
- ptFoot.x = word.ptWord.x + word.fWidth;
- ptFoot.y = word.ptWord.y + word.fDescent;
- } else if (pIterator->GetLine(line)) {
- ptHead.x = line.ptLine.x;
- ptHead.y = line.ptLine.y + line.fLineAscent;
- ptFoot.x = line.ptLine.x;
- ptFoot.y = line.ptLine.y + line.fLineDescent;
- }
-
- m_bNotifyFlag = true;
- m_pNotify->IOnSetCaret(!m_SelState.IsExist(), VTToEdit(ptHead),
- VTToEdit(ptFoot), m_wpCaret);
- m_bNotifyFlag = false;
- }
- }
-}
-
-void CFX_Edit::SetCaret(int32_t nPos) {
- if (m_pVT->IsValid()) {
- SelectNone();
- SetCaret(m_pVT->WordIndexToWordPlace(nPos));
- m_SelState.Set(m_wpCaret, m_wpCaret);
-
- ScrollToCaret();
- SetCaretOrigin();
- SetCaretInfo();
- }
-}
-
-void CFX_Edit::OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl) {
- if (m_pVT->IsValid()) {
- SelectNone();
- SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
- m_SelState.Set(m_wpCaret, m_wpCaret);
-
- ScrollToCaret();
- SetCaretOrigin();
- SetCaretInfo();
- }
-}
-
-void CFX_Edit::OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl) {
- if (m_pVT->IsValid()) {
- SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
-
- if (m_wpCaret != m_wpOldCaret) {
- m_SelState.SetEndPos(m_wpCaret);
-
- ScrollToCaret();
- Refresh();
- SetCaretOrigin();
- SetCaretInfo();
- }
- }
-}
-
-void CFX_Edit::OnVK_UP(bool bShift, bool bCtrl) {
- if (m_pVT->IsValid()) {
- SetCaret(m_pVT->GetUpWordPlace(m_wpCaret, m_ptCaret));
-
- if (bShift) {
- if (m_SelState.IsExist())
- m_SelState.SetEndPos(m_wpCaret);
- else
- m_SelState.Set(m_wpOldCaret, m_wpCaret);
-
- if (m_wpOldCaret != m_wpCaret) {
- ScrollToCaret();
- Refresh();
- SetCaretInfo();
- }
- } else {
- SelectNone();
-
- ScrollToCaret();
- SetCaretInfo();
- }
- }
-}
-
-void CFX_Edit::OnVK_DOWN(bool bShift, bool bCtrl) {
- if (m_pVT->IsValid()) {
- SetCaret(m_pVT->GetDownWordPlace(m_wpCaret, m_ptCaret));
-
- if (bShift) {
- if (m_SelState.IsExist())
- m_SelState.SetEndPos(m_wpCaret);
- else
- m_SelState.Set(m_wpOldCaret, m_wpCaret);
-
- if (m_wpOldCaret != m_wpCaret) {
- ScrollToCaret();
- Refresh();
- SetCaretInfo();
- }
- } else {
- SelectNone();
-
- ScrollToCaret();
- SetCaretInfo();
- }
- }
-}
-
-void CFX_Edit::OnVK_LEFT(bool bShift, bool bCtrl) {
- if (m_pVT->IsValid()) {
- if (bShift) {
- if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
- m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret))
- SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
-
- SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
-
- if (m_SelState.IsExist())
- m_SelState.SetEndPos(m_wpCaret);
- else
- m_SelState.Set(m_wpOldCaret, m_wpCaret);
-
- if (m_wpOldCaret != m_wpCaret) {
- ScrollToCaret();
- Refresh();
- SetCaretInfo();
- }
- } else {
- if (m_SelState.IsExist()) {
- if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) < 0)
- SetCaret(m_SelState.BeginPos);
- else
- SetCaret(m_SelState.EndPos);
-
- SelectNone();
- ScrollToCaret();
- SetCaretInfo();
- } else {
- if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
- m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret))
- SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
-
- SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
-
- ScrollToCaret();
- SetCaretOrigin();
- SetCaretInfo();
- }
- }
- }
-}
-
-void CFX_Edit::OnVK_RIGHT(bool bShift, bool bCtrl) {
- if (m_pVT->IsValid()) {
- if (bShift) {
- SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
-
- if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
- m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret))
- SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
-
- if (m_SelState.IsExist())
- m_SelState.SetEndPos(m_wpCaret);
- else
- m_SelState.Set(m_wpOldCaret, m_wpCaret);
-
- if (m_wpOldCaret != m_wpCaret) {
- ScrollToCaret();
- Refresh();
- SetCaretInfo();
- }
- } else {
- if (m_SelState.IsExist()) {
- if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) > 0)
- SetCaret(m_SelState.BeginPos);
- else
- SetCaret(m_SelState.EndPos);
-
- SelectNone();
- ScrollToCaret();
- SetCaretInfo();
- } else {
- SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
-
- if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
- m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret))
- SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
-
- ScrollToCaret();
- SetCaretOrigin();
- SetCaretInfo();
- }
- }
- }
-}
-
-void CFX_Edit::OnVK_HOME(bool bShift, bool bCtrl) {
- if (m_pVT->IsValid()) {
- if (bShift) {
- if (bCtrl)
- SetCaret(m_pVT->GetBeginWordPlace());
- else
- SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
-
- if (m_SelState.IsExist())
- m_SelState.SetEndPos(m_wpCaret);
- else
- m_SelState.Set(m_wpOldCaret, m_wpCaret);
-
- ScrollToCaret();
- Refresh();
- SetCaretInfo();
- } else {
- if (m_SelState.IsExist()) {
- if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) < 0)
- SetCaret(m_SelState.BeginPos);
- else
- SetCaret(m_SelState.EndPos);
-
- SelectNone();
- ScrollToCaret();
- SetCaretInfo();
- } else {
- if (bCtrl)
- SetCaret(m_pVT->GetBeginWordPlace());
- else
- SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
-
- ScrollToCaret();
- SetCaretOrigin();
- SetCaretInfo();
- }
- }
- }
-}
-
-void CFX_Edit::OnVK_END(bool bShift, bool bCtrl) {
- if (m_pVT->IsValid()) {
- if (bShift) {
- if (bCtrl)
- SetCaret(m_pVT->GetEndWordPlace());
- else
- SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
-
- if (m_SelState.IsExist())
- m_SelState.SetEndPos(m_wpCaret);
- else
- m_SelState.Set(m_wpOldCaret, m_wpCaret);
-
- ScrollToCaret();
- Refresh();
- SetCaretInfo();
- } else {
- if (m_SelState.IsExist()) {
- if (m_SelState.BeginPos.WordCmp(m_SelState.EndPos) > 0)
- SetCaret(m_SelState.BeginPos);
- else
- SetCaret(m_SelState.EndPos);
-
- SelectNone();
- ScrollToCaret();
- SetCaretInfo();
- } else {
- if (bCtrl)
- SetCaret(m_pVT->GetEndWordPlace());
- else
- SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
-
- ScrollToCaret();
- SetCaretOrigin();
- SetCaretInfo();
- }
- }
- }
-}
-
-bool CFX_Edit::InsertWord(uint16_t word,
- int32_t charset,
- const CPVT_WordProps* pWordProps,
- bool bAddUndo,
- bool bPaint) {
- if (IsTextOverflow() || !m_pVT->IsValid())
- return false;
-
- m_pVT->UpdateWordPlace(m_wpCaret);
- SetCaret(m_pVT->InsertWord(m_wpCaret, word,
- GetCharSetFromUnicode(word, charset), pWordProps));
- m_SelState.Set(m_wpCaret, m_wpCaret);
- if (m_wpCaret == m_wpOldCaret)
- return false;
-
- if (bAddUndo && m_bEnableUndo) {
- AddEditUndoItem(pdfium::MakeUnique<CFXEU_InsertWord>(
- this, m_wpOldCaret, m_wpCaret, word, charset, pWordProps));
- }
- if (bPaint)
- PaintInsertText(m_wpOldCaret, m_wpCaret);
-
- if (m_bOprNotify && m_pOprNotify)
- m_pOprNotify->OnInsertWord(m_wpCaret, m_wpOldCaret);
-
- return true;
-}
-
-bool CFX_Edit::InsertReturn(const CPVT_SecProps* pSecProps,
- const CPVT_WordProps* pWordProps,
- bool bAddUndo,
- bool bPaint) {
- if (IsTextOverflow() || !m_pVT->IsValid())
- return false;
-
- m_pVT->UpdateWordPlace(m_wpCaret);
- SetCaret(m_pVT->InsertSection(m_wpCaret, pSecProps, pWordProps));
- m_SelState.Set(m_wpCaret, m_wpCaret);
- if (m_wpCaret == m_wpOldCaret)
- return false;
-
- if (bAddUndo && m_bEnableUndo) {
- AddEditUndoItem(pdfium::MakeUnique<CFXEU_InsertReturn>(
- this, m_wpOldCaret, m_wpCaret, pSecProps, pWordProps));
- }
- if (bPaint) {
- RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret));
- ScrollToCaret();
- Refresh();
- SetCaretOrigin();
- SetCaretInfo();
- }
- if (m_bOprNotify && m_pOprNotify)
- m_pOprNotify->OnInsertReturn(m_wpCaret, m_wpOldCaret);
-
- return true;
-}
-
-bool CFX_Edit::Backspace(bool bAddUndo, bool bPaint) {
- if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetBeginWordPlace())
- return false;
-
- CPVT_Section section;
- CPVT_Word word;
- if (bAddUndo) {
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- pIterator->SetAt(m_wpCaret);
- pIterator->GetSection(section);
- pIterator->GetWord(word);
- }
- m_pVT->UpdateWordPlace(m_wpCaret);
- SetCaret(m_pVT->BackSpaceWord(m_wpCaret));
- m_SelState.Set(m_wpCaret, m_wpCaret);
- if (m_wpCaret == m_wpOldCaret)
- return false;
-
- if (bAddUndo && m_bEnableUndo) {
- if (m_wpCaret.SecCmp(m_wpOldCaret) != 0) {
- AddEditUndoItem(pdfium::MakeUnique<CFXEU_Backspace>(
- this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset,
- section.SecProps, section.WordProps));
- } else {
- AddEditUndoItem(pdfium::MakeUnique<CFXEU_Backspace>(
- this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset,
- section.SecProps, word.WordProps));
- }
- }
- if (bPaint) {
- RearrangePart(CPVT_WordRange(m_wpCaret, m_wpOldCaret));
- ScrollToCaret();
- Refresh();
- SetCaretOrigin();
- SetCaretInfo();
- }
- if (m_bOprNotify && m_pOprNotify)
- m_pOprNotify->OnBackSpace(m_wpCaret, m_wpOldCaret);
-
- return true;
-}
-
-bool CFX_Edit::Delete(bool bAddUndo, bool bPaint) {
- if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetEndWordPlace())
- return false;
-
- CPVT_Section section;
- CPVT_Word word;
- if (bAddUndo) {
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- pIterator->SetAt(m_pVT->GetNextWordPlace(m_wpCaret));
- pIterator->GetSection(section);
- pIterator->GetWord(word);
- }
- m_pVT->UpdateWordPlace(m_wpCaret);
- bool bSecEnd = (m_wpCaret == m_pVT->GetSectionEndPlace(m_wpCaret));
- SetCaret(m_pVT->DeleteWord(m_wpCaret));
- m_SelState.Set(m_wpCaret, m_wpCaret);
- if (bAddUndo && m_bEnableUndo) {
- if (bSecEnd) {
- AddEditUndoItem(pdfium::MakeUnique<CFXEU_Delete>(
- this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset,
- section.SecProps, section.WordProps, bSecEnd));
- } else {
- AddEditUndoItem(pdfium::MakeUnique<CFXEU_Delete>(
- this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset,
- section.SecProps, word.WordProps, bSecEnd));
- }
- }
- if (bPaint) {
- RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret));
- ScrollToCaret();
- Refresh();
- SetCaretOrigin();
- SetCaretInfo();
- }
- if (m_bOprNotify && m_pOprNotify)
- m_pOprNotify->OnDelete(m_wpCaret, m_wpOldCaret);
-
- return true;
-}
-
-bool CFX_Edit::Empty() {
- if (m_pVT->IsValid()) {
- m_pVT->DeleteWords(GetWholeWordRange());
- SetCaret(m_pVT->GetBeginWordPlace());
-
- return true;
- }
-
- return false;
-}
-
-bool CFX_Edit::Clear(bool bAddUndo, bool bPaint) {
- if (!m_pVT->IsValid() || !m_SelState.IsExist())
- return false;
-
- CPVT_WordRange range = m_SelState.ConvertToWordRange();
- if (bAddUndo && m_bEnableUndo)
- AddEditUndoItem(pdfium::MakeUnique<CFXEU_Clear>(this, range, GetSelText()));
-
- SelectNone();
- SetCaret(m_pVT->DeleteWords(range));
- m_SelState.Set(m_wpCaret, m_wpCaret);
- if (bPaint) {
- RearrangePart(range);
- ScrollToCaret();
- Refresh();
- SetCaretOrigin();
- SetCaretInfo();
- }
- if (m_bOprNotify && m_pOprNotify)
- m_pOprNotify->OnClear(m_wpCaret, m_wpOldCaret);
-
- return true;
-}
-
-bool CFX_Edit::InsertText(const CFX_WideString& sText,
- int32_t charset,
- bool bAddUndo,
- bool bPaint) {
- if (IsTextOverflow())
- return false;
-
- m_pVT->UpdateWordPlace(m_wpCaret);
- SetCaret(DoInsertText(m_wpCaret, sText, charset));
- m_SelState.Set(m_wpCaret, m_wpCaret);
- if (m_wpCaret == m_wpOldCaret)
- return false;
-
- if (bAddUndo && m_bEnableUndo) {
- AddEditUndoItem(pdfium::MakeUnique<CFXEU_InsertText>(
- this, m_wpOldCaret, m_wpCaret, sText, charset));
- }
- if (bPaint)
- PaintInsertText(m_wpOldCaret, m_wpCaret);
-
- if (m_bOprNotify && m_pOprNotify)
- m_pOprNotify->OnInsertText(m_wpCaret, m_wpOldCaret);
-
- return true;
-}
-
-void CFX_Edit::PaintInsertText(const CPVT_WordPlace& wpOld,
- const CPVT_WordPlace& wpNew) {
- if (m_pVT->IsValid()) {
- RearrangePart(CPVT_WordRange(wpOld, wpNew));
- ScrollToCaret();
- Refresh();
- SetCaretOrigin();
- SetCaretInfo();
- }
-}
-
-bool CFX_Edit::Redo() {
- if (m_bEnableUndo) {
- if (m_Undo.CanRedo()) {
- m_Undo.Redo();
- return true;
- }
- }
-
- return false;
-}
-
-bool CFX_Edit::Undo() {
- if (m_bEnableUndo) {
- if (m_Undo.CanUndo()) {
- m_Undo.Undo();
- return true;
- }
- }
-
- return false;
-}
-
-void CFX_Edit::SetCaretOrigin() {
- if (!m_pVT->IsValid())
- return;
-
- CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
- pIterator->SetAt(m_wpCaret);
- CPVT_Word word;
- CPVT_Line line;
- if (pIterator->GetWord(word)) {
- m_ptCaret.x = word.ptWord.x + word.fWidth;
- m_ptCaret.y = word.ptWord.y;
- } else if (pIterator->GetLine(line)) {
- m_ptCaret.x = line.ptLine.x;
- m_ptCaret.y = line.ptLine.y;
- }
-}
-
-int32_t CFX_Edit::WordPlaceToWordIndex(const CPVT_WordPlace& place) const {
- if (m_pVT->IsValid())
- return m_pVT->WordPlaceToWordIndex(place);
-
- return -1;
-}
-
-CPVT_WordPlace CFX_Edit::WordIndexToWordPlace(int32_t index) const {
- if (m_pVT->IsValid())
- return m_pVT->WordIndexToWordPlace(index);
-
- return CPVT_WordPlace();
-}
-
-bool CFX_Edit::IsTextFull() const {
- int32_t nTotalWords = m_pVT->GetTotalWords();
- int32_t nLimitChar = m_pVT->GetLimitChar();
- int32_t nCharArray = m_pVT->GetCharArray();
-
- return IsTextOverflow() || (nLimitChar > 0 && nTotalWords >= nLimitChar) ||
- (nCharArray > 0 && nTotalWords >= nCharArray);
-}
-
-bool CFX_Edit::IsTextOverflow() const {
- if (!m_bEnableScroll && !m_bEnableOverflow) {
- CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
- CFX_FloatRect rcContent = m_pVT->GetContentRect();
-
- if (m_pVT->IsMultiLine() && GetTotalLines() > 1 &&
- IsFloatBigger(rcContent.Height(), rcPlate.Height())) {
- return true;
- }
-
- if (IsFloatBigger(rcContent.Width(), rcPlate.Width()))
- return true;
- }
-
- return false;
-}
-
-bool CFX_Edit::CanUndo() const {
- if (m_bEnableUndo) {
- return m_Undo.CanUndo();
- }
-
- return false;
-}
-
-bool CFX_Edit::CanRedo() const {
- if (m_bEnableUndo) {
- return m_Undo.CanRedo();
- }
-
- return false;
-}
-
-void CFX_Edit::EnableRefresh(bool bRefresh) {
- m_bEnableRefresh = bRefresh;
-}
-
-void CFX_Edit::EnableUndo(bool bUndo) {
- m_bEnableUndo = bUndo;
-}
-
-void CFX_Edit::EnableOprNotify(bool bNotify) {
- m_bOprNotify = bNotify;
-}
-
-CPVT_WordPlace CFX_Edit::DoInsertText(const CPVT_WordPlace& place,
- const CFX_WideString& sText,
- int32_t charset) {
- CPVT_WordPlace wp = place;
-
- if (m_pVT->IsValid()) {
- for (int32_t i = 0, sz = sText.GetLength(); i < sz; i++) {
- uint16_t word = sText[i];
- switch (word) {
- case 0x0D:
- wp = m_pVT->InsertSection(wp, nullptr, nullptr);
- if (sText[i + 1] == 0x0A)
- i++;
- break;
- case 0x0A:
- wp = m_pVT->InsertSection(wp, nullptr, nullptr);
- if (sText[i + 1] == 0x0D)
- i++;
- break;
- case 0x09:
- word = 0x20;
- default:
- wp = m_pVT->InsertWord(wp, word, GetCharSetFromUnicode(word, charset),
- nullptr);
- break;
- }
- }
- }
-
- return wp;
-}
-
-int32_t CFX_Edit::GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset) {
- if (IPVT_FontMap* pFontMap = GetFontMap())
- return pFontMap->CharSetFromUnicode(word, nOldCharset);
- return nOldCharset;
-}
-
-void CFX_Edit::AddEditUndoItem(
- std::unique_ptr<CFX_Edit_UndoItem> pEditUndoItem) {
- if (m_pGroupUndoItem)
- m_pGroupUndoItem->AddUndoItem(std::move(pEditUndoItem));
- else
- m_Undo.AddItem(std::move(pEditUndoItem));
-}
-
-CFX_Edit_LineRectArray::CFX_Edit_LineRectArray() {}
-
-CFX_Edit_LineRectArray::~CFX_Edit_LineRectArray() {}
-
-void CFX_Edit_LineRectArray::operator=(CFX_Edit_LineRectArray&& that) {
- m_LineRects = std::move(that.m_LineRects);
-}
-
-void CFX_Edit_LineRectArray::Add(const CPVT_WordRange& wrLine,
- const CFX_FloatRect& rcLine) {
- m_LineRects.push_back(pdfium::MakeUnique<CFX_Edit_LineRect>(wrLine, rcLine));
-}
-
-int32_t CFX_Edit_LineRectArray::GetSize() const {
- return pdfium::CollectionSize<int32_t>(m_LineRects);
-}
-
-CFX_Edit_LineRect* CFX_Edit_LineRectArray::GetAt(int32_t nIndex) const {
- if (nIndex < 0 || nIndex >= GetSize())
- return nullptr;
-
- return m_LineRects[nIndex].get();
-}
-
-CFX_Edit_Select::CFX_Edit_Select() {}
-
-CFX_Edit_Select::CFX_Edit_Select(const CPVT_WordPlace& begin,
- const CPVT_WordPlace& end) {
- Set(begin, end);
-}
-
-CFX_Edit_Select::CFX_Edit_Select(const CPVT_WordRange& range) {
- Set(range.BeginPos, range.EndPos);
-}
-
-CPVT_WordRange CFX_Edit_Select::ConvertToWordRange() const {
- return CPVT_WordRange(BeginPos, EndPos);
-}
-
-void CFX_Edit_Select::Default() {
- BeginPos.Default();
- EndPos.Default();
-}
-
-void CFX_Edit_Select::Set(const CPVT_WordPlace& begin,
- const CPVT_WordPlace& end) {
- BeginPos = begin;
- EndPos = end;
-}
-
-void CFX_Edit_Select::SetBeginPos(const CPVT_WordPlace& begin) {
- BeginPos = begin;
-}
-
-void CFX_Edit_Select::SetEndPos(const CPVT_WordPlace& end) {
- EndPos = end;
-}
-
-bool CFX_Edit_Select::IsExist() const {
- return BeginPos != EndPos;
-}
-
-CFX_Edit_RectArray::CFX_Edit_RectArray() {}
-
-CFX_Edit_RectArray::~CFX_Edit_RectArray() {}
-
-void CFX_Edit_RectArray::Clear() {
- m_Rects.clear();
-}
-
-void CFX_Edit_RectArray::Add(const CFX_FloatRect& rect) {
- // check for overlapped area
- for (const auto& pRect : m_Rects) {
- if (pRect && pRect->Contains(rect))
- return;
- }
- m_Rects.push_back(pdfium::MakeUnique<CFX_FloatRect>(rect));
-}
-
-int32_t CFX_Edit_RectArray::GetSize() const {
- return pdfium::CollectionSize<int32_t>(m_Rects);
-}
-
-CFX_FloatRect* CFX_Edit_RectArray::GetAt(int32_t nIndex) const {
- if (nIndex < 0 || nIndex >= GetSize())
- return nullptr;
-
- return m_Rects[nIndex].get();
-}
diff --git a/fpdfsdk/fxedit/fxet_edit.h b/fpdfsdk/fxedit/fxet_edit.h
deleted file mode 100644
index ab83af2..0000000
--- a/fpdfsdk/fxedit/fxet_edit.h
+++ /dev/null
@@ -1,545 +0,0 @@
-// Copyright 2014 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_FXEDIT_FXET_EDIT_H_
-#define FPDFSDK_FXEDIT_FXET_EDIT_H_
-
-#include <deque>
-#include <memory>
-#include <vector>
-
-#include "core/fpdfdoc/cpvt_secprops.h"
-#include "core/fpdfdoc/cpvt_wordprops.h"
-#include "fpdfsdk/fxedit/fx_edit.h"
-
-class CFFL_FormFiller;
-class CFX_Edit;
-class CFX_Edit_Iterator;
-class CFX_Edit_Provider;
-class CFX_RenderDevice;
-class CFX_SystemHandler;
-class CPDF_PageObjectHolder;
-class CPDF_TextObject;
-class CPWL_Edit;
-class CPWL_EditCtrl;
-
-class IFX_Edit_UndoItem;
-
-struct CFX_Edit_LineRect {
- CFX_Edit_LineRect(const CPVT_WordRange& wrLine, const CFX_FloatRect& rcLine)
- : m_wrLine(wrLine), m_rcLine(rcLine) {}
-
- CPVT_WordRange m_wrLine;
- CFX_FloatRect m_rcLine;
-};
-
-class CFX_Edit_LineRectArray {
- public:
- CFX_Edit_LineRectArray();
- virtual ~CFX_Edit_LineRectArray();
-
- void operator=(CFX_Edit_LineRectArray&& rects);
- void Add(const CPVT_WordRange& wrLine, const CFX_FloatRect& rcLine);
-
- int32_t GetSize() const;
- CFX_Edit_LineRect* GetAt(int32_t nIndex) const;
-
- private:
- std::vector<std::unique_ptr<CFX_Edit_LineRect>> m_LineRects;
-};
-
-class CFX_Edit_RectArray {
- public:
- CFX_Edit_RectArray();
- virtual ~CFX_Edit_RectArray();
-
- void Clear();
- void Add(const CFX_FloatRect& rect);
-
- int32_t GetSize() const;
- CFX_FloatRect* GetAt(int32_t nIndex) const;
-
- private:
- std::vector<std::unique_ptr<CFX_FloatRect>> m_Rects;
-};
-
-class CFX_Edit_Refresh {
- public:
- CFX_Edit_Refresh();
- virtual ~CFX_Edit_Refresh();
-
- void BeginRefresh();
- void Push(const CPVT_WordRange& linerange, const CFX_FloatRect& rect);
- void NoAnalyse();
- void AddRefresh(const CFX_FloatRect& rect);
- const CFX_Edit_RectArray* GetRefreshRects() const;
- void EndRefresh();
-
- private:
- CFX_Edit_LineRectArray m_NewLineRects;
- CFX_Edit_LineRectArray m_OldLineRects;
- CFX_Edit_RectArray m_RefreshRects;
-};
-
-class CFX_Edit_Select {
- public:
- CFX_Edit_Select();
- CFX_Edit_Select(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
- explicit CFX_Edit_Select(const CPVT_WordRange& range);
-
- void Default();
- void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
- void SetBeginPos(const CPVT_WordPlace& begin);
- void SetEndPos(const CPVT_WordPlace& end);
-
- CPVT_WordRange ConvertToWordRange() const;
- bool IsExist() const;
-
- CPVT_WordPlace BeginPos;
- CPVT_WordPlace EndPos;
-};
-
-class CFX_Edit_Undo {
- public:
- explicit CFX_Edit_Undo(int32_t nBufsize);
- virtual ~CFX_Edit_Undo();
-
- void AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem);
- void Undo();
- void Redo();
- bool CanUndo() const;
- bool CanRedo() const;
- bool IsModified() const;
- void Reset();
-
- private:
- void RemoveHeads();
- void RemoveTails();
-
- std::deque<std::unique_ptr<IFX_Edit_UndoItem>> m_UndoItemStack;
- size_t m_nCurUndoPos;
- size_t m_nBufSize;
- bool m_bModified;
- bool m_bVirgin;
- bool m_bWorking;
-};
-
-class IFX_Edit_UndoItem {
- public:
- virtual ~IFX_Edit_UndoItem() {}
-
- virtual void Undo() = 0;
- virtual void Redo() = 0;
- virtual CFX_WideString GetUndoTitle() const = 0;
-};
-
-class CFX_Edit_UndoItem : public IFX_Edit_UndoItem {
- public:
- CFX_Edit_UndoItem();
- ~CFX_Edit_UndoItem() override;
-
- CFX_WideString GetUndoTitle() const override;
-
- void SetFirst(bool bFirst);
- void SetLast(bool bLast);
- bool IsLast();
-
- private:
- bool m_bFirst;
- bool m_bLast;
-};
-
-class CFX_Edit_GroupUndoItem : public IFX_Edit_UndoItem {
- public:
- explicit CFX_Edit_GroupUndoItem(const CFX_WideString& sTitle);
- ~CFX_Edit_GroupUndoItem() override;
-
- // IFX_Edit_UndoItem
- void Undo() override;
- void Redo() override;
- CFX_WideString GetUndoTitle() const override;
-
- void AddUndoItem(std::unique_ptr<CFX_Edit_UndoItem> pUndoItem);
- void UpdateItems();
-
- private:
- CFX_WideString m_sTitle;
- std::vector<std::unique_ptr<CFX_Edit_UndoItem>> m_Items;
-};
-
-class CFXEU_InsertWord : public CFX_Edit_UndoItem {
- public:
- CFXEU_InsertWord(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- uint16_t word,
- int32_t charset,
- const CPVT_WordProps* pWordProps);
- ~CFXEU_InsertWord() override;
-
- // CFX_Edit_UndoItem
- void Redo() override;
- void Undo() override;
-
- private:
- CFX_Edit* m_pEdit;
-
- CPVT_WordPlace m_wpOld;
- CPVT_WordPlace m_wpNew;
- uint16_t m_Word;
- int32_t m_nCharset;
- CPVT_WordProps m_WordProps;
-};
-
-class CFXEU_InsertReturn : public CFX_Edit_UndoItem {
- public:
- CFXEU_InsertReturn(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- const CPVT_SecProps* pSecProps,
- const CPVT_WordProps* pWordProps);
- ~CFXEU_InsertReturn() override;
-
- // CFX_Edit_UndoItem
- void Redo() override;
- void Undo() override;
-
- private:
- CFX_Edit* m_pEdit;
-
- CPVT_WordPlace m_wpOld;
- CPVT_WordPlace m_wpNew;
- CPVT_SecProps m_SecProps;
- CPVT_WordProps m_WordProps;
-};
-
-class CFXEU_Backspace : public CFX_Edit_UndoItem {
- public:
- CFXEU_Backspace(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- uint16_t word,
- int32_t charset,
- const CPVT_SecProps& SecProps,
- const CPVT_WordProps& WordProps);
- ~CFXEU_Backspace() override;
-
- // CFX_Edit_UndoItem
- void Redo() override;
- void Undo() override;
-
- private:
- CFX_Edit* m_pEdit;
-
- CPVT_WordPlace m_wpOld;
- CPVT_WordPlace m_wpNew;
- uint16_t m_Word;
- int32_t m_nCharset;
- CPVT_SecProps m_SecProps;
- CPVT_WordProps m_WordProps;
-};
-
-class CFXEU_Delete : public CFX_Edit_UndoItem {
- public:
- CFXEU_Delete(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- uint16_t word,
- int32_t charset,
- const CPVT_SecProps& SecProps,
- const CPVT_WordProps& WordProps,
- bool bSecEnd);
- ~CFXEU_Delete() override;
-
- // CFX_Edit_UndoItem
- void Redo() override;
- void Undo() override;
-
- private:
- CFX_Edit* m_pEdit;
-
- CPVT_WordPlace m_wpOld;
- CPVT_WordPlace m_wpNew;
- uint16_t m_Word;
- int32_t m_nCharset;
- CPVT_SecProps m_SecProps;
- CPVT_WordProps m_WordProps;
- bool m_bSecEnd;
-};
-
-class CFXEU_Clear : public CFX_Edit_UndoItem {
- public:
- CFXEU_Clear(CFX_Edit* pEdit,
- const CPVT_WordRange& wrSel,
- const CFX_WideString& swText);
- ~CFXEU_Clear() override;
-
- // CFX_Edit_UndoItem
- void Redo() override;
- void Undo() override;
-
- private:
- CFX_Edit* m_pEdit;
-
- CPVT_WordRange m_wrSel;
- CFX_WideString m_swText;
-};
-
-class CFXEU_InsertText : public CFX_Edit_UndoItem {
- public:
- CFXEU_InsertText(CFX_Edit* pEdit,
- const CPVT_WordPlace& wpOldPlace,
- const CPVT_WordPlace& wpNewPlace,
- const CFX_WideString& swText,
- int32_t charset);
- ~CFXEU_InsertText() override;
-
- // CFX_Edit_UndoItem
- void Redo() override;
- void Undo() override;
-
- private:
- CFX_Edit* m_pEdit;
-
- CPVT_WordPlace m_wpOld;
- CPVT_WordPlace m_wpNew;
- CFX_WideString m_swText;
- int32_t m_nCharset;
-};
-
-class CFX_Edit {
- public:
- static CFX_ByteString GetEditAppearanceStream(CFX_Edit* pEdit,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange,
- bool bContinuous,
- uint16_t SubWord);
- static CFX_ByteString GetSelectAppearanceStream(CFX_Edit* pEdit,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange);
- static void DrawEdit(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- CFX_Edit* pEdit,
- FX_COLORREF crTextFill,
- const CFX_FloatRect& rcClip,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange,
- CFX_SystemHandler* pSystemHandler,
- CFFL_FormFiller* pFFLData);
-
- CFX_Edit();
- ~CFX_Edit();
-
- void SetFontMap(IPVT_FontMap* pFontMap);
- void SetNotify(CPWL_EditCtrl* pNotify);
- void SetOprNotify(CPWL_Edit* pOprNotify);
-
- // Returns an iterator for the contents. Should not be released.
- CFX_Edit_Iterator* GetIterator();
- IPVT_FontMap* GetFontMap();
- void Initialize();
-
- // Set the bounding box of the text area.
- void SetPlateRect(const CFX_FloatRect& rect);
- void SetScrollPos(const CFX_PointF& point);
-
- // Set the horizontal text alignment. (nFormat [0:left, 1:middle, 2:right])
- void SetAlignmentH(int32_t nFormat, bool bPaint);
- // Set the vertical text alignment. (nFormat [0:left, 1:middle, 2:right])
- void SetAlignmentV(int32_t nFormat, bool bPaint);
-
- // Set the substitution character for hidden text.
- void SetPasswordChar(uint16_t wSubWord, bool bPaint);
-
- // Set the maximum number of words in the text.
- void SetLimitChar(int32_t nLimitChar);
- void SetCharArray(int32_t nCharArray);
- void SetCharSpace(FX_FLOAT fCharSpace);
- void SetMultiLine(bool bMultiLine, bool bPaint);
- void SetAutoReturn(bool bAuto, bool bPaint);
- void SetAutoFontSize(bool bAuto, bool bPaint);
- void SetAutoScroll(bool bAuto, bool bPaint);
- void SetFontSize(FX_FLOAT fFontSize);
- void SetTextOverflow(bool bAllowed, bool bPaint);
- void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl);
- void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl);
- void OnVK_UP(bool bShift, bool bCtrl);
- void OnVK_DOWN(bool bShift, bool bCtrl);
- void OnVK_LEFT(bool bShift, bool bCtrl);
- void OnVK_RIGHT(bool bShift, bool bCtrl);
- void OnVK_HOME(bool bShift, bool bCtrl);
- void OnVK_END(bool bShift, bool bCtrl);
- void SetText(const CFX_WideString& sText);
- bool InsertWord(uint16_t word, int32_t charset);
- bool InsertReturn();
- bool Backspace();
- bool Delete();
- bool Clear();
- bool InsertText(const CFX_WideString& sText, int32_t charset);
- bool Redo();
- bool Undo();
- int32_t WordPlaceToWordIndex(const CPVT_WordPlace& place) const;
- CPVT_WordPlace WordIndexToWordPlace(int32_t index) const;
- CPVT_WordPlace SearchWordPlace(const CFX_PointF& point) const;
- int32_t GetCaret() const;
- CPVT_WordPlace GetCaretWordPlace() const;
- CFX_WideString GetSelText() const;
- CFX_WideString GetText() const;
- FX_FLOAT GetFontSize() const;
- uint16_t GetPasswordChar() const;
- CFX_PointF GetScrollPos() const;
- int32_t GetCharArray() const;
- CFX_FloatRect GetContentRect() const;
- CFX_WideString GetRangeText(const CPVT_WordRange& range) const;
- int32_t GetHorzScale() const;
- FX_FLOAT GetCharSpace() const;
- int32_t GetTotalWords() const;
- void SetSel(int32_t nStartChar, int32_t nEndChar);
- void GetSel(int32_t& nStartChar, int32_t& nEndChar) const;
- void SelectAll();
- void SelectNone();
- bool IsSelected() const;
- void Paint();
- void EnableRefresh(bool bRefresh);
- void RefreshWordRange(const CPVT_WordRange& wr);
- void SetCaret(int32_t nPos);
- CPVT_WordRange GetWholeWordRange() const;
- CPVT_WordRange GetSelectWordRange() const;
- void EnableUndo(bool bUndo);
- void EnableOprNotify(bool bNotify);
- bool IsTextFull() const;
- bool IsTextOverflow() const;
- bool CanUndo() const;
- bool CanRedo() const;
- CPVT_WordRange GetVisibleWordRange() const;
-
- bool Empty();
-
- CPVT_WordPlace DoInsertText(const CPVT_WordPlace& place,
- const CFX_WideString& sText,
- int32_t charset);
- int32_t GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset);
-
- int32_t GetTotalLines() const;
-
- private:
- friend class CFX_Edit_Iterator;
- friend class CFXEU_InsertWord;
- friend class CFXEU_InsertReturn;
- friend class CFXEU_Backspace;
- friend class CFXEU_Delete;
- friend class CFXEU_Clear;
- friend class CFXEU_InsertText;
-
- void SetSel(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
-
- void RearrangeAll();
- void RearrangePart(const CPVT_WordRange& range);
- void ScrollToCaret();
- void SetScrollInfo();
- void SetScrollPosX(FX_FLOAT fx);
- void SetScrollPosY(FX_FLOAT fy);
- void SetScrollLimit();
- void SetContentChanged();
-
- bool InsertWord(uint16_t word,
- int32_t charset,
- const CPVT_WordProps* pWordProps,
- bool bAddUndo,
- bool bPaint);
- bool InsertReturn(const CPVT_SecProps* pSecProps,
- const CPVT_WordProps* pWordProps,
- bool bAddUndo,
- bool bPaint);
- bool Backspace(bool bAddUndo, bool bPaint);
- bool Delete(bool bAddUndo, bool bPaint);
- bool Clear(bool bAddUndo, bool bPaint);
- bool InsertText(const CFX_WideString& sText,
- int32_t charset,
- bool bAddUndo,
- bool bPaint);
- void PaintInsertText(const CPVT_WordPlace& wpOld,
- const CPVT_WordPlace& wpNew);
-
- inline CFX_PointF VTToEdit(const CFX_PointF& point) const;
- inline CFX_PointF EditToVT(const CFX_PointF& point) const;
- inline CFX_FloatRect VTToEdit(const CFX_FloatRect& rect) const;
-
- void Refresh();
- void RefreshPushLineRects(const CPVT_WordRange& wr);
-
- void SetCaret(const CPVT_WordPlace& place);
- void SetCaretInfo();
- void SetCaretOrigin();
-
- void AddEditUndoItem(std::unique_ptr<CFX_Edit_UndoItem> pEditUndoItem);
-
- private:
- std::unique_ptr<CPDF_VariableText> m_pVT;
- CPWL_EditCtrl* m_pNotify;
- CPWL_Edit* m_pOprNotify;
- std::unique_ptr<CFX_Edit_Provider> m_pVTProvider;
- CPVT_WordPlace m_wpCaret;
- CPVT_WordPlace m_wpOldCaret;
- CFX_Edit_Select m_SelState;
- CFX_PointF m_ptScrollPos;
- CFX_PointF m_ptRefreshScrollPos;
- bool m_bEnableScroll;
- std::unique_ptr<CFX_Edit_Iterator> m_pIterator;
- CFX_Edit_Refresh m_Refresh;
- CFX_PointF m_ptCaret;
- CFX_Edit_Undo m_Undo;
- int32_t m_nAlignment;
- bool m_bNotifyFlag;
- bool m_bEnableOverflow;
- bool m_bEnableRefresh;
- CFX_FloatRect m_rcOldContent;
- bool m_bEnableUndo;
- bool m_bOprNotify;
- CFX_Edit_GroupUndoItem* m_pGroupUndoItem;
-};
-
-class CFX_Edit_Iterator {
- public:
- CFX_Edit_Iterator(CFX_Edit* pEdit, CPDF_VariableText::Iterator* pVTIterator);
- ~CFX_Edit_Iterator();
-
- bool NextWord();
- bool PrevWord();
- bool GetWord(CPVT_Word& word) const;
- bool GetLine(CPVT_Line& line) const;
- bool GetSection(CPVT_Section& section) const;
- void SetAt(int32_t nWordIndex);
- void SetAt(const CPVT_WordPlace& place);
- const CPVT_WordPlace& GetAt() const;
-
- private:
- CFX_Edit* m_pEdit;
- CPDF_VariableText::Iterator* m_pVTIterator;
-};
-
-class CFX_Edit_Provider : public CPDF_VariableText::Provider {
- public:
- explicit CFX_Edit_Provider(IPVT_FontMap* pFontMap);
- ~CFX_Edit_Provider() override;
-
- IPVT_FontMap* GetFontMap();
-
- // CPDF_VariableText::Provider:
- int32_t GetCharWidth(int32_t nFontIndex, uint16_t word) override;
- int32_t GetTypeAscent(int32_t nFontIndex) override;
- int32_t GetTypeDescent(int32_t nFontIndex) override;
- int32_t GetWordFontIndex(uint16_t word,
- int32_t charset,
- int32_t nFontIndex) override;
- int32_t GetDefaultFontIndex() override;
- bool IsLatinWord(uint16_t word) override;
-
- private:
- IPVT_FontMap* m_pFontMap;
-};
-
-#endif // FPDFSDK_FXEDIT_FXET_EDIT_H_
diff --git a/fpdfsdk/fxedit/fxet_list.cpp b/fpdfsdk/fxedit/fxet_list.cpp
deleted file mode 100644
index 39877c9..0000000
--- a/fpdfsdk/fxedit/fxet_list.cpp
+++ /dev/null
@@ -1,784 +0,0 @@
-// Copyright 2014 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/fxedit/fxet_list.h"
-
-#include "core/fpdfdoc/cpvt_word.h"
-#include "fpdfsdk/fxedit/fxet_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_ListBox.h"
-
-CFX_ListItem::CFX_ListItem()
- : m_pEdit(new CFX_Edit),
- m_bSelected(false),
- m_rcListItem(0.0f, 0.0f, 0.0f, 0.0f) {
- m_pEdit->SetAlignmentV(1, true);
- m_pEdit->Initialize();
-}
-
-CFX_ListItem::~CFX_ListItem() {
-}
-
-void CFX_ListItem::SetFontMap(IPVT_FontMap* pFontMap) {
- m_pEdit->SetFontMap(pFontMap);
-}
-
-CFX_Edit* CFX_ListItem::GetEdit() const {
- return m_pEdit.get();
-}
-
-CFX_Edit_Iterator* CFX_ListItem::GetIterator() const {
- return m_pEdit->GetIterator();
-}
-
-void CFX_ListItem::SetRect(const CLST_Rect& rect) {
- m_rcListItem = rect;
-}
-
-CLST_Rect CFX_ListItem::GetRect() const {
- return m_rcListItem;
-}
-
-bool CFX_ListItem::IsSelected() const {
- return m_bSelected;
-}
-
-void CFX_ListItem::SetSelect(bool bSelected) {
- m_bSelected = bSelected;
-}
-
-void CFX_ListItem::SetText(const CFX_WideString& text) {
- m_pEdit->SetText(text);
-}
-
-void CFX_ListItem::SetFontSize(FX_FLOAT fFontSize) {
- m_pEdit->SetFontSize(fFontSize);
-}
-
-FX_FLOAT CFX_ListItem::GetItemHeight() const {
- return m_pEdit->GetContentRect().Height();
-}
-
-uint16_t CFX_ListItem::GetFirstChar() const {
- CPVT_Word word;
- CFX_Edit_Iterator* pIterator = GetIterator();
- pIterator->SetAt(1);
- pIterator->GetWord(word);
- return word.Word;
-}
-
-CFX_WideString CFX_ListItem::GetText() const {
- return m_pEdit->GetText();
-}
-
-CFX_ListContainer::CFX_ListContainer() {}
-
-CFX_ListContainer::~CFX_ListContainer() {}
-
-void CFX_ListContainer::SetPlateRect(const CFX_FloatRect& rect) {
- m_rcPlate = rect;
-}
-
-CPLST_Select::CPLST_Select() {}
-
-CPLST_Select::~CPLST_Select() {
- for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++)
- delete m_aItems.GetAt(i);
-
- m_aItems.RemoveAll();
-}
-
-void CPLST_Select::Add(int32_t nItemIndex) {
- int32_t nIndex = Find(nItemIndex);
-
- if (nIndex < 0) {
- m_aItems.Add(new CPLST_Select_Item(nItemIndex, 1));
- } else {
- if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) {
- pItem->nState = 1;
- }
- }
-}
-
-void CPLST_Select::Add(int32_t nBeginIndex, int32_t nEndIndex) {
- if (nBeginIndex > nEndIndex) {
- int32_t nTemp = nEndIndex;
- nEndIndex = nBeginIndex;
- nBeginIndex = nTemp;
- }
-
- for (int32_t i = nBeginIndex; i <= nEndIndex; i++)
- Add(i);
-}
-
-void CPLST_Select::Sub(int32_t nItemIndex) {
- for (int32_t i = m_aItems.GetSize() - 1; i >= 0; i--) {
- if (CPLST_Select_Item* pItem = m_aItems.GetAt(i))
- if (pItem->nItemIndex == nItemIndex)
- pItem->nState = -1;
- }
-}
-
-void CPLST_Select::Sub(int32_t nBeginIndex, int32_t nEndIndex) {
- if (nBeginIndex > nEndIndex) {
- int32_t nTemp = nEndIndex;
- nEndIndex = nBeginIndex;
- nBeginIndex = nTemp;
- }
-
- for (int32_t i = nBeginIndex; i <= nEndIndex; i++)
- Sub(i);
-}
-
-int32_t CPLST_Select::Find(int32_t nItemIndex) const {
- for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) {
- if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) {
- if (pItem->nItemIndex == nItemIndex)
- return i;
- }
- }
-
- return -1;
-}
-
-bool CPLST_Select::IsExist(int32_t nItemIndex) const {
- return Find(nItemIndex) >= 0;
-}
-
-int32_t CPLST_Select::GetCount() const {
- return m_aItems.GetSize();
-}
-
-int32_t CPLST_Select::GetItemIndex(int32_t nIndex) const {
- if (nIndex >= 0 && nIndex < m_aItems.GetSize())
- if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex))
- return pItem->nItemIndex;
-
- return -1;
-}
-
-int32_t CPLST_Select::GetState(int32_t nIndex) const {
- if (nIndex >= 0 && nIndex < m_aItems.GetSize())
- if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex))
- return pItem->nState;
-
- return 0;
-}
-
-void CPLST_Select::DeselectAll() {
- for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) {
- if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) {
- pItem->nState = -1;
- }
- }
-}
-
-void CPLST_Select::Done() {
- for (int32_t i = m_aItems.GetSize() - 1; i >= 0; i--) {
- if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) {
- if (pItem->nState == -1) {
- delete pItem;
- m_aItems.RemoveAt(i);
- } else {
- pItem->nState = 0;
- }
- }
- }
-}
-
-CFX_ListCtrl::CFX_ListCtrl()
- : m_pNotify(nullptr),
- m_bNotifyFlag(false),
- m_nSelItem(-1),
- m_nFootIndex(-1),
- m_bCtrlSel(false),
- m_nCaretIndex(-1),
- m_fFontSize(0.0f),
- m_pFontMap(nullptr),
- m_bMultiple(false) {}
-
-CFX_ListCtrl::~CFX_ListCtrl() {
- Empty();
-}
-
-void CFX_ListCtrl::SetNotify(CPWL_List_Notify* pNotify) {
- m_pNotify = pNotify;
-}
-
-CFX_PointF CFX_ListCtrl::InToOut(const CFX_PointF& point) const {
- CFX_FloatRect rcPlate = GetPlateRect();
- return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left),
- point.y - (m_ptScrollPos.y - rcPlate.top));
-}
-
-CFX_PointF CFX_ListCtrl::OutToIn(const CFX_PointF& point) const {
- CFX_FloatRect rcPlate = GetPlateRect();
- return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left),
- point.y + (m_ptScrollPos.y - rcPlate.top));
-}
-
-CFX_FloatRect CFX_ListCtrl::InToOut(const CFX_FloatRect& rect) const {
- CFX_PointF ptLeftBottom = InToOut(CFX_PointF(rect.left, rect.bottom));
- CFX_PointF ptRightTop = InToOut(CFX_PointF(rect.right, rect.top));
- return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
- ptRightTop.y);
-}
-
-CFX_FloatRect CFX_ListCtrl::OutToIn(const CFX_FloatRect& rect) const {
- CFX_PointF ptLeftBottom = OutToIn(CFX_PointF(rect.left, rect.bottom));
- CFX_PointF ptRightTop = OutToIn(CFX_PointF(rect.right, rect.top));
- return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
- ptRightTop.y);
-}
-
-void CFX_ListCtrl::OnMouseDown(const CFX_PointF& point,
- bool bShift,
- bool bCtrl) {
- int32_t nHitIndex = GetItemIndex(point);
-
- if (IsMultipleSel()) {
- if (bCtrl) {
- if (IsItemSelected(nHitIndex)) {
- m_aSelItems.Sub(nHitIndex);
- SelectItems();
- m_bCtrlSel = false;
- } else {
- m_aSelItems.Add(nHitIndex);
- SelectItems();
- m_bCtrlSel = true;
- }
-
- m_nFootIndex = nHitIndex;
- } else if (bShift) {
- m_aSelItems.DeselectAll();
- m_aSelItems.Add(m_nFootIndex, nHitIndex);
- SelectItems();
- } else {
- m_aSelItems.DeselectAll();
- m_aSelItems.Add(nHitIndex);
- SelectItems();
-
- m_nFootIndex = nHitIndex;
- }
-
- SetCaret(nHitIndex);
- } else {
- SetSingleSelect(nHitIndex);
- }
-
- if (!IsItemVisible(nHitIndex))
- ScrollToListItem(nHitIndex);
-}
-
-void CFX_ListCtrl::OnMouseMove(const CFX_PointF& point,
- bool bShift,
- bool bCtrl) {
- int32_t nHitIndex = GetItemIndex(point);
-
- if (IsMultipleSel()) {
- if (bCtrl) {
- if (m_bCtrlSel)
- m_aSelItems.Add(m_nFootIndex, nHitIndex);
- else
- m_aSelItems.Sub(m_nFootIndex, nHitIndex);
-
- SelectItems();
- } else {
- m_aSelItems.DeselectAll();
- m_aSelItems.Add(m_nFootIndex, nHitIndex);
- SelectItems();
- }
-
- SetCaret(nHitIndex);
- } else {
- SetSingleSelect(nHitIndex);
- }
-
- if (!IsItemVisible(nHitIndex))
- ScrollToListItem(nHitIndex);
-}
-
-void CFX_ListCtrl::OnVK(int32_t nItemIndex, bool bShift, bool bCtrl) {
- if (IsMultipleSel()) {
- if (nItemIndex >= 0 && nItemIndex < GetCount()) {
- if (bCtrl) {
- } else if (bShift) {
- m_aSelItems.DeselectAll();
- m_aSelItems.Add(m_nFootIndex, nItemIndex);
- SelectItems();
- } else {
- m_aSelItems.DeselectAll();
- m_aSelItems.Add(nItemIndex);
- SelectItems();
- m_nFootIndex = nItemIndex;
- }
-
- SetCaret(nItemIndex);
- }
- } else {
- SetSingleSelect(nItemIndex);
- }
-
- if (!IsItemVisible(nItemIndex))
- ScrollToListItem(nItemIndex);
-}
-
-void CFX_ListCtrl::OnVK_UP(bool bShift, bool bCtrl) {
- OnVK(IsMultipleSel() ? GetCaret() - 1 : GetSelect() - 1, bShift, bCtrl);
-}
-
-void CFX_ListCtrl::OnVK_DOWN(bool bShift, bool bCtrl) {
- OnVK(IsMultipleSel() ? GetCaret() + 1 : GetSelect() + 1, bShift, bCtrl);
-}
-
-void CFX_ListCtrl::OnVK_LEFT(bool bShift, bool bCtrl) {
- OnVK(0, bShift, bCtrl);
-}
-
-void CFX_ListCtrl::OnVK_RIGHT(bool bShift, bool bCtrl) {
- OnVK(GetCount() - 1, bShift, bCtrl);
-}
-
-void CFX_ListCtrl::OnVK_HOME(bool bShift, bool bCtrl) {
- OnVK(0, bShift, bCtrl);
-}
-
-void CFX_ListCtrl::OnVK_END(bool bShift, bool bCtrl) {
- OnVK(GetCount() - 1, bShift, bCtrl);
-}
-
-bool CFX_ListCtrl::OnChar(uint16_t nChar, bool bShift, bool bCtrl) {
- int32_t nIndex = GetLastSelected();
- int32_t nFindIndex = FindNext(nIndex, nChar);
-
- if (nFindIndex != nIndex) {
- OnVK(nFindIndex, bShift, bCtrl);
- return true;
- }
- return false;
-}
-
-void CFX_ListCtrl::SetPlateRect(const CFX_FloatRect& rect) {
- CFX_ListContainer::SetPlateRect(rect);
- m_ptScrollPos.x = rect.left;
- SetScrollPos(CFX_PointF(rect.left, rect.top));
- ReArrange(0);
- InvalidateItem(-1);
-}
-
-CFX_FloatRect CFX_ListCtrl::GetItemRect(int32_t nIndex) const {
- return InToOut(GetItemRectInternal(nIndex));
-}
-
-CFX_FloatRect CFX_ListCtrl::GetItemRectInternal(int32_t nIndex) const {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) {
- CFX_FloatRect rcItem = pListItem->GetRect();
- rcItem.left = 0.0f;
- rcItem.right = GetPlateRect().Width();
- return InnerToOuter(CLST_Rect(rcItem));
- }
-
- return CFX_FloatRect();
-}
-
-int32_t CFX_ListCtrl::GetCaret() const {
- return m_nCaretIndex;
-}
-
-int32_t CFX_ListCtrl::GetSelect() const {
- return m_nSelItem;
-}
-
-void CFX_ListCtrl::AddString(const CFX_WideString& str) {
- AddItem(str);
- ReArrange(GetCount() - 1);
-}
-
-void CFX_ListCtrl::SetMultipleSelect(int32_t nItemIndex, bool bSelected) {
- if (!IsValid(nItemIndex))
- return;
-
- if (bSelected != IsItemSelected(nItemIndex)) {
- if (bSelected) {
- SetItemSelect(nItemIndex, true);
- InvalidateItem(nItemIndex);
- } else {
- SetItemSelect(nItemIndex, false);
- InvalidateItem(nItemIndex);
- }
- }
-}
-
-void CFX_ListCtrl::SetSingleSelect(int32_t nItemIndex) {
- if (!IsValid(nItemIndex))
- return;
-
- if (m_nSelItem != nItemIndex) {
- if (m_nSelItem >= 0) {
- SetItemSelect(m_nSelItem, false);
- InvalidateItem(m_nSelItem);
- }
-
- SetItemSelect(nItemIndex, true);
- InvalidateItem(nItemIndex);
- m_nSelItem = nItemIndex;
- }
-}
-
-void CFX_ListCtrl::SetCaret(int32_t nItemIndex) {
- if (!IsValid(nItemIndex))
- return;
-
- if (IsMultipleSel()) {
- int32_t nOldIndex = m_nCaretIndex;
-
- if (nOldIndex != nItemIndex) {
- m_nCaretIndex = nItemIndex;
- InvalidateItem(nOldIndex);
- InvalidateItem(nItemIndex);
- }
- }
-}
-
-void CFX_ListCtrl::InvalidateItem(int32_t nItemIndex) {
- if (m_pNotify) {
- if (nItemIndex == -1) {
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- CFX_FloatRect rcRefresh = GetPlateRect();
- m_pNotify->IOnInvalidateRect(&rcRefresh);
- m_bNotifyFlag = false;
- }
- } else {
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- CFX_FloatRect rcRefresh = GetItemRect(nItemIndex);
- rcRefresh.left -= 1.0f;
- rcRefresh.right += 1.0f;
- rcRefresh.bottom -= 1.0f;
- rcRefresh.top += 1.0f;
-
- m_pNotify->IOnInvalidateRect(&rcRefresh);
- m_bNotifyFlag = false;
- }
- }
- }
-}
-
-void CFX_ListCtrl::SelectItems() {
- for (int32_t i = 0, sz = m_aSelItems.GetCount(); i < sz; i++) {
- int32_t nItemIndex = m_aSelItems.GetItemIndex(i);
- int32_t nState = m_aSelItems.GetState(i);
-
- switch (nState) {
- case 1:
- SetMultipleSelect(nItemIndex, true);
- break;
- case -1:
- SetMultipleSelect(nItemIndex, false);
- break;
- }
- }
-
- m_aSelItems.Done();
-}
-
-void CFX_ListCtrl::Select(int32_t nItemIndex) {
- if (!IsValid(nItemIndex))
- return;
-
- if (IsMultipleSel()) {
- m_aSelItems.Add(nItemIndex);
- SelectItems();
- } else {
- SetSingleSelect(nItemIndex);
- }
-}
-
-bool CFX_ListCtrl::IsItemVisible(int32_t nItemIndex) const {
- CFX_FloatRect rcPlate = GetPlateRect();
- CFX_FloatRect rcItem = GetItemRect(nItemIndex);
-
- return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top;
-}
-
-void CFX_ListCtrl::ScrollToListItem(int32_t nItemIndex) {
- if (!IsValid(nItemIndex))
- return;
-
- CFX_FloatRect rcPlate = GetPlateRect();
- CFX_FloatRect rcItem = GetItemRectInternal(nItemIndex);
- CFX_FloatRect rcItemCtrl = GetItemRect(nItemIndex);
-
- if (IsFloatSmaller(rcItemCtrl.bottom, rcPlate.bottom)) {
- if (IsFloatSmaller(rcItemCtrl.top, rcPlate.top)) {
- SetScrollPosY(rcItem.bottom + rcPlate.Height());
- }
- } else if (IsFloatBigger(rcItemCtrl.top, rcPlate.top)) {
- if (IsFloatBigger(rcItemCtrl.bottom, rcPlate.bottom)) {
- SetScrollPosY(rcItem.top);
- }
- }
-}
-
-void CFX_ListCtrl::SetScrollInfo() {
- if (m_pNotify) {
- CFX_FloatRect rcPlate = GetPlateRect();
- CFX_FloatRect rcContent = GetContentRectInternal();
-
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top,
- rcContent.bottom, rcContent.top,
- GetFirstHeight(), rcPlate.Height());
- m_bNotifyFlag = false;
- }
- }
-}
-
-void CFX_ListCtrl::SetScrollPos(const CFX_PointF& point) {
- SetScrollPosY(point.y);
-}
-
-void CFX_ListCtrl::SetScrollPosY(FX_FLOAT fy) {
- if (!IsFloatEqual(m_ptScrollPos.y, fy)) {
- CFX_FloatRect rcPlate = GetPlateRect();
- CFX_FloatRect rcContent = GetContentRectInternal();
-
- if (rcPlate.Height() > rcContent.Height()) {
- fy = rcPlate.top;
- } else {
- if (IsFloatSmaller(fy - rcPlate.Height(), rcContent.bottom)) {
- fy = rcContent.bottom + rcPlate.Height();
- } else if (IsFloatBigger(fy, rcContent.top)) {
- fy = rcContent.top;
- }
- }
-
- m_ptScrollPos.y = fy;
- InvalidateItem(-1);
-
- if (m_pNotify) {
- if (!m_bNotifyFlag) {
- m_bNotifyFlag = true;
- m_pNotify->IOnSetScrollPosY(fy);
- m_bNotifyFlag = false;
- }
- }
- }
-}
-
-CFX_FloatRect CFX_ListCtrl::GetContentRectInternal() const {
- return InnerToOuter(CFX_ListContainer::GetContentRect());
-}
-
-CFX_FloatRect CFX_ListCtrl::GetContentRect() const {
- return InToOut(GetContentRectInternal());
-}
-
-void CFX_ListCtrl::ReArrange(int32_t nItemIndex) {
- FX_FLOAT fPosY = 0.0f;
-
- if (CFX_ListItem* pPrevItem = m_aListItems.GetAt(nItemIndex - 1))
- fPosY = pPrevItem->GetRect().bottom;
-
- for (int32_t i = nItemIndex, sz = m_aListItems.GetSize(); i < sz; i++) {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) {
- FX_FLOAT fListItemHeight = pListItem->GetItemHeight();
- pListItem->SetRect(CLST_Rect(0.0f, fPosY, 0.0f, fPosY + fListItemHeight));
- fPosY += fListItemHeight;
- }
- }
-
- SetContentRect(CLST_Rect(0.0f, 0.0f, 0.0f, fPosY));
- SetScrollInfo();
-}
-
-void CFX_ListCtrl::SetTopItem(int32_t nIndex) {
- if (IsValid(nIndex)) {
- GetPlateRect();
- CFX_FloatRect rcItem = GetItemRectInternal(nIndex);
- SetScrollPosY(rcItem.top);
- }
-}
-
-int32_t CFX_ListCtrl::GetTopItem() const {
- int32_t nItemIndex = GetItemIndex(GetBTPoint());
-
- if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1))
- nItemIndex += 1;
-
- return nItemIndex;
-}
-
-void CFX_ListCtrl::Empty() {
- for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++)
- delete m_aListItems.GetAt(i);
-
- m_aListItems.RemoveAll();
-
- InvalidateItem(-1);
-}
-
-void CFX_ListCtrl::Cancel() {
- m_aSelItems.DeselectAll();
-}
-
-int32_t CFX_ListCtrl::GetItemIndex(const CFX_PointF& point) const {
- CFX_PointF pt = OuterToInner(OutToIn(point));
-
- bool bFirst = true;
- bool bLast = true;
-
- for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) {
- CLST_Rect rcListItem = pListItem->GetRect();
-
- if (IsFloatBigger(pt.y, rcListItem.top)) {
- bFirst = false;
- }
-
- if (IsFloatSmaller(pt.y, rcListItem.bottom)) {
- bLast = false;
- }
-
- if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom) {
- return i;
- }
- }
- }
-
- if (bFirst)
- return 0;
- if (bLast)
- return m_aListItems.GetSize() - 1;
-
- return -1;
-}
-
-CFX_WideString CFX_ListCtrl::GetText() const {
- if (IsMultipleSel())
- return GetItemText(m_nCaretIndex);
- return GetItemText(m_nSelItem);
-}
-
-void CFX_ListCtrl::SetFontMap(IPVT_FontMap* pFontMap) {
- m_pFontMap = pFontMap;
-}
-
-void CFX_ListCtrl::SetFontSize(FX_FLOAT fFontSize) {
- m_fFontSize = fFontSize;
-}
-
-void CFX_ListCtrl::AddItem(const CFX_WideString& str) {
- CFX_ListItem* pListItem = new CFX_ListItem();
- pListItem->SetFontMap(m_pFontMap);
- pListItem->SetFontSize(m_fFontSize);
- pListItem->SetText(str);
- m_aListItems.Add(pListItem);
-}
-
-CFX_Edit* CFX_ListCtrl::GetItemEdit(int32_t nIndex) const {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) {
- return pListItem->GetEdit();
- }
-
- return nullptr;
-}
-
-int32_t CFX_ListCtrl::GetCount() const {
- return m_aListItems.GetSize();
-}
-
-CFX_FloatRect CFX_ListCtrl::GetPlateRect() const {
- return CFX_ListContainer::GetPlateRect();
-}
-
-FX_FLOAT CFX_ListCtrl::GetFontSize() const {
- return m_fFontSize;
-}
-
-FX_FLOAT CFX_ListCtrl::GetFirstHeight() const {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(0)) {
- return pListItem->GetItemHeight();
- }
-
- return 1.0f;
-}
-
-int32_t CFX_ListCtrl::GetFirstSelected() const {
- for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) {
- if (pListItem->IsSelected())
- return i;
- }
- }
- return -1;
-}
-
-int32_t CFX_ListCtrl::GetLastSelected() const {
- for (int32_t i = m_aListItems.GetSize() - 1; i >= 0; i--) {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) {
- if (pListItem->IsSelected())
- return i;
- }
- }
- return -1;
-}
-
-FX_WCHAR CFX_ListCtrl::Toupper(FX_WCHAR c) const {
- if ((c >= 'a') && (c <= 'z'))
- c = c - ('a' - 'A');
- return c;
-}
-
-int32_t CFX_ListCtrl::FindNext(int32_t nIndex, FX_WCHAR nChar) const {
- int32_t nCircleIndex = nIndex;
-
- for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) {
- nCircleIndex++;
- if (nCircleIndex >= sz)
- nCircleIndex = 0;
-
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(nCircleIndex)) {
- if (Toupper(pListItem->GetFirstChar()) == Toupper(nChar))
- return nCircleIndex;
- }
- }
-
- return nCircleIndex;
-}
-
-bool CFX_ListCtrl::IsItemSelected(int32_t nIndex) const {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex))
- return pListItem->IsSelected();
- return false;
-}
-
-void CFX_ListCtrl::SetItemSelect(int32_t nItemIndex, bool bSelected) {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(nItemIndex)) {
- pListItem->SetSelect(bSelected);
- }
-}
-
-void CFX_ListCtrl::SetMultipleSel(bool bMultiple) {
- m_bMultiple = bMultiple;
-}
-
-bool CFX_ListCtrl::IsMultipleSel() const {
- return m_bMultiple;
-}
-
-bool CFX_ListCtrl::IsValid(int32_t nItemIndex) const {
- return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize();
-}
-
-CFX_WideString CFX_ListCtrl::GetItemText(int32_t nIndex) const {
- if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) {
- return pListItem->GetText();
- }
-
- return L"";
-}
diff --git a/fpdfsdk/fxedit/fxet_list.h b/fpdfsdk/fxedit/fxet_list.h
deleted file mode 100644
index 01e18bc..0000000
--- a/fpdfsdk/fxedit/fxet_list.h
+++ /dev/null
@@ -1,304 +0,0 @@
-// Copyright 2014 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_FXEDIT_FXET_LIST_H_
-#define FPDFSDK_FXEDIT_FXET_LIST_H_
-
-#include <memory>
-
-#include "core/fxcrt/fx_coordinates.h"
-#include "fpdfsdk/fxedit/fx_edit.h"
-
-class CFX_Edit;
-class CFX_Edit_Iterator;
-class CPWL_List_Notify;
-
-class CLST_Rect : public CFX_FloatRect {
- public:
- CLST_Rect() { left = top = right = bottom = 0.0f; }
-
- CLST_Rect(FX_FLOAT other_left,
- FX_FLOAT other_top,
- FX_FLOAT other_right,
- FX_FLOAT other_bottom) {
- left = other_left;
- top = other_top;
- right = other_right;
- bottom = other_bottom;
- }
-
- explicit CLST_Rect(const CFX_FloatRect& rect) {
- left = rect.left;
- top = rect.top;
- right = rect.right;
- bottom = rect.bottom;
- }
-
- ~CLST_Rect() {}
-
- void Default() { left = top = right = bottom = 0.0f; }
-
- const CLST_Rect operator=(const CFX_FloatRect& rect) {
- left = rect.left;
- top = rect.top;
- right = rect.right;
- bottom = rect.bottom;
-
- return *this;
- }
-
- bool operator==(const CLST_Rect& rect) const {
- return FXSYS_memcmp(this, &rect, sizeof(CLST_Rect)) == 0;
- }
-
- bool operator!=(const CLST_Rect& rect) const { return !(*this == rect); }
-
- FX_FLOAT Width() const { return right - left; }
-
- FX_FLOAT Height() const {
- if (top > bottom)
- return top - bottom;
- return bottom - top;
- }
-
- CFX_PointF LeftTop() const { return CFX_PointF(left, top); }
-
- CFX_PointF RightBottom() const { return CFX_PointF(right, bottom); }
-
- const CLST_Rect operator+=(const CFX_PointF& point) {
- left += point.x;
- right += point.x;
- top += point.y;
- bottom += point.y;
-
- return *this;
- }
-
- const CLST_Rect operator-=(const CFX_PointF& point) {
- left -= point.x;
- right -= point.x;
- top -= point.y;
- bottom -= point.y;
-
- return *this;
- }
-
- CLST_Rect operator+(const CFX_PointF& point) const {
- return CLST_Rect(left + point.x, top + point.y, right + point.x,
- bottom + point.y);
- }
-
- CLST_Rect operator-(const CFX_PointF& point) const {
- return CLST_Rect(left - point.x, top - point.y, right - point.x,
- bottom - point.y);
- }
-};
-
-class CFX_ListItem final {
- public:
- CFX_ListItem();
- ~CFX_ListItem();
-
- void SetFontMap(IPVT_FontMap* pFontMap);
- CFX_Edit* GetEdit() const;
-
- void SetRect(const CLST_Rect& rect);
- void SetSelect(bool bSelected);
- void SetText(const CFX_WideString& text);
- void SetFontSize(FX_FLOAT fFontSize);
- CFX_WideString GetText() const;
-
- CLST_Rect GetRect() const;
- bool IsSelected() const;
- FX_FLOAT GetItemHeight() const;
- uint16_t GetFirstChar() const;
-
- private:
- CFX_Edit_Iterator* GetIterator() const;
-
- std::unique_ptr<CFX_Edit> m_pEdit;
- bool m_bSelected;
- CLST_Rect m_rcListItem;
-};
-
-class CFX_ListContainer {
- public:
- CFX_ListContainer();
- virtual ~CFX_ListContainer();
-
- virtual void SetPlateRect(const CFX_FloatRect& rect);
-
- CFX_FloatRect GetPlateRect() const { return m_rcPlate; }
- void SetContentRect(const CLST_Rect& rect) { m_rcContent = rect; }
- CLST_Rect GetContentRect() const { return m_rcContent; }
- CFX_PointF GetBTPoint() const {
- return CFX_PointF(m_rcPlate.left, m_rcPlate.top);
- }
- CFX_PointF GetETPoint() const {
- return CFX_PointF(m_rcPlate.right, m_rcPlate.bottom);
- }
-
- public:
- CFX_PointF InnerToOuter(const CFX_PointF& point) const {
- return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
- }
- CFX_PointF OuterToInner(const CFX_PointF& point) const {
- return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
- }
- CFX_FloatRect InnerToOuter(const CLST_Rect& rect) const {
- CFX_PointF ptLeftTop = InnerToOuter(CFX_PointF(rect.left, rect.top));
- CFX_PointF ptRightBottom =
- InnerToOuter(CFX_PointF(rect.right, rect.bottom));
- return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x,
- ptLeftTop.y);
- }
- CLST_Rect OuterToInner(const CFX_FloatRect& rect) const {
- CFX_PointF ptLeftTop = OuterToInner(CFX_PointF(rect.left, rect.top));
- CFX_PointF ptRightBottom =
- OuterToInner(CFX_PointF(rect.right, rect.bottom));
- return CLST_Rect(ptLeftTop.x, ptLeftTop.y, ptRightBottom.x,
- ptRightBottom.y);
- }
-
- private:
- CFX_FloatRect m_rcPlate;
- CLST_Rect m_rcContent; // positive forever!
-};
-
-template <class TYPE>
-class CLST_ArrayTemplate : public CFX_ArrayTemplate<TYPE> {
- public:
- bool IsEmpty() { return CFX_ArrayTemplate<TYPE>::GetSize() <= 0; }
- TYPE GetAt(int32_t nIndex) const {
- if (nIndex >= 0 && nIndex < CFX_ArrayTemplate<TYPE>::GetSize())
- return CFX_ArrayTemplate<TYPE>::GetAt(nIndex);
- return nullptr;
- }
- void RemoveAt(int32_t nIndex) {
- if (nIndex >= 0 && nIndex < CFX_ArrayTemplate<TYPE>::GetSize())
- CFX_ArrayTemplate<TYPE>::RemoveAt(nIndex);
- }
-};
-
-struct CPLST_Select_Item {
- CPLST_Select_Item(int32_t other_nItemIndex, int32_t other_nState) {
- nItemIndex = other_nItemIndex;
- nState = other_nState;
- }
-
- int32_t nItemIndex;
- int32_t nState; // 0:normal select -1:to deselect 1: to select
-};
-
-class CPLST_Select {
- public:
- CPLST_Select();
- virtual ~CPLST_Select();
-
- public:
- void Add(int32_t nItemIndex);
- void Add(int32_t nBeginIndex, int32_t nEndIndex);
- void Sub(int32_t nItemIndex);
- void Sub(int32_t nBeginIndex, int32_t nEndIndex);
- bool IsExist(int32_t nItemIndex) const;
- int32_t Find(int32_t nItemIndex) const;
- int32_t GetCount() const;
- int32_t GetItemIndex(int32_t nIndex) const;
- int32_t GetState(int32_t nIndex) const;
- void Done();
- void DeselectAll();
-
- private:
- CFX_ArrayTemplate<CPLST_Select_Item*> m_aItems;
-};
-
-class CFX_ListCtrl : protected CFX_ListContainer {
- public:
- CFX_ListCtrl();
- ~CFX_ListCtrl() override;
-
- // CFX_ListContainer
- void SetPlateRect(const CFX_FloatRect& rect) override;
-
- void SetNotify(CPWL_List_Notify* pNotify);
- void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl);
- void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl);
- void OnVK_UP(bool bShift, bool bCtrl);
- void OnVK_DOWN(bool bShift, bool bCtrl);
- void OnVK_LEFT(bool bShift, bool bCtrl);
- void OnVK_RIGHT(bool bShift, bool bCtrl);
- void OnVK_HOME(bool bShift, bool bCtrl);
- void OnVK_END(bool bShift, bool bCtrl);
- void OnVK(int32_t nItemIndex, bool bShift, bool bCtrl);
- bool OnChar(uint16_t nChar, bool bShift, bool bCtrl);
-
- void SetScrollPos(const CFX_PointF& point);
- void ScrollToListItem(int32_t nItemIndex);
- CFX_FloatRect GetItemRect(int32_t nIndex) const;
- int32_t GetCaret() const;
- int32_t GetSelect() const;
- int32_t GetTopItem() const;
- CFX_FloatRect GetContentRect() const;
- int32_t GetItemIndex(const CFX_PointF& point) const;
- void AddString(const CFX_WideString& str);
- void SetTopItem(int32_t nIndex);
- void Select(int32_t nItemIndex);
- void SetCaret(int32_t nItemIndex);
- void Empty();
- void Cancel();
- CFX_WideString GetText() const;
-
- void SetFontMap(IPVT_FontMap* pFontMap);
- void SetFontSize(FX_FLOAT fFontSize);
- CFX_FloatRect GetPlateRect() const;
- FX_FLOAT GetFontSize() const;
- CFX_Edit* GetItemEdit(int32_t nIndex) const;
- int32_t GetCount() const;
- bool IsItemSelected(int32_t nIndex) const;
- FX_FLOAT GetFirstHeight() const;
- void SetMultipleSel(bool bMultiple);
- bool IsMultipleSel() const;
- bool IsValid(int32_t nItemIndex) const;
- int32_t FindNext(int32_t nIndex, FX_WCHAR nChar) const;
- int32_t GetFirstSelected() const;
-
- CFX_PointF InToOut(const CFX_PointF& point) const;
- CFX_PointF OutToIn(const CFX_PointF& point) const;
- CFX_FloatRect InToOut(const CFX_FloatRect& rect) const;
- CFX_FloatRect OutToIn(const CFX_FloatRect& rect) const;
-
- private:
- void ReArrange(int32_t nItemIndex);
- CFX_FloatRect GetItemRectInternal(int32_t nIndex) const;
- CFX_FloatRect GetContentRectInternal() const;
- void SetMultipleSelect(int32_t nItemIndex, bool bSelected);
- void SetSingleSelect(int32_t nItemIndex);
- void InvalidateItem(int32_t nItemIndex);
- void SelectItems();
- bool IsItemVisible(int32_t nItemIndex) const;
- void SetScrollInfo();
- void SetScrollPosY(FX_FLOAT fy);
- void AddItem(const CFX_WideString& str);
- CFX_WideString GetItemText(int32_t nIndex) const;
- void SetItemSelect(int32_t nItemIndex, bool bSelected);
- int32_t GetLastSelected() const;
- FX_WCHAR Toupper(FX_WCHAR c) const;
-
- CPWL_List_Notify* m_pNotify;
- bool m_bNotifyFlag;
- CFX_PointF m_ptScrollPos;
- CPLST_Select m_aSelItems; // for multiple
- int32_t m_nSelItem; // for single
- int32_t m_nFootIndex; // for multiple
- bool m_bCtrlSel; // for multiple
- int32_t m_nCaretIndex; // for multiple
- CLST_ArrayTemplate<CFX_ListItem*> m_aListItems;
- FX_FLOAT m_fFontSize;
- IPVT_FontMap* m_pFontMap;
- bool m_bMultiple;
-};
-
-#endif // FPDFSDK_FXEDIT_FXET_LIST_H_
diff --git a/fpdfsdk/ipdfsdk_annothandler.h b/fpdfsdk/ipdfsdk_annothandler.h
index 636d161..bffeac6 100644
--- a/fpdfsdk/ipdfsdk_annothandler.h
+++ b/fpdfsdk/ipdfsdk_annothandler.h
@@ -7,7 +7,6 @@
#ifndef FPDFSDK_IPDFSDK_ANNOTHANDLER_H_
#define FPDFSDK_IPDFSDK_ANNOTHANDLER_H_
-#include "core/fxcrt/fx_basic.h"
#include "core/fxcrt/fx_coordinates.h"
#include "fpdfsdk/cpdfsdk_annot.h"
@@ -36,6 +35,9 @@
virtual void ReleaseAnnot(CPDFSDK_Annot* pAnnot) = 0;
virtual CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot) = 0;
+ virtual WideString GetSelectedText(CPDFSDK_Annot* pAnnot) = 0;
+ virtual void ReplaceSelection(CPDFSDK_Annot* pAnnot,
+ const WideString& text) = 0;
virtual bool HitTest(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
const CFX_PointF& point) = 0;
diff --git a/fpdfsdk/javascript/Annot.cpp b/fpdfsdk/javascript/Annot.cpp
deleted file mode 100644
index 41c71ec..0000000
--- a/fpdfsdk/javascript/Annot.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2016 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/javascript/Annot.h"
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-
-namespace {
-
-CPDFSDK_BAAnnot* ToBAAnnot(CPDFSDK_Annot* annot) {
- return static_cast<CPDFSDK_BAAnnot*>(annot);
-}
-
-} // namespace
-
-JSConstSpec CJS_Annot::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Annot::PropertySpecs[] = {
- {"hidden", get_hidden_static, set_hidden_static},
- {"name", get_name_static, set_name_static},
- {"type", get_type_static, set_type_static},
- {0, 0, 0}};
-
-JSMethodSpec CJS_Annot::MethodSpecs[] = {{0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Annot, Annot)
-
-Annot::Annot(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {}
-
-Annot::~Annot() {}
-
-bool Annot::hidden(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsGetting()) {
- if (!m_pAnnot) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- CPDF_Annot* pPDFAnnot = ToBAAnnot(m_pAnnot.Get())->GetPDFAnnot();
- vp << CPDF_Annot::IsAnnotationHidden(pPDFAnnot->GetAnnotDict());
- return true;
- }
-
- bool bHidden;
- vp >> bHidden; // May invalidate m_pAnnot.
- if (!m_pAnnot) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
-
- uint32_t flags = ToBAAnnot(m_pAnnot.Get())->GetFlags();
- if (bHidden) {
- flags |= ANNOTFLAG_HIDDEN;
- flags |= ANNOTFLAG_INVISIBLE;
- flags |= ANNOTFLAG_NOVIEW;
- flags &= ~ANNOTFLAG_PRINT;
- } else {
- flags &= ~ANNOTFLAG_HIDDEN;
- flags &= ~ANNOTFLAG_INVISIBLE;
- flags &= ~ANNOTFLAG_NOVIEW;
- flags |= ANNOTFLAG_PRINT;
- }
- ToBAAnnot(m_pAnnot.Get())->SetFlags(flags);
- return true;
-}
-
-bool Annot::name(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsGetting()) {
- if (!m_pAnnot) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- vp << ToBAAnnot(m_pAnnot.Get())->GetAnnotName();
- return true;
- }
-
- CFX_WideString annotName;
- vp >> annotName; // May invalidate m_pAnnot.
- if (!m_pAnnot) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
-
- ToBAAnnot(m_pAnnot.Get())->SetAnnotName(annotName);
- return true;
-}
-
-bool Annot::type(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- if (!m_pAnnot) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- vp << CPDF_Annot::AnnotSubtypeToString(
- ToBAAnnot(m_pAnnot.Get())->GetAnnotSubtype());
- return true;
-}
-
-void Annot::SetSDKAnnot(CPDFSDK_BAAnnot* annot) {
- m_pAnnot.Reset(annot);
-}
diff --git a/fpdfsdk/javascript/Annot.h b/fpdfsdk/javascript/Annot.h
deleted file mode 100644
index d9757fa..0000000
--- a/fpdfsdk/javascript/Annot.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 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_JAVASCRIPT_ANNOT_H_
-#define FPDFSDK_JAVASCRIPT_ANNOT_H_
-
-#include <memory>
-
-#include "fpdfsdk/cpdfsdk_baannot.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class Annot : public CJS_EmbedObj {
- public:
- explicit Annot(CJS_Object* pJSObject);
- ~Annot() override;
-
- bool hidden(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool name(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool type(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
-
- void SetSDKAnnot(CPDFSDK_BAAnnot* annot);
-
- private:
- CPDFSDK_Annot::ObservedPtr m_pAnnot;
-};
-
-class CJS_Annot : public CJS_Object {
- public:
- explicit CJS_Annot(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Annot() override {}
-
- DECLARE_JS_CLASS();
- JS_STATIC_PROP(hidden, Annot);
- JS_STATIC_PROP(name, Annot);
- JS_STATIC_PROP(type, Annot);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_ANNOT_H_
diff --git a/fpdfsdk/javascript/Consts.cpp b/fpdfsdk/javascript/Consts.cpp
deleted file mode 100644
index 82f9b4c..0000000
--- a/fpdfsdk/javascript/Consts.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2014 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/javascript/Consts.h"
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-
-JSConstSpec CJS_Border::ConstSpecs[] = {
- {"s", JSConstSpec::String, 0, "solid"},
- {"b", JSConstSpec::String, 0, "beveled"},
- {"d", JSConstSpec::String, 0, "dashed"},
- {"i", JSConstSpec::String, 0, "inset"},
- {"u", JSConstSpec::String, 0, "underline"},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_Border, border)
-
-JSConstSpec CJS_Display::ConstSpecs[] = {{"visible", JSConstSpec::Number, 0, 0},
- {"hidden", JSConstSpec::Number, 1, 0},
- {"noPrint", JSConstSpec::Number, 2, 0},
- {"noView", JSConstSpec::Number, 3, 0},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_Display, display)
-
-JSConstSpec CJS_Font::ConstSpecs[] = {
- {"Times", JSConstSpec::String, 0, "Times-Roman"},
- {"TimesB", JSConstSpec::String, 0, "Times-Bold"},
- {"TimesI", JSConstSpec::String, 0, "Times-Italic"},
- {"TimesBI", JSConstSpec::String, 0, "Times-BoldItalic"},
- {"Helv", JSConstSpec::String, 0, "Helvetica"},
- {"HelvB", JSConstSpec::String, 0, "Helvetica-Bold"},
- {"HelvI", JSConstSpec::String, 0, "Helvetica-Oblique"},
- {"HelvBI", JSConstSpec::String, 0, "Helvetica-BoldOblique"},
- {"Cour", JSConstSpec::String, 0, "Courier"},
- {"CourB", JSConstSpec::String, 0, "Courier-Bold"},
- {"CourI", JSConstSpec::String, 0, "Courier-Oblique"},
- {"CourBI", JSConstSpec::String, 0, "Courier-BoldOblique"},
- {"Symbol", JSConstSpec::String, 0, "Symbol"},
- {"ZapfD", JSConstSpec::String, 0, "ZapfDingbats"},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_Font, font)
-
-JSConstSpec CJS_Highlight::ConstSpecs[] = {
- {"n", JSConstSpec::String, 0, "none"},
- {"i", JSConstSpec::String, 0, "invert"},
- {"p", JSConstSpec::String, 0, "push"},
- {"o", JSConstSpec::String, 0, "outline"},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_Highlight, highlight)
-
-JSConstSpec CJS_Position::ConstSpecs[] = {
- {"textOnly", JSConstSpec::Number, 0, 0},
- {"iconOnly", JSConstSpec::Number, 1, 0},
- {"iconTextV", JSConstSpec::Number, 2, 0},
- {"textIconV", JSConstSpec::Number, 3, 0},
- {"iconTextH", JSConstSpec::Number, 4, 0},
- {"textIconH", JSConstSpec::Number, 5, 0},
- {"overlay", JSConstSpec::Number, 6, 0},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_Position, position)
-
-JSConstSpec CJS_ScaleHow::ConstSpecs[] = {
- {"proportional", JSConstSpec::Number, 0, 0},
- {"anamorphic", JSConstSpec::Number, 1, 0},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_ScaleHow, scaleHow)
-
-JSConstSpec CJS_ScaleWhen::ConstSpecs[] = {
- {"always", JSConstSpec::Number, 0, 0},
- {"never", JSConstSpec::Number, 1, 0},
- {"tooBig", JSConstSpec::Number, 2, 0},
- {"tooSmall", JSConstSpec::Number, 3, 0},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_ScaleWhen, scaleWhen)
-
-JSConstSpec CJS_Style::ConstSpecs[] = {
- {"ch", JSConstSpec::String, 0, "check"},
- {"cr", JSConstSpec::String, 0, "cross"},
- {"di", JSConstSpec::String, 0, "diamond"},
- {"ci", JSConstSpec::String, 0, "circle"},
- {"st", JSConstSpec::String, 0, "star"},
- {"sq", JSConstSpec::String, 0, "square"},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_Style, style)
-
-JSConstSpec CJS_Zoomtype::ConstSpecs[] = {
- {"none", JSConstSpec::String, 0, "NoVary"},
- {"fitP", JSConstSpec::String, 0, "FitPage"},
- {"fitW", JSConstSpec::String, 0, "FitWidth"},
- {"fitH", JSConstSpec::String, 0, "FitHeight"},
- {"fitV", JSConstSpec::String, 0, "FitVisibleWidth"},
- {"pref", JSConstSpec::String, 0, "Preferred"},
- {"refW", JSConstSpec::String, 0, "ReflowWidth"},
- {0, JSConstSpec::Number, 0, 0}};
-IMPLEMENT_JS_CLASS_CONST(CJS_Zoomtype, zoomtype)
-
-#define GLOBAL_STRING(rt, name, value) \
- (rt)->DefineGlobalConst( \
- (name), [](const v8::FunctionCallbackInfo<v8::Value>& info) { \
- info.GetReturnValue().Set( \
- CFXJS_Engine::CurrentEngineFromIsolate(info.GetIsolate()) \
- ->NewString(value)); \
- })
-
-void CJS_GlobalConsts::DefineJSObjects(CJS_Runtime* pRuntime) {
- GLOBAL_STRING(pRuntime, L"IDS_GREATER_THAN",
- L"Invalid value: must be greater than or equal to % s.");
-
- GLOBAL_STRING(pRuntime, L"IDS_GT_AND_LT",
- L"Invalid value: must be greater than or equal to % s "
- L"and less than or equal to % s.");
-
- GLOBAL_STRING(pRuntime, L"IDS_LESS_THAN",
- L"Invalid value: must be less than or equal to % s.");
-
- GLOBAL_STRING(pRuntime, L"IDS_INVALID_MONTH", L"**Invalid**");
- GLOBAL_STRING(
- pRuntime, L"IDS_INVALID_DATE",
- L"Invalid date / time: please ensure that the date / time exists.Field");
-
- GLOBAL_STRING(pRuntime, L"IDS_INVALID_VALUE",
- L"The value entered does not match the format of the field");
-
- GLOBAL_STRING(pRuntime, L"IDS_AM", L"am");
- GLOBAL_STRING(pRuntime, L"IDS_PM", L"pm");
- GLOBAL_STRING(pRuntime, L"IDS_MONTH_INFO",
- L"January[1] February[2] March[3] April[4] May[5] "
- L"June[6] July[7] August[8] September[9] October[10] "
- L"November[11] December[12] Sept[9] Jan[1] Feb[2] Mar[3] "
- L"Apr[4] Jun[6] Jul[7] Aug[8] Sep[9] Oct[10] Nov[11] "
- L"Dec[12]");
-
- GLOBAL_STRING(pRuntime, L"IDS_STARTUP_CONSOLE_MSG", L"** ^ _ ^ **");
-}
-
-#define GLOBAL_ARRAY(rt, name, ...) \
- { \
- const FX_WCHAR* values[] = {__VA_ARGS__}; \
- v8::Local<v8::Array> array = (rt)->NewArray(); \
- for (size_t i = 0; i < FX_ArraySize(values); ++i) \
- array->Set(i, (rt)->NewString(values[i])); \
- (rt)->SetConstArray((name), array); \
- (rt)->DefineGlobalConst( \
- (name), [](const v8::FunctionCallbackInfo<v8::Value>& info) { \
- CJS_Runtime* pCurrentRuntime = \
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); \
- if (pCurrentRuntime) \
- info.GetReturnValue().Set(pCurrentRuntime->GetConstArray(name)); \
- }); \
- }
-
-void CJS_GlobalArrays::DefineJSObjects(CJS_Runtime* pRuntime) {
- GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_ENTRY_DOT_SEP", L"[+-]?\\d*\\.?\\d*");
- GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_COMMIT_DOT_SEP",
- L"[+-]?\\d+(\\.\\d+)?", // -1.0 or -1
- L"[+-]?\\.\\d+", // -.1
- L"[+-]?\\d+\\."); // -1.
-
- GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_ENTRY_COMMA_SEP", L"[+-]?\\d*,?\\d*");
- GLOBAL_ARRAY(pRuntime, L"RE_NUMBER_COMMIT_COMMA_SEP",
- L"[+-]?\\d+([.,]\\d+)?", // -1,0 or -1
- L"[+-]?[.,]\\d+", // -,1
- L"[+-]?\\d+[.,]"); // -1,
-
- GLOBAL_ARRAY(pRuntime, L"RE_ZIP_ENTRY", L"\\d{0,5}");
- GLOBAL_ARRAY(pRuntime, L"RE_ZIP_COMMIT", L"\\d{5}");
- GLOBAL_ARRAY(pRuntime, L"RE_ZIP4_ENTRY", L"\\d{0,5}(\\.|[- ])?\\d{0,4}");
- GLOBAL_ARRAY(pRuntime, L"RE_ZIP4_COMMIT", L"\\d{5}(\\.|[- ])?\\d{4}");
- GLOBAL_ARRAY(pRuntime, L"RE_PHONE_ENTRY",
- // 555-1234 or 408 555-1234
- L"\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}",
-
- // (408
- L"\\(\\d{0,3}",
-
- // (408) 555-1234
- // (allow the addition of parens as an afterthought)
- L"\\(\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}",
-
- // (408 555-1234
- L"\\(\\d{0,3}(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}",
-
- // 408) 555-1234
- L"\\d{0,3}\\)(\\.|[- ])?\\d{0,3}(\\.|[- ])?\\d{0,4}",
-
- // international
- L"011(\\.|[- \\d])*");
-
- GLOBAL_ARRAY(
- pRuntime, L"RE_PHONE_COMMIT", L"\\d{3}(\\.|[- ])?\\d{4}", // 555-1234
- L"\\d{3}(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}", // 408 555-1234
- L"\\(\\d{3}\\)(\\.|[- ])?\\d{3}(\\.|[- ])?\\d{4}", // (408) 555-1234
- L"011(\\.|[- \\d])*"); // international
-
- GLOBAL_ARRAY(pRuntime, L"RE_SSN_ENTRY",
- L"\\d{0,3}(\\.|[- ])?\\d{0,2}(\\.|[- ])?\\d{0,4}");
-
- GLOBAL_ARRAY(pRuntime, L"RE_SSN_COMMIT",
- L"\\d{3}(\\.|[- ])?\\d{2}(\\.|[- ])?\\d{4}");
-}
diff --git a/fpdfsdk/javascript/Consts.h b/fpdfsdk/javascript/Consts.h
deleted file mode 100644
index e358cb9..0000000
--- a/fpdfsdk/javascript/Consts.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_CONSTS_H_
-#define FPDFSDK_JAVASCRIPT_CONSTS_H_
-
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class CJS_Border : public CJS_Object {
- public:
- explicit CJS_Border(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Border() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_Display : public CJS_Object {
- public:
- explicit CJS_Display(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Display() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_Font : public CJS_Object {
- public:
- explicit CJS_Font(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Font() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_Highlight : public CJS_Object {
- public:
- explicit CJS_Highlight(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Highlight() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_Position : public CJS_Object {
- public:
- explicit CJS_Position(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Position() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_ScaleHow : public CJS_Object {
- public:
- explicit CJS_ScaleHow(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_ScaleHow() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_ScaleWhen : public CJS_Object {
- public:
- explicit CJS_ScaleWhen(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_ScaleWhen() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_Style : public CJS_Object {
- public:
- explicit CJS_Style(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Style() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_Zoomtype : public CJS_Object {
- public:
- explicit CJS_Zoomtype(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Zoomtype() override {}
-
- DECLARE_JS_CLASS_CONST();
-};
-
-class CJS_GlobalConsts : public CJS_Object {
- public:
- static void DefineJSObjects(CJS_Runtime* pRuntime);
-};
-
-class CJS_GlobalArrays : public CJS_Object {
- public:
- static void DefineJSObjects(CJS_Runtime* pRuntmie);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_CONSTS_H_
diff --git a/fpdfsdk/javascript/DEPS b/fpdfsdk/javascript/DEPS
deleted file mode 100644
index 36a51aa..0000000
--- a/fpdfsdk/javascript/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- '+fxjs'
-]
diff --git a/fpdfsdk/javascript/Document.cpp b/fpdfsdk/javascript/Document.cpp
deleted file mode 100644
index a45b8b9..0000000
--- a/fpdfsdk/javascript/Document.cpp
+++ /dev/null
@@ -1,1658 +0,0 @@
-// Copyright 2014 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/javascript/Document.h"
-
-#include <algorithm>
-#include <utility>
-#include <vector>
-
-#include "core/fpdfapi/font/cpdf_font.h"
-#include "core/fpdfapi/page/cpdf_page.h"
-#include "core/fpdfapi/parser/cpdf_array.h"
-#include "core/fpdfapi/parser/cpdf_document.h"
-#include "core/fpdfapi/parser/cpdf_string.h"
-#include "core/fpdfapi/parser/fpdf_parser_decode.h"
-#include "core/fpdfdoc/cpdf_interform.h"
-#include "core/fpdfdoc/cpdf_nametree.h"
-#include "fpdfsdk/cpdfsdk_annotiteration.h"
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/cpdfsdk_interform.h"
-#include "fpdfsdk/cpdfsdk_pageview.h"
-#include "fpdfsdk/cpdfsdk_widget.h"
-#include "fpdfsdk/javascript/Annot.h"
-#include "fpdfsdk/javascript/Field.h"
-#include "fpdfsdk/javascript/Icon.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/app.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fpdfsdk/javascript/resource.h"
-#include "third_party/base/numerics/safe_math.h"
-#include "third_party/base/ptr_util.h"
-
-JSConstSpec CJS_PrintParamsObj::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_PrintParamsObj::PropertySpecs[] = {{0, 0, 0}};
-
-JSMethodSpec CJS_PrintParamsObj::MethodSpecs[] = {{0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_PrintParamsObj, PrintParamsObj)
-
-PrintParamsObj::PrintParamsObj(CJS_Object* pJSObject)
- : CJS_EmbedObj(pJSObject) {
- bUI = true;
- nStart = 0;
- nEnd = 0;
- bSilent = false;
- bShrinkToFit = false;
- bPrintAsImage = false;
- bReverse = false;
- bAnnotations = true;
-}
-
-#define MINWIDTH 5.0f
-#define MINHEIGHT 5.0f
-
-JSConstSpec CJS_Document::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Document::PropertySpecs[] = {
- {"ADBE", get_ADBE_static, set_ADBE_static},
- {"author", get_author_static, set_author_static},
- {"baseURL", get_baseURL_static, set_baseURL_static},
- {"bookmarkRoot", get_bookmarkRoot_static, set_bookmarkRoot_static},
- {"calculate", get_calculate_static, set_calculate_static},
- {"Collab", get_Collab_static, set_Collab_static},
- {"creationDate", get_creationDate_static, set_creationDate_static},
- {"creator", get_creator_static, set_creator_static},
- {"delay", get_delay_static, set_delay_static},
- {"dirty", get_dirty_static, set_dirty_static},
- {"documentFileName", get_documentFileName_static,
- set_documentFileName_static},
- {"external", get_external_static, set_external_static},
- {"filesize", get_filesize_static, set_filesize_static},
- {"icons", get_icons_static, set_icons_static},
- {"info", get_info_static, set_info_static},
- {"keywords", get_keywords_static, set_keywords_static},
- {"layout", get_layout_static, set_layout_static},
- {"media", get_media_static, set_media_static},
- {"modDate", get_modDate_static, set_modDate_static},
- {"mouseX", get_mouseX_static, set_mouseX_static},
- {"mouseY", get_mouseY_static, set_mouseY_static},
- {"numFields", get_numFields_static, set_numFields_static},
- {"numPages", get_numPages_static, set_numPages_static},
- {"pageNum", get_pageNum_static, set_pageNum_static},
- {"pageWindowRect", get_pageWindowRect_static, set_pageWindowRect_static},
- {"path", get_path_static, set_path_static},
- {"producer", get_producer_static, set_producer_static},
- {"subject", get_subject_static, set_subject_static},
- {"title", get_title_static, set_title_static},
- {"URL", get_URL_static, set_URL_static},
- {"zoom", get_zoom_static, set_zoom_static},
- {"zoomType", get_zoomType_static, set_zoomType_static},
- {0, 0, 0}};
-
-JSMethodSpec CJS_Document::MethodSpecs[] = {
- {"addAnnot", addAnnot_static},
- {"addField", addField_static},
- {"addLink", addLink_static},
- {"addIcon", addIcon_static},
- {"calculateNow", calculateNow_static},
- {"closeDoc", closeDoc_static},
- {"createDataObject", createDataObject_static},
- {"deletePages", deletePages_static},
- {"exportAsText", exportAsText_static},
- {"exportAsFDF", exportAsFDF_static},
- {"exportAsXFDF", exportAsXFDF_static},
- {"extractPages", extractPages_static},
- {"getAnnot", getAnnot_static},
- {"getAnnots", getAnnots_static},
- {"getAnnot3D", getAnnot3D_static},
- {"getAnnots3D", getAnnots3D_static},
- {"getField", getField_static},
- {"getIcon", getIcon_static},
- {"getLinks", getLinks_static},
- {"getNthFieldName", getNthFieldName_static},
- {"getOCGs", getOCGs_static},
- {"getPageBox", getPageBox_static},
- {"getPageNthWord", getPageNthWord_static},
- {"getPageNthWordQuads", getPageNthWordQuads_static},
- {"getPageNumWords", getPageNumWords_static},
- {"getPrintParams", getPrintParams_static},
- {"getURL", getURL_static},
- {"gotoNamedDest", gotoNamedDest_static},
- {"importAnFDF", importAnFDF_static},
- {"importAnXFDF", importAnXFDF_static},
- {"importTextData", importTextData_static},
- {"insertPages", insertPages_static},
- {"mailForm", mailForm_static},
- {"print", print_static},
- {"removeField", removeField_static},
- {"replacePages", replacePages_static},
- {"resetForm", resetForm_static},
- {"removeIcon", removeIcon_static},
- {"saveAs", saveAs_static},
- {"submitForm", submitForm_static},
- {"syncAnnotScan", syncAnnotScan_static},
- {"mailDoc", mailDoc_static},
- {0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Document, Document)
-
-void CJS_Document::InitInstance(IJS_Runtime* pIRuntime) {
- CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime);
- Document* pDoc = static_cast<Document*>(GetEmbedObject());
- pDoc->SetFormFillEnv(pRuntime->GetFormFillEnv());
-}
-
-Document::Document(CJS_Object* pJSObject)
- : CJS_EmbedObj(pJSObject),
- m_pFormFillEnv(nullptr),
- m_cwBaseURL(L""),
- m_bDelay(false) {}
-
-Document::~Document() {
-}
-
-// the total number of fileds in document.
-bool Document::numFields(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
- vp << static_cast<int>(pPDFForm->CountFields(CFX_WideString()));
- return true;
-}
-
-bool Document::dirty(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (vp.IsGetting()) {
- vp << !!m_pFormFillEnv->GetChangeMark();
- return true;
- }
- bool bChanged = false;
- vp >> bChanged;
- if (bChanged)
- m_pFormFillEnv->SetChangeMark();
- else
- m_pFormFillEnv->ClearChangeMark();
-
- return true;
-}
-
-bool Document::ADBE(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsGetting())
- vp.GetJSValue()->SetNull(pRuntime);
-
- return true;
-}
-
-bool Document::pageNum(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (vp.IsGetting()) {
- if (CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetCurrentView())
- vp << pPageView->GetPageIndex();
- return true;
- }
- int iPageCount = m_pFormFillEnv->GetPageCount();
- int iPageNum = 0;
- vp >> iPageNum;
- if (iPageNum >= 0 && iPageNum < iPageCount)
- m_pFormFillEnv->JS_docgotoPage(iPageNum);
- else if (iPageNum >= iPageCount)
- m_pFormFillEnv->JS_docgotoPage(iPageCount - 1);
- else if (iPageNum < 0)
- m_pFormFillEnv->JS_docgotoPage(0);
-
- return true;
-}
-
-bool Document::addAnnot(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Not supported.
- return true;
-}
-
-bool Document::addField(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Not supported.
- return true;
-}
-
-bool Document::exportAsText(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::exportAsFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::exportAsXFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-// Maps a field object in PDF document to a JavaScript variable
-// comment:
-// note: the paremter cName, this is clue how to treat if the cName is not a
-// valiable filed name in this document
-
-bool Document::getField(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() < 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- CFX_WideString wideName = params[0].ToCFXWideString(pRuntime);
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
- if (pPDFForm->CountFields(wideName) <= 0) {
- vRet.SetNull(pRuntime);
- return true;
- }
-
- v8::Local<v8::Object> pFieldObj =
- pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID);
- if (pFieldObj.IsEmpty())
- return false;
-
- CJS_Field* pJSField =
- static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj));
- Field* pField = static_cast<Field*>(pJSField->GetEmbedObject());
- pField->AttachField(this, wideName);
- vRet = CJS_Value(pRuntime, pJSField);
- return true;
-}
-
-// Gets the name of the nth field in the document
-bool Document::getNthFieldName(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- int nIndex = params[0].ToInt(pRuntime);
- if (nIndex < 0) {
- sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
- return false;
- }
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
- CPDF_FormField* pField = pPDFForm->GetField(nIndex, CFX_WideString());
- if (!pField)
- return false;
-
- vRet = CJS_Value(pRuntime, pField->GetFullName().c_str());
- return true;
-}
-
-bool Document::importAnFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::importAnXFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::importTextData(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-// exports the form data and mails the resulting fdf file as an attachment to
-// all recipients.
-// comment: need reader supports
-bool Document::mailForm(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) {
- sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION);
- return false;
- }
- int iLength = params.size();
- bool bUI = iLength > 0 ? params[0].ToBool(pRuntime) : true;
- CFX_WideString cTo = iLength > 1 ? params[1].ToCFXWideString(pRuntime) : L"";
- CFX_WideString cCc = iLength > 2 ? params[2].ToCFXWideString(pRuntime) : L"";
- CFX_WideString cBcc = iLength > 3 ? params[3].ToCFXWideString(pRuntime) : L"";
- CFX_WideString cSubject =
- iLength > 4 ? params[4].ToCFXWideString(pRuntime) : L"";
- CFX_WideString cMsg = iLength > 5 ? params[5].ToCFXWideString(pRuntime) : L"";
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CFX_ByteTextBuf textBuf;
- if (!pInterForm->ExportFormToFDFTextBuf(textBuf))
- return false;
-
- pRuntime->BeginBlock();
- CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
- pFormFillEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI,
- cTo.c_str(), cSubject.c_str(), cCc.c_str(),
- cBcc.c_str(), cMsg.c_str());
- pRuntime->EndBlock();
- return true;
-}
-
-bool Document::print(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- bool bUI = true;
- int nStart = 0;
- int nEnd = 0;
- bool bSilent = false;
- bool bShrinkToFit = false;
- bool bPrintAsImage = false;
- bool bReverse = false;
- bool bAnnotations = false;
- int nlength = params.size();
- if (nlength == 9) {
- if (params[8].GetType() == CJS_Value::VT_object) {
- v8::Local<v8::Object> pObj = params[8].ToV8Object(pRuntime);
- if (CFXJS_Engine::GetObjDefnID(pObj) ==
- CJS_PrintParamsObj::g_nObjDefnID) {
- if (CJS_Object* pJSObj = params[8].ToCJSObject(pRuntime)) {
- if (PrintParamsObj* pprintparamsObj =
- static_cast<PrintParamsObj*>(pJSObj->GetEmbedObject())) {
- bUI = pprintparamsObj->bUI;
- nStart = pprintparamsObj->nStart;
- nEnd = pprintparamsObj->nEnd;
- bSilent = pprintparamsObj->bSilent;
- bShrinkToFit = pprintparamsObj->bShrinkToFit;
- bPrintAsImage = pprintparamsObj->bPrintAsImage;
- bReverse = pprintparamsObj->bReverse;
- bAnnotations = pprintparamsObj->bAnnotations;
- }
- }
- }
- }
- } else {
- if (nlength >= 1)
- bUI = params[0].ToBool(pRuntime);
- if (nlength >= 2)
- nStart = params[1].ToInt(pRuntime);
- if (nlength >= 3)
- nEnd = params[2].ToInt(pRuntime);
- if (nlength >= 4)
- bSilent = params[3].ToBool(pRuntime);
- if (nlength >= 5)
- bShrinkToFit = params[4].ToBool(pRuntime);
- if (nlength >= 6)
- bPrintAsImage = params[5].ToBool(pRuntime);
- if (nlength >= 7)
- bReverse = params[6].ToBool(pRuntime);
- if (nlength >= 8)
- bAnnotations = params[7].ToBool(pRuntime);
- }
-
- if (m_pFormFillEnv) {
- m_pFormFillEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit,
- bPrintAsImage, bReverse, bAnnotations);
- return true;
- }
- return false;
-}
-
-// removes the specified field from the document.
-// comment:
-// note: if the filed name is not rational, adobe is dumb for it.
-
-bool Document::removeField(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) ||
- m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM))) {
- sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION);
- return false;
- }
- CFX_WideString sFieldName = params[0].ToCFXWideString(pRuntime);
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
- pInterForm->GetWidgets(sFieldName, &widgets);
- if (widgets.empty())
- return true;
-
- for (const auto& pAnnot : widgets) {
- CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot.Get());
- if (!pWidget)
- continue;
-
- CFX_FloatRect rcAnnot = pWidget->GetRect();
- --rcAnnot.left;
- --rcAnnot.bottom;
- ++rcAnnot.right;
- ++rcAnnot.top;
-
- std::vector<CFX_FloatRect> aRefresh(1, rcAnnot);
- UnderlyingPageType* pPage = pWidget->GetUnderlyingPage();
- ASSERT(pPage);
-
- // If there is currently no pageview associated with the page being used
- // do not create one. We may be in the process of tearing down the document
- // and creating a new pageview at this point will cause bad things.
- CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(pPage, false);
- if (pPageView) {
-#if PDF_ENABLE_XFA
- pPageView->DeleteAnnot(pWidget);
-#endif // PDF_ENABLE_XFA
- pPageView->UpdateRects(aRefresh);
- }
- }
- m_pFormFillEnv->SetChangeMark();
-
- return true;
-}
-
-// reset filed values within a document.
-// comment:
-// note: if the fields names r not rational, aodbe is dumb for it.
-
-bool Document::resetForm(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) ||
- m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) ||
- m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) {
- sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION);
- return false;
- }
-
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
- CJS_Array aName;
-
- if (params.empty()) {
- pPDFForm->ResetForm(true);
- m_pFormFillEnv->SetChangeMark();
- return true;
- }
-
- switch (params[0].GetType()) {
- default:
- aName.Attach(params[0].ToV8Array(pRuntime));
- break;
- case CJS_Value::VT_string:
- aName.SetElement(pRuntime, 0, params[0]);
- break;
- }
-
- std::vector<CPDF_FormField*> aFields;
- for (int i = 0, isz = aName.GetLength(pRuntime); i < isz; ++i) {
- CJS_Value valElement(pRuntime);
- aName.GetElement(pRuntime, i, valElement);
- CFX_WideString swVal = valElement.ToCFXWideString(pRuntime);
- for (int j = 0, jsz = pPDFForm->CountFields(swVal); j < jsz; ++j)
- aFields.push_back(pPDFForm->GetField(j, swVal));
- }
-
- if (!aFields.empty()) {
- pPDFForm->ResetForm(aFields, true, true);
- m_pFormFillEnv->SetChangeMark();
- }
-
- return true;
-}
-
-bool Document::saveAs(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::syncAnnotScan(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::submitForm(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int nSize = params.size();
- if (nSize < 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
-
- CJS_Array aFields;
- CFX_WideString strURL;
- bool bFDF = true;
- bool bEmpty = false;
- CJS_Value v = params[0];
- if (v.GetType() == CJS_Value::VT_string) {
- strURL = params[0].ToCFXWideString(pRuntime);
- if (nSize > 1)
- bFDF = params[1].ToBool(pRuntime);
- if (nSize > 2)
- bEmpty = params[2].ToBool(pRuntime);
- if (nSize > 3)
- aFields.Attach(params[3].ToV8Array(pRuntime));
- } else if (v.GetType() == CJS_Value::VT_object) {
- v8::Local<v8::Object> pObj = params[0].ToV8Object(pRuntime);
- v8::Local<v8::Value> pValue = pRuntime->GetObjectProperty(pObj, L"cURL");
- if (!pValue.IsEmpty())
- strURL = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime);
-
- pValue = pRuntime->GetObjectProperty(pObj, L"bFDF");
- bFDF = CJS_Value(pRuntime, pValue).ToBool(pRuntime);
-
- pValue = pRuntime->GetObjectProperty(pObj, L"bEmpty");
- bEmpty = CJS_Value(pRuntime, pValue).ToBool(pRuntime);
-
- pValue = pRuntime->GetObjectProperty(pObj, L"aFields");
- aFields.Attach(CJS_Value(pRuntime, pValue).ToV8Array(pRuntime));
- }
-
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDF_InterForm* pPDFInterForm = pInterForm->GetInterForm();
- if (aFields.GetLength(pRuntime) == 0 && bEmpty) {
- if (pPDFInterForm->CheckRequiredFields(nullptr, true)) {
- pRuntime->BeginBlock();
- pInterForm->SubmitForm(strURL, false);
- pRuntime->EndBlock();
- }
- return true;
- }
-
- std::vector<CPDF_FormField*> fieldObjects;
- for (int i = 0, sz = aFields.GetLength(pRuntime); i < sz; ++i) {
- CJS_Value valName(pRuntime);
- aFields.GetElement(pRuntime, i, valName);
-
- CFX_WideString sName = valName.ToCFXWideString(pRuntime);
- CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
- for (int j = 0, jsz = pPDFForm->CountFields(sName); j < jsz; ++j) {
- CPDF_FormField* pField = pPDFForm->GetField(j, sName);
- if (!bEmpty && pField->GetValue().IsEmpty())
- continue;
-
- fieldObjects.push_back(pField);
- }
- }
-
- if (pPDFInterForm->CheckRequiredFields(&fieldObjects, true)) {
- pRuntime->BeginBlock();
- pInterForm->SubmitFields(strURL, fieldObjects, true, !bFDF);
- pRuntime->EndBlock();
- }
- return true;
-}
-
-void Document::SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pFormFillEnv.Reset(pFormFillEnv);
-}
-
-bool Document::bookmarkRoot(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::mailDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // TODO(tsepez): Check maximum number of allowed params.
- bool bUI = true;
- CFX_WideString cTo = L"";
- CFX_WideString cCc = L"";
- CFX_WideString cBcc = L"";
- CFX_WideString cSubject = L"";
- CFX_WideString cMsg = L"";
-
- if (params.size() >= 1)
- bUI = params[0].ToBool(pRuntime);
- if (params.size() >= 2)
- cTo = params[1].ToCFXWideString(pRuntime);
- if (params.size() >= 3)
- cCc = params[2].ToCFXWideString(pRuntime);
- if (params.size() >= 4)
- cBcc = params[3].ToCFXWideString(pRuntime);
- if (params.size() >= 5)
- cSubject = params[4].ToCFXWideString(pRuntime);
- if (params.size() >= 6)
- cMsg = params[5].ToCFXWideString(pRuntime);
-
- if (params.size() >= 1 && params[0].GetType() == CJS_Value::VT_object) {
- v8::Local<v8::Object> pObj = params[0].ToV8Object(pRuntime);
-
- v8::Local<v8::Value> pValue = pRuntime->GetObjectProperty(pObj, L"bUI");
- bUI = CJS_Value(pRuntime, pValue).ToBool(pRuntime);
-
- pValue = pRuntime->GetObjectProperty(pObj, L"cTo");
- cTo = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime);
-
- pValue = pRuntime->GetObjectProperty(pObj, L"cCc");
- cCc = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime);
-
- pValue = pRuntime->GetObjectProperty(pObj, L"cBcc");
- cBcc = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime);
-
- pValue = pRuntime->GetObjectProperty(pObj, L"cSubject");
- cSubject = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime);
-
- pValue = pRuntime->GetObjectProperty(pObj, L"cMsg");
- cMsg = CJS_Value(pRuntime, pValue).ToCFXWideString(pRuntime);
- }
-
- pRuntime->BeginBlock();
- CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
- pFormFillEnv->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(), cSubject.c_str(),
- cCc.c_str(), cBcc.c_str(), cMsg.c_str());
- pRuntime->EndBlock();
- return true;
-}
-
-bool Document::author(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return getPropertyInternal(pRuntime, vp, "Author", sError);
-}
-
-bool Document::info(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo();
- if (!pDictionary)
- return false;
-
- CFX_WideString cwAuthor = pDictionary->GetUnicodeTextFor("Author");
- CFX_WideString cwTitle = pDictionary->GetUnicodeTextFor("Title");
- CFX_WideString cwSubject = pDictionary->GetUnicodeTextFor("Subject");
- CFX_WideString cwKeywords = pDictionary->GetUnicodeTextFor("Keywords");
- CFX_WideString cwCreator = pDictionary->GetUnicodeTextFor("Creator");
- CFX_WideString cwProducer = pDictionary->GetUnicodeTextFor("Producer");
- CFX_WideString cwCreationDate =
- pDictionary->GetUnicodeTextFor("CreationDate");
- CFX_WideString cwModDate = pDictionary->GetUnicodeTextFor("ModDate");
- CFX_WideString cwTrapped = pDictionary->GetUnicodeTextFor("Trapped");
-
- v8::Local<v8::Object> pObj = pRuntime->NewFxDynamicObj(-1);
- pRuntime->PutObjectProperty(pObj, L"Author",
- pRuntime->NewString(cwAuthor.AsStringC()));
- pRuntime->PutObjectProperty(pObj, L"Title",
- pRuntime->NewString(cwTitle.AsStringC()));
- pRuntime->PutObjectProperty(pObj, L"Subject",
- pRuntime->NewString(cwSubject.AsStringC()));
- pRuntime->PutObjectProperty(pObj, L"Keywords",
- pRuntime->NewString(cwKeywords.AsStringC()));
- pRuntime->PutObjectProperty(pObj, L"Creator",
- pRuntime->NewString(cwCreator.AsStringC()));
- pRuntime->PutObjectProperty(pObj, L"Producer",
- pRuntime->NewString(cwProducer.AsStringC()));
- pRuntime->PutObjectProperty(pObj, L"CreationDate",
- pRuntime->NewString(cwCreationDate.AsStringC()));
- pRuntime->PutObjectProperty(pObj, L"ModDate",
- pRuntime->NewString(cwModDate.AsStringC()));
- pRuntime->PutObjectProperty(pObj, L"Trapped",
- pRuntime->NewString(cwTrapped.AsStringC()));
-
- // It's to be compatible to non-standard info dictionary.
- for (const auto& it : *pDictionary) {
- const CFX_ByteString& bsKey = it.first;
- CPDF_Object* pValueObj = it.second.get();
- CFX_WideString wsKey = CFX_WideString::FromUTF8(bsKey.AsStringC());
- if (pValueObj->IsString() || pValueObj->IsName()) {
- pRuntime->PutObjectProperty(
- pObj, wsKey,
- pRuntime->NewString(pValueObj->GetUnicodeText().AsStringC()));
- } else if (pValueObj->IsNumber()) {
- pRuntime->PutObjectProperty(pObj, wsKey,
- pRuntime->NewNumber(pValueObj->GetNumber()));
- } else if (pValueObj->IsBoolean()) {
- pRuntime->PutObjectProperty(
- pObj, wsKey, pRuntime->NewBoolean(!!pValueObj->GetInteger()));
- }
- }
- vp << pObj;
- return true;
-}
-
-bool Document::getPropertyInternal(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- const CFX_ByteString& propName,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- CPDF_Dictionary* pDictionary = m_pFormFillEnv->GetPDFDocument()->GetInfo();
- if (!pDictionary)
- return false;
-
- if (vp.IsGetting()) {
- vp << pDictionary->GetUnicodeTextFor(propName);
- } else {
- if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY)) {
- sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION);
- return false;
- }
- CFX_WideString csProperty;
- vp >> csProperty;
- pDictionary->SetNewFor<CPDF_String>(propName, PDF_EncodeText(csProperty),
- false);
- m_pFormFillEnv->SetChangeMark();
- }
- return true;
-}
-
-bool Document::creationDate(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return getPropertyInternal(pRuntime, vp, "CreationDate", sError);
-}
-
-bool Document::creator(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return getPropertyInternal(pRuntime, vp, "Creator", sError);
-}
-
-bool Document::delay(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (vp.IsGetting()) {
- vp << m_bDelay;
- return true;
- }
- if (!m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY)) {
- sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION);
- return false;
- }
- vp >> m_bDelay;
- if (m_bDelay) {
- m_DelayData.clear();
- return true;
- }
- std::list<std::unique_ptr<CJS_DelayData>> DelayDataToProcess;
- DelayDataToProcess.swap(m_DelayData);
- for (const auto& pData : DelayDataToProcess)
- Field::DoDelay(m_pFormFillEnv.Get(), pData.get());
-
- return true;
-}
-
-bool Document::keywords(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return getPropertyInternal(pRuntime, vp, "Keywords", sError);
-}
-
-bool Document::modDate(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return getPropertyInternal(pRuntime, vp, "ModDate", sError);
-}
-
-bool Document::producer(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return getPropertyInternal(pRuntime, vp, "Producer", sError);
-}
-
-bool Document::subject(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return getPropertyInternal(pRuntime, vp, "Subject", sError);
-}
-
-bool Document::title(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv || !m_pFormFillEnv->GetUnderlyingDocument()) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- return getPropertyInternal(pRuntime, vp, "Title", sError);
-}
-
-bool Document::numPages(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- vp << m_pFormFillEnv->GetPageCount();
- return true;
-}
-
-bool Document::external(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- // In Chrome case, should always return true.
- if (vp.IsGetting()) {
- vp << true;
- }
- return true;
-}
-
-bool Document::filesize(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- vp << 0;
- return true;
-}
-
-bool Document::mouseX(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::mouseY(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::URL(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- vp << m_pFormFillEnv->JS_docGetFilePath();
- return true;
-}
-
-bool Document::baseURL(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsGetting()) {
- vp << m_cwBaseURL;
- } else {
- vp >> m_cwBaseURL;
- }
- return true;
-}
-
-bool Document::calculate(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- if (vp.IsGetting()) {
- vp << !!pInterForm->IsCalculateEnabled();
- return true;
- }
- bool bCalculate;
- vp >> bCalculate;
- pInterForm->EnableCalculate(bCalculate);
- return true;
-}
-
-bool Document::documentFileName(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- CFX_WideString wsFilePath = m_pFormFillEnv->JS_docGetFilePath();
- int32_t i = wsFilePath.GetLength() - 1;
- for (; i >= 0; i--) {
- if (wsFilePath.GetAt(i) == L'\\' || wsFilePath.GetAt(i) == L'/')
- break;
- }
- if (i >= 0 && i < wsFilePath.GetLength() - 1) {
- vp << (wsFilePath.GetBuffer(wsFilePath.GetLength()) + i + 1);
- } else {
- vp << L"";
- }
- return true;
-}
-
-bool Document::path(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- vp << app::SysPathToPDFPath(m_pFormFillEnv->JS_docGetFilePath());
- return true;
-}
-
-bool Document::pageWindowRect(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::layout(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::addLink(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::closeDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::getPageBox(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::getAnnot(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 2) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- int nPageNo = params[0].ToInt(pRuntime);
- CFX_WideString swAnnotName = params[1].ToCFXWideString(pRuntime);
- CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(nPageNo);
- if (!pPageView)
- return false;
-
- CPDFSDK_AnnotIteration annotIteration(pPageView, false);
- CPDFSDK_BAAnnot* pSDKBAAnnot = nullptr;
- for (const auto& pSDKAnnotCur : annotIteration) {
- CPDFSDK_BAAnnot* pBAAnnot =
- static_cast<CPDFSDK_BAAnnot*>(pSDKAnnotCur.Get());
- if (pBAAnnot && pBAAnnot->GetAnnotName() == swAnnotName) {
- pSDKBAAnnot = pBAAnnot;
- break;
- }
- }
- if (!pSDKBAAnnot)
- return false;
-
- v8::Local<v8::Object> pObj =
- pRuntime->NewFxDynamicObj(CJS_Annot::g_nObjDefnID);
- if (pObj.IsEmpty())
- return false;
-
- CJS_Annot* pJS_Annot =
- static_cast<CJS_Annot*>(pRuntime->GetObjectPrivate(pObj));
- Annot* pAnnot = static_cast<Annot*>(pJS_Annot->GetEmbedObject());
- pAnnot->SetSDKAnnot(pSDKBAAnnot);
- vRet = CJS_Value(pRuntime, pJS_Annot);
- return true;
-}
-
-bool Document::getAnnots(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- // TODO(tonikitoo): Add support supported parameters as per
- // the PDF spec.
-
- int nPageNo = m_pFormFillEnv->GetPageCount();
- CJS_Array annots;
-
- for (int i = 0; i < nPageNo; ++i) {
- CPDFSDK_PageView* pPageView = m_pFormFillEnv->GetPageView(i);
- if (!pPageView)
- return false;
-
- CPDFSDK_AnnotIteration annotIteration(pPageView, false);
- for (const auto& pSDKAnnotCur : annotIteration) {
- if (!pSDKAnnotCur) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- v8::Local<v8::Object> pObj =
- pRuntime->NewFxDynamicObj(CJS_Annot::g_nObjDefnID);
- if (pObj.IsEmpty())
- return false;
-
- CJS_Annot* pJS_Annot =
- static_cast<CJS_Annot*>(pRuntime->GetObjectPrivate(pObj));
- Annot* pAnnot = static_cast<Annot*>(pJS_Annot->GetEmbedObject());
- pAnnot->SetSDKAnnot(static_cast<CPDFSDK_BAAnnot*>(pSDKAnnotCur.Get()));
- annots.SetElement(pRuntime, i, CJS_Value(pRuntime, pJS_Annot));
- }
- }
- vRet = CJS_Value(pRuntime, annots);
- return true;
-}
-
-bool Document::getAnnot3D(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- vRet.SetNull(pRuntime);
- return true;
-}
-
-bool Document::getAnnots3D(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::getOCGs(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::getLinks(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect) {
- return (rect.left <= LinkRect.left && rect.top <= LinkRect.top &&
- rect.right >= LinkRect.right && rect.bottom >= LinkRect.bottom);
-}
-
-bool Document::addIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 2) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CFX_WideString swIconName = params[0].ToCFXWideString(pRuntime);
- if (params[1].GetType() != CJS_Value::VT_object) {
- sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR);
- return false;
- }
-
- v8::Local<v8::Object> pJSIcon = params[1].ToV8Object(pRuntime);
- if (pRuntime->GetObjDefnID(pJSIcon) != CJS_Icon::g_nObjDefnID) {
- sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR);
- return false;
- }
-
- if (!params[1].ToCJSObject(pRuntime)->GetEmbedObject()) {
- sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR);
- return false;
- }
-
- m_IconNames.push_back(swIconName);
- return true;
-}
-
-bool Document::icons(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
- if (m_IconNames.empty()) {
- vp.GetJSValue()->SetNull(pRuntime);
- return true;
- }
-
- CJS_Array Icons;
- int i = 0;
- for (const auto& name : m_IconNames) {
- v8::Local<v8::Object> pObj =
- pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID);
- if (pObj.IsEmpty())
- return false;
-
- CJS_Icon* pJS_Icon =
- static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj));
- Icon* pIcon = static_cast<Icon*>(pJS_Icon->GetEmbedObject());
- pIcon->SetIconName(name);
- Icons.SetElement(pRuntime, i++, CJS_Value(pRuntime, pJS_Icon));
- }
-
- vp << Icons;
- return true;
-}
-
-bool Document::getIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CFX_WideString swIconName = params[0].ToCFXWideString(pRuntime);
- auto it = std::find(m_IconNames.begin(), m_IconNames.end(), swIconName);
- if (it == m_IconNames.end())
- return false;
-
- v8::Local<v8::Object> pObj =
- pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID);
- if (pObj.IsEmpty())
- return false;
-
- CJS_Icon* pJS_Icon = static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj));
- Icon* pIcon = static_cast<Icon*>(pJS_Icon->GetEmbedObject());
- pIcon->SetIconName(*it);
- vRet = CJS_Value(pRuntime, pJS_Icon);
- return true;
-}
-
-bool Document::removeIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, no supported.
- return true;
-}
-
-bool Document::createDataObject(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not implemented.
- return true;
-}
-
-bool Document::media(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::calculateNow(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (!(m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY) ||
- m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) ||
- m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM))) {
- sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION);
- return false;
- }
- m_pFormFillEnv->GetInterForm()->OnCalculate();
- return true;
-}
-
-bool Document::Collab(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::getPageNthWord(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) {
- sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION);
- return false;
- }
-
- // TODO(tsepez): check maximum allowable params.
-
- int nPageNo = params.size() > 0 ? params[0].ToInt(pRuntime) : 0;
- int nWordNo = params.size() > 1 ? params[1].ToInt(pRuntime) : 0;
- bool bStrip = params.size() > 2 ? params[2].ToBool(pRuntime) : true;
-
- CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
- if (!pDocument)
- return false;
-
- if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) {
- sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
- return false;
- }
-
- CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo);
- if (!pPageDict)
- return false;
-
- CPDF_Page page(pDocument, pPageDict, true);
- page.ParseContent();
-
- int nWords = 0;
- CFX_WideString swRet;
- for (auto& pPageObj : *page.GetPageObjectList()) {
- if (pPageObj->IsText()) {
- CPDF_TextObject* pTextObj = pPageObj->AsText();
- int nObjWords = CountWords(pTextObj);
- if (nWords + nObjWords >= nWordNo) {
- swRet = GetObjWordStr(pTextObj, nWordNo - nWords);
- break;
- }
- nWords += nObjWords;
- }
- }
-
- if (bStrip) {
- swRet.TrimLeft();
- swRet.TrimRight();
- }
-
- vRet = CJS_Value(pRuntime, swRet.c_str());
- return true;
-}
-
-bool Document::getPageNthWordQuads(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- return false;
-}
-
-bool Document::getPageNumWords(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- if (!m_pFormFillEnv->GetPermissions(FPDFPERM_EXTRACT_ACCESS)) {
- sError = JSGetStringFromID(IDS_STRING_JSNOPERMISSION);
- return false;
- }
- int nPageNo = params.size() > 0 ? params[0].ToInt(pRuntime) : 0;
- CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
- if (nPageNo < 0 || nPageNo >= pDocument->GetPageCount()) {
- sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
- return false;
- }
-
- CPDF_Dictionary* pPageDict = pDocument->GetPage(nPageNo);
- if (!pPageDict)
- return false;
-
- CPDF_Page page(pDocument, pPageDict, true);
- page.ParseContent();
-
- int nWords = 0;
- for (auto& pPageObj : *page.GetPageObjectList()) {
- if (pPageObj->IsText())
- nWords += CountWords(pPageObj->AsText());
- }
-
- vRet = CJS_Value(pRuntime, nWords);
- return true;
-}
-
-bool Document::getPrintParams(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- v8::Local<v8::Object> pRetObj =
- pRuntime->NewFxDynamicObj(CJS_PrintParamsObj::g_nObjDefnID);
- if (pRetObj.IsEmpty())
- return false;
-
- // Not implemented yet.
-
- vRet = CJS_Value(pRuntime, pRetObj);
- return true;
-}
-
-#define ISLATINWORD(u) (u != 0x20 && u <= 0x28FF)
-
-int Document::CountWords(CPDF_TextObject* pTextObj) {
- if (!pTextObj)
- return 0;
-
- int nWords = 0;
-
- CPDF_Font* pFont = pTextObj->GetFont();
- if (!pFont)
- return 0;
-
- bool bIsLatin = false;
-
- for (int i = 0, sz = pTextObj->CountChars(); i < sz; i++) {
- uint32_t charcode = CPDF_Font::kInvalidCharCode;
- FX_FLOAT kerning;
-
- pTextObj->GetCharInfo(i, &charcode, &kerning);
- CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode);
-
- uint16_t unicode = 0;
- if (swUnicode.GetLength() > 0)
- unicode = swUnicode[0];
-
- if (ISLATINWORD(unicode) && bIsLatin)
- continue;
-
- bIsLatin = ISLATINWORD(unicode);
- if (unicode != 0x20)
- nWords++;
- }
-
- return nWords;
-}
-
-CFX_WideString Document::GetObjWordStr(CPDF_TextObject* pTextObj,
- int nWordIndex) {
- CFX_WideString swRet;
-
- CPDF_Font* pFont = pTextObj->GetFont();
- if (!pFont)
- return L"";
-
- int nWords = 0;
- bool bIsLatin = false;
-
- for (int i = 0, sz = pTextObj->CountChars(); i < sz; i++) {
- uint32_t charcode = CPDF_Font::kInvalidCharCode;
- FX_FLOAT kerning;
-
- pTextObj->GetCharInfo(i, &charcode, &kerning);
- CFX_WideString swUnicode = pFont->UnicodeFromCharCode(charcode);
-
- uint16_t unicode = 0;
- if (swUnicode.GetLength() > 0)
- unicode = swUnicode[0];
-
- if (ISLATINWORD(unicode) && bIsLatin) {
- } else {
- bIsLatin = ISLATINWORD(unicode);
- if (unicode != 0x20)
- nWords++;
- }
-
- if (nWords - 1 == nWordIndex)
- swRet += unicode;
- }
-
- return swRet;
-}
-
-bool Document::zoom(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-/**
-(none, NoVary)
-(fitP, FitPage)
-(fitW, FitWidth)
-(fitH, FitHeight)
-(fitV, FitVisibleWidth)
-(pref, Preferred)
-(refW, ReflowWidth)
-*/
-
-bool Document::zoomType(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Document::deletePages(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, no supported.
- return true;
-}
-
-bool Document::extractPages(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::insertPages(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::replacePages(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::getURL(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Document::gotoNamedDest(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- if (!m_pFormFillEnv) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
- CFX_WideString wideName = params[0].ToCFXWideString(pRuntime);
- CFX_ByteString utf8Name = wideName.UTF8Encode();
- CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
- if (!pDocument)
- return false;
-
- CPDF_NameTree nameTree(pDocument, "Dests");
- CPDF_Array* destArray = nameTree.LookupNamedDest(pDocument, utf8Name);
- if (!destArray)
- return false;
-
- CPDF_Dest dest(destArray);
- const CPDF_Array* arrayObject = ToArray(dest.GetObject());
-
- std::unique_ptr<float[]> scrollPositionArray;
- int scrollPositionArraySize = 0;
-
- if (arrayObject) {
- scrollPositionArray.reset(new float[arrayObject->GetCount()]);
- int j = 0;
- for (size_t i = 2; i < arrayObject->GetCount(); i++)
- scrollPositionArray[j++] = arrayObject->GetFloatAt(i);
- scrollPositionArraySize = j;
- }
-
- pRuntime->BeginBlock();
- m_pFormFillEnv->DoGoToAction(dest.GetPageIndex(pDocument), dest.GetZoomMode(),
- scrollPositionArray.get(),
- scrollPositionArraySize);
- pRuntime->EndBlock();
-
- return true;
-}
-
-void Document::AddDelayData(CJS_DelayData* pData) {
- m_DelayData.push_back(std::unique_ptr<CJS_DelayData>(pData));
-}
-
-void Document::DoFieldDelay(const CFX_WideString& sFieldName,
- int nControlIndex) {
- std::vector<std::unique_ptr<CJS_DelayData>> DelayDataForFieldAndControlIndex;
- auto iter = m_DelayData.begin();
- while (iter != m_DelayData.end()) {
- auto old = iter++;
- if ((*old)->sFieldName == sFieldName &&
- (*old)->nControlIndex == nControlIndex) {
- DelayDataForFieldAndControlIndex.push_back(std::move(*old));
- m_DelayData.erase(old);
- }
- }
-
- for (const auto& pData : DelayDataForFieldAndControlIndex)
- Field::DoDelay(m_pFormFillEnv.Get(), pData.get());
-}
-
-CJS_Document* Document::GetCJSDoc() const {
- return static_cast<CJS_Document*>(m_pJSObject);
-}
diff --git a/fpdfsdk/javascript/Document.h b/fpdfsdk/javascript/Document.h
deleted file mode 100644
index 91ca778..0000000
--- a/fpdfsdk/javascript/Document.h
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_DOCUMENT_H_
-#define FPDFSDK_JAVASCRIPT_DOCUMENT_H_
-
-#include <list>
-#include <memory>
-#include <vector>
-
-#include "core/fpdfapi/page/cpdf_pageobject.h"
-#include "core/fpdfapi/page/cpdf_textobject.h"
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class PrintParamsObj : public CJS_EmbedObj {
- public:
- explicit PrintParamsObj(CJS_Object* pJSObject);
- ~PrintParamsObj() override {}
-
- public:
- bool bUI;
- int nStart;
- int nEnd;
- bool bSilent;
- bool bShrinkToFit;
- bool bPrintAsImage;
- bool bReverse;
- bool bAnnotations;
-};
-
-class CJS_PrintParamsObj : public CJS_Object {
- public:
- explicit CJS_PrintParamsObj(v8::Local<v8::Object> pObject)
- : CJS_Object(pObject) {}
- ~CJS_PrintParamsObj() override {}
-
- DECLARE_JS_CLASS();
-};
-
-struct CJS_AnnotObj;
-struct CJS_DelayAnnot;
-struct CJS_DelayData;
-
-class Document : public CJS_EmbedObj {
- public:
- explicit Document(CJS_Object* pJSObject);
- ~Document() override;
-
- bool ADBE(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool author(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool baseURL(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool bookmarkRoot(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool calculate(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool Collab(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool creationDate(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool creator(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool delay(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool dirty(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool documentFileName(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool external(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool filesize(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool icons(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool info(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool keywords(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool layout(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool media(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool modDate(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool mouseX(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool mouseY(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool numFields(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool numPages(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool pageNum(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool pageWindowRect(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool path(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool producer(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool subject(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool title(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool zoom(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool zoomType(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
-
- bool addAnnot(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool addField(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool addLink(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool addIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool calculateNow(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool closeDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool createDataObject(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool deletePages(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool exportAsText(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool exportAsFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool exportAsXFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool extractPages(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getAnnot(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getAnnots(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getAnnot3D(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getAnnots3D(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getField(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getLinks(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getNthFieldName(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getOCGs(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getPageBox(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getPageNthWord(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getPageNthWordQuads(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getPageNumWords(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getPrintParams(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getURL(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool gotoNamedDest(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool importAnFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool importAnXFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool importTextData(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool insertPages(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool mailForm(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool print(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool removeField(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool replacePages(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool resetForm(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool saveAs(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool submitForm(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool syncAnnotScan(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool mailDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool removeIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool URL(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
-
- void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- CPDFSDK_FormFillEnvironment* GetFormFillEnv() const {
- return m_pFormFillEnv.Get();
- }
- void AddDelayData(CJS_DelayData* pData);
- void DoFieldDelay(const CFX_WideString& sFieldName, int nControlIndex);
- CJS_Document* GetCJSDoc() const;
-
- private:
- bool IsEnclosedInRect(CFX_FloatRect rect, CFX_FloatRect LinkRect);
- int CountWords(CPDF_TextObject* pTextObj);
- CFX_WideString GetObjWordStr(CPDF_TextObject* pTextObj, int nWordIndex);
-
- bool getPropertyInternal(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- const CFX_ByteString& propName,
- CFX_WideString& sError);
-
- CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
- CFX_WideString m_cwBaseURL;
- std::list<std::unique_ptr<CJS_DelayData>> m_DelayData;
- // Needs to be a std::list for iterator stability.
- std::list<CFX_WideString> m_IconNames;
- bool m_bDelay;
-};
-
-class CJS_Document : public CJS_Object {
- public:
- explicit CJS_Document(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Document() override {}
-
- // CJS_Object
- void InitInstance(IJS_Runtime* pIRuntime) override;
-
- DECLARE_JS_CLASS();
-
- JS_STATIC_PROP(ADBE, Document);
- JS_STATIC_PROP(author, Document);
- JS_STATIC_PROP(baseURL, Document);
- JS_STATIC_PROP(bookmarkRoot, Document);
- JS_STATIC_PROP(calculate, Document);
- JS_STATIC_PROP(Collab, Document);
- JS_STATIC_PROP(creationDate, Document);
- JS_STATIC_PROP(creator, Document);
- JS_STATIC_PROP(delay, Document);
- JS_STATIC_PROP(dirty, Document);
- JS_STATIC_PROP(documentFileName, Document);
- JS_STATIC_PROP(external, Document);
- JS_STATIC_PROP(filesize, Document);
- JS_STATIC_PROP(icons, Document);
- JS_STATIC_PROP(info, Document);
- JS_STATIC_PROP(keywords, Document);
- JS_STATIC_PROP(layout, Document);
- JS_STATIC_PROP(media, Document);
- JS_STATIC_PROP(modDate, Document);
- JS_STATIC_PROP(mouseX, Document);
- JS_STATIC_PROP(mouseY, Document);
- JS_STATIC_PROP(numFields, Document);
- JS_STATIC_PROP(numPages, Document);
- JS_STATIC_PROP(pageNum, Document);
- JS_STATIC_PROP(pageWindowRect, Document);
- JS_STATIC_PROP(path, Document);
- JS_STATIC_PROP(producer, Document);
- JS_STATIC_PROP(subject, Document);
- JS_STATIC_PROP(title, Document);
- JS_STATIC_PROP(URL, Document);
- JS_STATIC_PROP(zoom, Document);
- JS_STATIC_PROP(zoomType, Document);
-
- JS_STATIC_METHOD(addAnnot, Document);
- JS_STATIC_METHOD(addField, Document);
- JS_STATIC_METHOD(addLink, Document);
- JS_STATIC_METHOD(addIcon, Document);
- JS_STATIC_METHOD(calculateNow, Document);
- JS_STATIC_METHOD(closeDoc, Document);
- JS_STATIC_METHOD(createDataObject, Document);
- JS_STATIC_METHOD(deletePages, Document);
- JS_STATIC_METHOD(exportAsText, Document);
- JS_STATIC_METHOD(exportAsFDF, Document);
- JS_STATIC_METHOD(exportAsXFDF, Document);
- JS_STATIC_METHOD(extractPages, Document);
- JS_STATIC_METHOD(getAnnot, Document);
- JS_STATIC_METHOD(getAnnots, Document);
- JS_STATIC_METHOD(getAnnot3D, Document);
- JS_STATIC_METHOD(getAnnots3D, Document);
- JS_STATIC_METHOD(getField, Document);
- JS_STATIC_METHOD(getIcon, Document);
- JS_STATIC_METHOD(getLinks, Document);
- JS_STATIC_METHOD(getNthFieldName, Document);
- JS_STATIC_METHOD(getOCGs, Document);
- JS_STATIC_METHOD(getPageBox, Document);
- JS_STATIC_METHOD(getPageNthWord, Document);
- JS_STATIC_METHOD(getPageNthWordQuads, Document);
- JS_STATIC_METHOD(getPageNumWords, Document);
- JS_STATIC_METHOD(getPrintParams, Document);
- JS_STATIC_METHOD(getURL, Document);
- JS_STATIC_METHOD(gotoNamedDest, Document);
- JS_STATIC_METHOD(importAnFDF, Document);
- JS_STATIC_METHOD(importAnXFDF, Document);
- JS_STATIC_METHOD(importTextData, Document);
- JS_STATIC_METHOD(insertPages, Document);
- JS_STATIC_METHOD(mailForm, Document);
- JS_STATIC_METHOD(print, Document);
- JS_STATIC_METHOD(removeField, Document);
- JS_STATIC_METHOD(replacePages, Document);
- JS_STATIC_METHOD(removeIcon, Document);
- JS_STATIC_METHOD(resetForm, Document);
- JS_STATIC_METHOD(saveAs, Document);
- JS_STATIC_METHOD(submitForm, Document);
- JS_STATIC_METHOD(syncAnnotScan, Document);
- JS_STATIC_METHOD(mailDoc, Document);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_DOCUMENT_H_
diff --git a/fpdfsdk/javascript/Field.cpp b/fpdfsdk/javascript/Field.cpp
deleted file mode 100644
index f37b3d4..0000000
--- a/fpdfsdk/javascript/Field.cpp
+++ /dev/null
@@ -1,3405 +0,0 @@
-// Copyright 2014 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/javascript/Field.h"
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "core/fpdfapi/font/cpdf_font.h"
-#include "core/fpdfapi/page/cpdf_page.h"
-#include "core/fpdfapi/parser/cpdf_document.h"
-#include "core/fpdfdoc/cpdf_interform.h"
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/cpdfsdk_interform.h"
-#include "fpdfsdk/cpdfsdk_pageview.h"
-#include "fpdfsdk/cpdfsdk_widget.h"
-#include "fpdfsdk/javascript/Document.h"
-#include "fpdfsdk/javascript/Icon.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/PublicMethods.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fpdfsdk/javascript/color.h"
-
-namespace {
-
-bool SetWidgetDisplayStatus(CPDFSDK_Widget* pWidget, int value) {
- if (!pWidget)
- return false;
-
- uint32_t dwFlag = pWidget->GetFlags();
- switch (value) {
- case 0:
- dwFlag &= ~ANNOTFLAG_INVISIBLE;
- dwFlag &= ~ANNOTFLAG_HIDDEN;
- dwFlag &= ~ANNOTFLAG_NOVIEW;
- dwFlag |= ANNOTFLAG_PRINT;
- break;
- case 1:
- dwFlag &= ~ANNOTFLAG_INVISIBLE;
- dwFlag &= ~ANNOTFLAG_NOVIEW;
- dwFlag |= (ANNOTFLAG_HIDDEN | ANNOTFLAG_PRINT);
- break;
- case 2:
- dwFlag &= ~ANNOTFLAG_INVISIBLE;
- dwFlag &= ~ANNOTFLAG_PRINT;
- dwFlag &= ~ANNOTFLAG_HIDDEN;
- dwFlag &= ~ANNOTFLAG_NOVIEW;
- break;
- case 3:
- dwFlag |= ANNOTFLAG_NOVIEW;
- dwFlag |= ANNOTFLAG_PRINT;
- dwFlag &= ~ANNOTFLAG_HIDDEN;
- break;
- }
-
- if (dwFlag != pWidget->GetFlags()) {
- pWidget->SetFlags(dwFlag);
- return true;
- }
-
- return false;
-}
-
-} // namespace
-
-JSConstSpec CJS_Field::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Field::PropertySpecs[] = {
- {"alignment", get_alignment_static, set_alignment_static},
- {"borderStyle", get_borderStyle_static, set_borderStyle_static},
- {"buttonAlignX", get_buttonAlignX_static, set_buttonAlignX_static},
- {"buttonAlignY", get_buttonAlignY_static, set_buttonAlignY_static},
- {"buttonFitBounds", get_buttonFitBounds_static, set_buttonFitBounds_static},
- {"buttonPosition", get_buttonPosition_static, set_buttonPosition_static},
- {"buttonScaleHow", get_buttonScaleHow_static, set_buttonScaleHow_static},
- {"buttonScaleWhen", get_buttonScaleWhen_static, set_buttonScaleWhen_static},
- {"calcOrderIndex", get_calcOrderIndex_static, set_calcOrderIndex_static},
- {"charLimit", get_charLimit_static, set_charLimit_static},
- {"comb", get_comb_static, set_comb_static},
- {"commitOnSelChange", get_commitOnSelChange_static,
- set_commitOnSelChange_static},
- {"currentValueIndices", get_currentValueIndices_static,
- set_currentValueIndices_static},
- {"defaultStyle", get_defaultStyle_static, set_defaultStyle_static},
- {"defaultValue", get_defaultValue_static, set_defaultValue_static},
- {"doNotScroll", get_doNotScroll_static, set_doNotScroll_static},
- {"doNotSpellCheck", get_doNotSpellCheck_static, set_doNotSpellCheck_static},
- {"delay", get_delay_static, set_delay_static},
- {"display", get_display_static, set_display_static},
- {"doc", get_doc_static, set_doc_static},
- {"editable", get_editable_static, set_editable_static},
- {"exportValues", get_exportValues_static, set_exportValues_static},
- {"hidden", get_hidden_static, set_hidden_static},
- {"fileSelect", get_fileSelect_static, set_fileSelect_static},
- {"fillColor", get_fillColor_static, set_fillColor_static},
- {"lineWidth", get_lineWidth_static, set_lineWidth_static},
- {"highlight", get_highlight_static, set_highlight_static},
- {"multiline", get_multiline_static, set_multiline_static},
- {"multipleSelection", get_multipleSelection_static,
- set_multipleSelection_static},
- {"name", get_name_static, set_name_static},
- {"numItems", get_numItems_static, set_numItems_static},
- {"page", get_page_static, set_page_static},
- {"password", get_password_static, set_password_static},
- {"print", get_print_static, set_print_static},
- {"radiosInUnison", get_radiosInUnison_static, set_radiosInUnison_static},
- {"readonly", get_readonly_static, set_readonly_static},
- {"rect", get_rect_static, set_rect_static},
- {"required", get_required_static, set_required_static},
- {"richText", get_richText_static, set_richText_static},
- {"richValue", get_richValue_static, set_richValue_static},
- {"rotation", get_rotation_static, set_rotation_static},
- {"strokeColor", get_strokeColor_static, set_strokeColor_static},
- {"style", get_style_static, set_style_static},
- {"submitName", get_submitName_static, set_submitName_static},
- {"textColor", get_textColor_static, set_textColor_static},
- {"textFont", get_textFont_static, set_textFont_static},
- {"textSize", get_textSize_static, set_textSize_static},
- {"type", get_type_static, set_type_static},
- {"userName", get_userName_static, set_userName_static},
- {"value", get_value_static, set_value_static},
- {"valueAsString", get_valueAsString_static, set_valueAsString_static},
- {"source", get_source_static, set_source_static},
- {0, 0, 0}};
-
-JSMethodSpec CJS_Field::MethodSpecs[] = {
- {"browseForFileToSubmit", browseForFileToSubmit_static},
- {"buttonGetCaption", buttonGetCaption_static},
- {"buttonGetIcon", buttonGetIcon_static},
- {"buttonImportIcon", buttonImportIcon_static},
- {"buttonSetCaption", buttonSetCaption_static},
- {"buttonSetIcon", buttonSetIcon_static},
- {"checkThisBox", checkThisBox_static},
- {"clearItems", clearItems_static},
- {"defaultIsChecked", defaultIsChecked_static},
- {"deleteItemAt", deleteItemAt_static},
- {"getArray", getArray_static},
- {"getItemAt", getItemAt_static},
- {"getLock", getLock_static},
- {"insertItemAt", insertItemAt_static},
- {"isBoxChecked", isBoxChecked_static},
- {"isDefaultChecked", isDefaultChecked_static},
- {"setAction", setAction_static},
- {"setFocus", setFocus_static},
- {"setItems", setItems_static},
- {"setLock", setLock_static},
- {"signatureGetModifications", signatureGetModifications_static},
- {"signatureGetSeedValue", signatureGetSeedValue_static},
- {"signatureInfo", signatureInfo_static},
- {"signatureSetSeedValue", signatureSetSeedValue_static},
- {"signatureSign", signatureSign_static},
- {"signatureValidate", signatureValidate_static},
- {0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Field, Field)
-
-CJS_DelayData::CJS_DelayData(FIELD_PROP prop,
- int idx,
- const CFX_WideString& name)
- : eProp(prop), nControlIndex(idx), sFieldName(name) {}
-
-CJS_DelayData::~CJS_DelayData() {}
-
-void CJS_Field::InitInstance(IJS_Runtime* pIRuntime) {
-}
-
-Field::Field(CJS_Object* pJSObject)
- : CJS_EmbedObj(pJSObject),
- m_pJSDoc(nullptr),
- m_pFormFillEnv(nullptr),
- m_nFormControlIndex(-1),
- m_bCanSet(false),
- m_bDelay(false) {}
-
-Field::~Field() {}
-
-// note: iControlNo = -1, means not a widget.
-void Field::ParseFieldName(const std::wstring& strFieldNameParsed,
- std::wstring& strFieldName,
- int& iControlNo) {
- int iStart = strFieldNameParsed.find_last_of(L'.');
- if (iStart == -1) {
- strFieldName = strFieldNameParsed;
- iControlNo = -1;
- return;
- }
- std::wstring suffixal = strFieldNameParsed.substr(iStart + 1);
- iControlNo = FXSYS_wtoi(suffixal.c_str());
- if (iControlNo == 0) {
- int iSpaceStart;
- while ((iSpaceStart = suffixal.find_last_of(L" ")) != -1) {
- suffixal.erase(iSpaceStart, 1);
- }
-
- if (suffixal.compare(L"0") != 0) {
- strFieldName = strFieldNameParsed;
- iControlNo = -1;
- return;
- }
- }
- strFieldName = strFieldNameParsed.substr(0, iStart);
-}
-
-bool Field::AttachField(Document* pDocument,
- const CFX_WideString& csFieldName) {
- m_pJSDoc = pDocument;
- m_pFormFillEnv.Reset(pDocument->GetFormFillEnv());
- m_bCanSet = m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM) ||
- m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) ||
- m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY);
-
- CPDFSDK_InterForm* pRDInterForm = m_pFormFillEnv->GetInterForm();
- CPDF_InterForm* pInterForm = pRDInterForm->GetInterForm();
- CFX_WideString swFieldNameTemp = csFieldName;
- swFieldNameTemp.Replace(L"..", L".");
-
- if (pInterForm->CountFields(swFieldNameTemp) <= 0) {
- std::wstring strFieldName;
- int iControlNo = -1;
- ParseFieldName(swFieldNameTemp.c_str(), strFieldName, iControlNo);
- if (iControlNo == -1)
- return false;
-
- m_FieldName = strFieldName.c_str();
- m_nFormControlIndex = iControlNo;
- return true;
- }
-
- m_FieldName = swFieldNameTemp;
- m_nFormControlIndex = -1;
-
- return true;
-}
-
-std::vector<CPDF_FormField*> Field::GetFormFields(
- CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& csFieldName) {
- std::vector<CPDF_FormField*> fields;
- CPDFSDK_InterForm* pReaderInterForm = pFormFillEnv->GetInterForm();
- CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
- for (int i = 0, sz = pInterForm->CountFields(csFieldName); i < sz; ++i) {
- if (CPDF_FormField* pFormField = pInterForm->GetField(i, csFieldName))
- fields.push_back(pFormField);
- }
- return fields;
-}
-
-std::vector<CPDF_FormField*> Field::GetFormFields(
- const CFX_WideString& csFieldName) const {
- return Field::GetFormFields(m_pFormFillEnv.Get(), csFieldName);
-}
-
-void Field::UpdateFormField(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDF_FormField* pFormField,
- bool bChangeMark,
- bool bResetAP,
- bool bRefresh) {
- CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
-
- if (bResetAP) {
- std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
- pInterForm->GetWidgets(pFormField, &widgets);
-
- int nFieldType = pFormField->GetFieldType();
- if (nFieldType == FIELDTYPE_COMBOBOX || nFieldType == FIELDTYPE_TEXTFIELD) {
- for (auto& pObserved : widgets) {
- if (pObserved) {
- bool bFormatted = false;
- CFX_WideString sValue = static_cast<CPDFSDK_Widget*>(pObserved.Get())
- ->OnFormat(bFormatted);
- if (pObserved) { // Not redundant, may be clobbered by OnFormat.
- static_cast<CPDFSDK_Widget*>(pObserved.Get())
- ->ResetAppearance(bFormatted ? &sValue : nullptr, false);
- }
- }
- }
- } else {
- for (auto& pObserved : widgets) {
- if (pObserved) {
- static_cast<CPDFSDK_Widget*>(pObserved.Get())
- ->ResetAppearance(nullptr, false);
- }
- }
- }
- }
-
- if (bRefresh) {
- // Refresh the widget list. The calls in |bResetAP| may have caused widgets
- // to be removed from the list. We need to call |GetWidgets| again to be
- // sure none of the widgets have been deleted.
- std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
- pInterForm->GetWidgets(pFormField, &widgets);
-
- // TODO(dsinclair): Determine if all widgets share the same
- // CPDFSDK_InterForm. If that's the case, we can move the code to
- // |GetFormFillEnv| out of the loop.
- for (auto& pObserved : widgets) {
- if (pObserved) {
- CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pObserved.Get());
- pWidget->GetInterForm()->GetFormFillEnv()->UpdateAllViews(nullptr,
- pWidget);
- }
- }
- }
-
- if (bChangeMark)
- pFormFillEnv->SetChangeMark();
-}
-
-void Field::UpdateFormControl(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDF_FormControl* pFormControl,
- bool bChangeMark,
- bool bResetAP,
- bool bRefresh) {
- ASSERT(pFormControl);
-
- CPDFSDK_InterForm* pForm = pFormFillEnv->GetInterForm();
- CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl);
-
- if (pWidget) {
- if (bResetAP) {
- int nFieldType = pWidget->GetFieldType();
- if (nFieldType == FIELDTYPE_COMBOBOX ||
- nFieldType == FIELDTYPE_TEXTFIELD) {
- bool bFormatted = false;
- CFX_WideString sValue = pWidget->OnFormat(bFormatted);
- pWidget->ResetAppearance(bFormatted ? &sValue : nullptr, false);
- } else {
- pWidget->ResetAppearance(nullptr, false);
- }
- }
-
- if (bRefresh) {
- CPDFSDK_InterForm* pInterForm = pWidget->GetInterForm();
- pInterForm->GetFormFillEnv()->UpdateAllViews(nullptr, pWidget);
- }
- }
-
- if (bChangeMark)
- pFormFillEnv->SetChangeMark();
-}
-
-CPDFSDK_Widget* Field::GetWidget(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDF_FormControl* pFormControl) {
- CPDFSDK_InterForm* pInterForm =
- static_cast<CPDFSDK_InterForm*>(pFormFillEnv->GetInterForm());
- return pInterForm ? pInterForm->GetWidget(pFormControl) : nullptr;
-}
-
-bool Field::ValueIsOccur(CPDF_FormField* pFormField,
- CFX_WideString csOptLabel) {
- for (int i = 0, sz = pFormField->CountOptions(); i < sz; i++) {
- if (csOptLabel.Compare(pFormField->GetOptionLabel(i)) == 0)
- return true;
- }
-
- return false;
-}
-
-CPDF_FormControl* Field::GetSmartFieldControl(CPDF_FormField* pFormField) {
- if (!pFormField->CountControls() ||
- m_nFormControlIndex >= pFormField->CountControls())
- return nullptr;
-
- if (m_nFormControlIndex < 0)
- return pFormField->GetControl(0);
-
- return pFormField->GetControl(m_nFormControlIndex);
-}
-
-bool Field::alignment(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- CFX_ByteString alignStr;
- vp >> alignStr;
-
- if (m_bDelay) {
- AddDelay_String(FP_ALIGNMENT, alignStr);
- } else {
- Field::SetAlignment(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, alignStr);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- switch (pFormControl->GetControlAlignment()) {
- case 1:
- vp << L"center";
- break;
- case 0:
- vp << L"left";
- break;
- case 2:
- vp << L"right";
- break;
- default:
- vp << L"";
- }
- }
-
- return true;
-}
-
-void Field::SetAlignment(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string) {
- // Not supported.
-}
-
-bool Field::borderStyle(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- CFX_ByteString strType = "";
- vp >> strType;
-
- if (m_bDelay) {
- AddDelay_String(FP_BORDERSTYLE, strType);
- } else {
- Field::SetBorderStyle(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, strType);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (!pFormField)
- return false;
-
- CPDFSDK_Widget* pWidget =
- GetWidget(m_pFormFillEnv.Get(), GetSmartFieldControl(pFormField));
- if (!pWidget)
- return false;
-
- switch (pWidget->GetBorderStyle()) {
- case BorderStyle::SOLID:
- vp << L"solid";
- break;
- case BorderStyle::DASH:
- vp << L"dashed";
- break;
- case BorderStyle::BEVELED:
- vp << L"beveled";
- break;
- case BorderStyle::INSET:
- vp << L"inset";
- break;
- case BorderStyle::UNDERLINE:
- vp << L"underline";
- break;
- default:
- vp << L"";
- break;
- }
- }
-
- return true;
-}
-
-void Field::SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string) {
- ASSERT(pFormFillEnv);
-
- BorderStyle nBorderStyle = BorderStyle::SOLID;
- if (string == "solid")
- nBorderStyle = BorderStyle::SOLID;
- else if (string == "beveled")
- nBorderStyle = BorderStyle::BEVELED;
- else if (string == "dashed")
- nBorderStyle = BorderStyle::DASH;
- else if (string == "inset")
- nBorderStyle = BorderStyle::INSET;
- else if (string == "underline")
- nBorderStyle = BorderStyle::UNDERLINE;
- else
- return;
-
- std::vector<CPDF_FormField*> FieldArray =
- GetFormFields(pFormFillEnv, swFieldName);
- for (CPDF_FormField* pFormField : FieldArray) {
- if (nControlIndex < 0) {
- bool bSet = false;
- for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
- if (CPDFSDK_Widget* pWidget =
- GetWidget(pFormFillEnv, pFormField->GetControl(i))) {
- if (pWidget->GetBorderStyle() != nBorderStyle) {
- pWidget->SetBorderStyle(nBorderStyle);
- bSet = true;
- }
- }
- }
- if (bSet)
- UpdateFormField(pFormFillEnv, pFormField, true, true, true);
- } else {
- if (nControlIndex >= pFormField->CountControls())
- return;
- if (CPDF_FormControl* pFormControl =
- pFormField->GetControl(nControlIndex)) {
- if (CPDFSDK_Widget* pWidget = GetWidget(pFormFillEnv, pFormControl)) {
- if (pWidget->GetBorderStyle() != nBorderStyle) {
- pWidget->SetBorderStyle(nBorderStyle);
- UpdateFormControl(pFormFillEnv, pFormControl, true, true, true);
- }
- }
- }
- }
- }
-}
-
-bool Field::buttonAlignX(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
-
- if (m_bDelay) {
- AddDelay_Int(FP_BUTTONALIGNX, nVP);
- } else {
- Field::SetButtonAlignX(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, nVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- CPDF_IconFit IconFit = pFormControl->GetIconFit();
-
- FX_FLOAT fLeft, fBottom;
- IconFit.GetIconPosition(fLeft, fBottom);
-
- vp << (int32_t)fLeft;
- }
-
- return true;
-}
-
-void Field::SetButtonAlignX(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::buttonAlignY(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
-
- if (m_bDelay) {
- AddDelay_Int(FP_BUTTONALIGNY, nVP);
- } else {
- Field::SetButtonAlignY(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, nVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- CPDF_IconFit IconFit = pFormControl->GetIconFit();
-
- FX_FLOAT fLeft, fBottom;
- IconFit.GetIconPosition(fLeft, fBottom);
-
- vp << (int32_t)fBottom;
- }
-
- return true;
-}
-
-void Field::SetButtonAlignY(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::buttonFitBounds(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
-
- if (m_bDelay) {
- AddDelay_Bool(FP_BUTTONFITBOUNDS, bVP);
- } else {
- Field::SetButtonFitBounds(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, bVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- vp << pFormControl->GetIconFit().GetFittingBounds();
- }
-
- return true;
-}
-
-void Field::SetButtonFitBounds(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b) {
- // Not supported.
-}
-
-bool Field::buttonPosition(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
-
- if (m_bDelay) {
- AddDelay_Int(FP_BUTTONPOSITION, nVP);
- } else {
- Field::SetButtonPosition(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, nVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- vp << pFormControl->GetTextPosition();
- }
- return true;
-}
-
-void Field::SetButtonPosition(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::buttonScaleHow(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
-
- if (m_bDelay) {
- AddDelay_Int(FP_BUTTONSCALEHOW, nVP);
- } else {
- Field::SetButtonScaleHow(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, nVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- CPDF_IconFit IconFit = pFormControl->GetIconFit();
- if (IconFit.IsProportionalScale())
- vp << (int32_t)0;
- else
- vp << (int32_t)1;
- }
-
- return true;
-}
-
-void Field::SetButtonScaleHow(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::buttonScaleWhen(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
-
- if (m_bDelay) {
- AddDelay_Int(FP_BUTTONSCALEWHEN, nVP);
- } else {
- Field::SetButtonScaleWhen(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, nVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- CPDF_IconFit IconFit = pFormControl->GetIconFit();
- int ScaleM = IconFit.GetScaleMethod();
- switch (ScaleM) {
- case CPDF_IconFit::Always:
- vp << (int32_t)CPDF_IconFit::Always;
- break;
- case CPDF_IconFit::Bigger:
- vp << (int32_t)CPDF_IconFit::Bigger;
- break;
- case CPDF_IconFit::Never:
- vp << (int32_t)CPDF_IconFit::Never;
- break;
- case CPDF_IconFit::Smaller:
- vp << (int32_t)CPDF_IconFit::Smaller;
- break;
- }
- }
-
- return true;
-}
-
-void Field::SetButtonScaleWhen(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::calcOrderIndex(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
-
- if (m_bDelay) {
- AddDelay_Int(FP_CALCORDERINDEX, nVP);
- } else {
- Field::SetCalcOrderIndex(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, nVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX &&
- pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD) {
- return false;
- }
-
- CPDFSDK_InterForm* pRDInterForm = m_pFormFillEnv->GetInterForm();
- CPDF_InterForm* pInterForm = pRDInterForm->GetInterForm();
- vp << (int32_t)pInterForm->FindFieldInCalculationOrder(pFormField);
- }
-
- return true;
-}
-
-void Field::SetCalcOrderIndex(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::charLimit(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
-
- if (m_bDelay) {
- AddDelay_Int(FP_CHARLIMIT, nVP);
- } else {
- Field::SetCharLimit(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, nVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD)
- return false;
-
- vp << (int32_t)pFormField->GetMaxLen();
- }
- return true;
-}
-
-void Field::SetCharLimit(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::comb(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
-
- if (m_bDelay) {
- AddDelay_Bool(FP_COMB, bVP);
- } else {
- Field::SetComb(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- bVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD)
- return false;
-
- if (pFormField->GetFieldFlags() & FIELDFLAG_COMB)
- vp << true;
- else
- vp << false;
- }
-
- return true;
-}
-
-void Field::SetComb(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b) {
- // Not supported.
-}
-
-bool Field::commitOnSelChange(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
-
- if (m_bDelay) {
- AddDelay_Bool(FP_COMMITONSELCHANGE, bVP);
- } else {
- Field::SetCommitOnSelChange(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, bVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX &&
- pFormField->GetFieldType() != FIELDTYPE_LISTBOX) {
- return false;
- }
-
- if (pFormField->GetFieldFlags() & FIELDFLAG_COMMITONSELCHANGE)
- vp << true;
- else
- vp << false;
- }
-
- return true;
-}
-
-void Field::SetCommitOnSelChange(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b) {
- // Not supported.
-}
-
-bool Field::currentValueIndices(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- std::vector<uint32_t> array;
- if (vp.GetJSValue()->GetType() == CJS_Value::VT_number) {
- int iSelecting = 0;
- vp >> iSelecting;
- array.push_back(iSelecting);
- } else if (vp.GetJSValue()->IsArrayObject()) {
- CJS_Array SelArray;
- CJS_Value SelValue(pRuntime);
- int iSelecting;
- vp >> SelArray;
- for (int i = 0, sz = SelArray.GetLength(pRuntime); i < sz; i++) {
- SelArray.GetElement(pRuntime, i, SelValue);
- iSelecting = SelValue.ToInt(pRuntime);
- array.push_back(iSelecting);
- }
- }
-
- if (m_bDelay) {
- AddDelay_WordArray(FP_CURRENTVALUEINDICES, array);
- } else {
- Field::SetCurrentValueIndices(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, array);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX &&
- pFormField->GetFieldType() != FIELDTYPE_LISTBOX) {
- return false;
- }
-
- if (pFormField->CountSelectedItems() == 1) {
- vp << pFormField->GetSelectedIndex(0);
- } else if (pFormField->CountSelectedItems() > 1) {
- CJS_Array SelArray;
- for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
- SelArray.SetElement(
- pRuntime, i, CJS_Value(pRuntime, pFormField->GetSelectedIndex(i)));
- }
- vp << SelArray;
- } else {
- vp << -1;
- }
- }
-
- return true;
-}
-
-void Field::SetCurrentValueIndices(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const std::vector<uint32_t>& array) {
- ASSERT(pFormFillEnv);
- std::vector<CPDF_FormField*> FieldArray =
- GetFormFields(pFormFillEnv, swFieldName);
-
- for (CPDF_FormField* pFormField : FieldArray) {
- int nFieldType = pFormField->GetFieldType();
- if (nFieldType == FIELDTYPE_COMBOBOX || nFieldType == FIELDTYPE_LISTBOX) {
- uint32_t dwFieldFlags = pFormField->GetFieldFlags();
- pFormField->ClearSelection(true);
- for (size_t i = 0; i < array.size(); ++i) {
- if (i != 0 && !(dwFieldFlags & (1 << 21)))
- break;
- if (array[i] < static_cast<uint32_t>(pFormField->CountOptions()) &&
- !pFormField->IsItemSelected(array[i])) {
- pFormField->SetItemSelection(array[i], true);
- }
- }
- UpdateFormField(pFormFillEnv, pFormField, true, true, true);
- }
- }
-}
-
-bool Field::defaultStyle(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return false;
-}
-
-void Field::SetDefaultStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex) {
- // Not supported.
-}
-
-bool Field::defaultValue(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- CFX_WideString WideStr;
- vp >> WideStr;
-
- if (m_bDelay) {
- AddDelay_WideString(FP_DEFAULTVALUE, WideStr);
- } else {
- Field::SetDefaultValue(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, WideStr);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() == FIELDTYPE_PUSHBUTTON ||
- pFormField->GetFieldType() == FIELDTYPE_SIGNATURE) {
- return false;
- }
-
- vp << pFormField->GetDefaultValue();
- }
- return true;
-}
-
-void Field::SetDefaultValue(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_WideString& string) {
- // Not supported.
-}
-
-bool Field::doNotScroll(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
-
- if (m_bDelay) {
- AddDelay_Bool(FP_DONOTSCROLL, bVP);
- } else {
- Field::SetDoNotScroll(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, bVP);
- }
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD)
- return false;
-
- if (pFormField->GetFieldFlags() & FIELDFLAG_DONOTSCROLL)
- vp << true;
- else
- vp << false;
- }
-
- return true;
-}
-
-void Field::SetDoNotScroll(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b) {
- // Not supported.
-}
-
-bool Field::doNotSpellCheck(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- } else {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD &&
- pFormField->GetFieldType() != FIELDTYPE_COMBOBOX) {
- return false;
- }
-
- if (pFormField->GetFieldFlags() & FIELDFLAG_DONOTSPELLCHECK)
- vp << true;
- else
- vp << false;
- }
-
- return true;
-}
-
-void Field::SetDelay(bool bDelay) {
- m_bDelay = bDelay;
-
- if (!m_bDelay) {
- if (m_pJSDoc)
- m_pJSDoc->DoFieldDelay(m_FieldName, m_nFormControlIndex);
- }
-}
-
-bool Field::delay(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsSetting()) {
- vp << m_bDelay;
- return true;
- }
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- SetDelay(bVP);
- return true;
-}
-
-bool Field::display(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
- if (m_bDelay) {
- AddDelay_Int(FP_DISPLAY, nVP);
- } else {
- Field::SetDisplay(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- nVP);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- ASSERT(pFormField);
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDFSDK_Widget* pWidget =
- pInterForm->GetWidget(GetSmartFieldControl(pFormField));
- if (!pWidget)
- return false;
-
- uint32_t dwFlag = pWidget->GetFlags();
- if (ANNOTFLAG_INVISIBLE & dwFlag || ANNOTFLAG_HIDDEN & dwFlag) {
- vp << (int32_t)1;
- } else {
- if (ANNOTFLAG_PRINT & dwFlag) {
- if (ANNOTFLAG_NOVIEW & dwFlag) {
- vp << (int32_t)3;
- } else {
- vp << (int32_t)0;
- }
- } else {
- vp << (int32_t)2;
- }
- }
- return true;
-}
-
-void Field::SetDisplay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
- std::vector<CPDF_FormField*> FieldArray =
- GetFormFields(pFormFillEnv, swFieldName);
- for (CPDF_FormField* pFormField : FieldArray) {
- if (nControlIndex < 0) {
- bool bAnySet = false;
- for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
- CPDF_FormControl* pFormControl = pFormField->GetControl(i);
- ASSERT(pFormControl);
-
- CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl);
- if (SetWidgetDisplayStatus(pWidget, number))
- bAnySet = true;
- }
-
- if (bAnySet)
- UpdateFormField(pFormFillEnv, pFormField, true, false, true);
- } else {
- if (nControlIndex >= pFormField->CountControls())
- return;
-
- CPDF_FormControl* pFormControl = pFormField->GetControl(nControlIndex);
- if (!pFormControl)
- return;
-
- CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl);
- if (SetWidgetDisplayStatus(pWidget, number))
- UpdateFormControl(pFormFillEnv, pFormControl, true, false, true);
- }
- }
-}
-
-bool Field::doc(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- vp << m_pJSDoc->GetCJSDoc();
- return true;
-}
-
-bool Field::editable(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX)
- return false;
-
- vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_EDIT);
- return true;
-}
-
-bool Field::exportValues(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_CHECKBOX &&
- pFormField->GetFieldType() != FIELDTYPE_RADIOBUTTON) {
- return false;
- }
- if (vp.IsSetting())
- return m_bCanSet && vp.GetJSValue()->IsArrayObject();
-
- CJS_Array ExportValusArray;
- if (m_nFormControlIndex < 0) {
- for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
- CPDF_FormControl* pFormControl = pFormField->GetControl(i);
- ExportValusArray.SetElement(
- pRuntime, i,
- CJS_Value(pRuntime, pFormControl->GetExportValue().c_str()));
- }
- } else {
- if (m_nFormControlIndex >= pFormField->CountControls())
- return false;
-
- CPDF_FormControl* pFormControl =
- pFormField->GetControl(m_nFormControlIndex);
- if (!pFormControl)
- return false;
-
- ExportValusArray.SetElement(
- pRuntime, 0,
- CJS_Value(pRuntime, pFormControl->GetExportValue().c_str()));
- }
- vp << ExportValusArray;
- return true;
-}
-
-bool Field::fileSelect(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD)
- return false;
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- return true;
- }
- vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_FILESELECT);
- return true;
-}
-
-bool Field::fillColor(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_Array crArray;
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- if (!vp.GetJSValue()->IsArrayObject())
- return false;
-
- vp >> crArray;
-
- CPWL_Color color;
- color::ConvertArrayToPWLColor(pRuntime, crArray, &color);
- if (m_bDelay) {
- AddDelay_Color(FP_FILLCOLOR, color);
- } else {
- Field::SetFillColor(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, color);
- }
- return true;
- }
- CPDF_FormField* pFormField = FieldArray[0];
- ASSERT(pFormField);
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- int iColorType;
- pFormControl->GetBackgroundColor(iColorType);
-
- CPWL_Color color;
- if (iColorType == COLORTYPE_TRANSPARENT) {
- color = CPWL_Color(COLORTYPE_TRANSPARENT);
- } else if (iColorType == COLORTYPE_GRAY) {
- color =
- CPWL_Color(COLORTYPE_GRAY, pFormControl->GetOriginalBackgroundColor(0));
- } else if (iColorType == COLORTYPE_RGB) {
- color =
- CPWL_Color(COLORTYPE_RGB, pFormControl->GetOriginalBackgroundColor(0),
- pFormControl->GetOriginalBackgroundColor(1),
- pFormControl->GetOriginalBackgroundColor(2));
- } else if (iColorType == COLORTYPE_CMYK) {
- color =
- CPWL_Color(COLORTYPE_CMYK, pFormControl->GetOriginalBackgroundColor(0),
- pFormControl->GetOriginalBackgroundColor(1),
- pFormControl->GetOriginalBackgroundColor(2),
- pFormControl->GetOriginalBackgroundColor(3));
- } else {
- return false;
- }
- color::ConvertPWLColorToArray(pRuntime, color, &crArray);
- vp << crArray;
- return true;
-}
-
-void Field::SetFillColor(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CPWL_Color& color) {
- // Not supported.
-}
-
-bool Field::hidden(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- if (m_bDelay) {
- AddDelay_Bool(FP_HIDDEN, bVP);
- } else {
- Field::SetHidden(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- bVP);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- ASSERT(pFormField);
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDFSDK_Widget* pWidget =
- pInterForm->GetWidget(GetSmartFieldControl(pFormField));
- if (!pWidget)
- return false;
-
- uint32_t dwFlags = pWidget->GetFlags();
- if (ANNOTFLAG_INVISIBLE & dwFlags || ANNOTFLAG_HIDDEN & dwFlags)
- vp << true;
- else
- vp << false;
-
- return true;
-}
-
-void Field::SetHidden(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b) {
- int display = b ? 1 /*Hidden*/ : 0 /*Visible*/;
- SetDisplay(pFormFillEnv, swFieldName, nControlIndex, display);
-}
-
-bool Field::highlight(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- CFX_ByteString strMode;
- vp >> strMode;
-
- if (m_bDelay) {
- AddDelay_String(FP_HIGHLIGHT, strMode);
- } else {
- Field::SetHighlight(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, strMode);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- int eHM = pFormControl->GetHighlightingMode();
- switch (eHM) {
- case CPDF_FormControl::None:
- vp << L"none";
- break;
- case CPDF_FormControl::Push:
- vp << L"push";
- break;
- case CPDF_FormControl::Invert:
- vp << L"invert";
- break;
- case CPDF_FormControl::Outline:
- vp << L"outline";
- break;
- case CPDF_FormControl::Toggle:
- vp << L"toggle";
- break;
- }
- return true;
-}
-
-void Field::SetHighlight(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string) {
- // Not supported.
-}
-
-bool Field::lineWidth(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int iWidth;
- vp >> iWidth;
-
- if (m_bDelay) {
- AddDelay_Int(FP_LINEWIDTH, iWidth);
- } else {
- Field::SetLineWidth(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, iWidth);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- ASSERT(pFormField);
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- if (!pFormField->CountControls())
- return false;
-
- CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormField->GetControl(0));
- if (!pWidget)
- return false;
-
- vp << (int32_t)pWidget->GetBorderWidth();
- return true;
-}
-
-void Field::SetLineWidth(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
- std::vector<CPDF_FormField*> FieldArray =
- GetFormFields(pFormFillEnv, swFieldName);
- for (CPDF_FormField* pFormField : FieldArray) {
- if (nControlIndex < 0) {
- bool bSet = false;
- for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
- CPDF_FormControl* pFormControl = pFormField->GetControl(i);
- ASSERT(pFormControl);
-
- if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
- if (number != pWidget->GetBorderWidth()) {
- pWidget->SetBorderWidth(number);
- bSet = true;
- }
- }
- }
- if (bSet)
- UpdateFormField(pFormFillEnv, pFormField, true, true, true);
- } else {
- if (nControlIndex >= pFormField->CountControls())
- return;
- if (CPDF_FormControl* pFormControl =
- pFormField->GetControl(nControlIndex)) {
- if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
- if (number != pWidget->GetBorderWidth()) {
- pWidget->SetBorderWidth(number);
- UpdateFormControl(pFormFillEnv, pFormControl, true, true, true);
- }
- }
- }
- }
- }
-}
-
-bool Field::multiline(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
-
- if (m_bDelay) {
- AddDelay_Bool(FP_MULTILINE, bVP);
- } else {
- Field::SetMultiline(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, bVP);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD)
- return false;
-
- if (pFormField->GetFieldFlags() & FIELDFLAG_MULTILINE)
- vp << true;
- else
- vp << false;
-
- return true;
-}
-
-void Field::SetMultiline(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b) {
- // Not supported.
-}
-
-bool Field::multipleSelection(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- if (m_bDelay) {
- AddDelay_Bool(FP_MULTIPLESELECTION, bVP);
- } else {
- Field::SetMultipleSelection(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, bVP);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_LISTBOX)
- return false;
-
- vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_MULTISELECT);
- return true;
-}
-
-void Field::SetMultipleSelection(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b) {
- // Not supported.
-}
-
-bool Field::name(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- vp << m_FieldName;
- return true;
-}
-
-bool Field::numItems(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_COMBOBOX &&
- pFormField->GetFieldType() != FIELDTYPE_LISTBOX) {
- return false;
- }
-
- vp << (int32_t)pFormField->CountOptions();
- return true;
-}
-
-bool Field::page(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting()) {
- sError = JSGetStringFromID(IDS_STRING_JSREADONLY);
- return false;
- }
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (!pFormField)
- return false;
-
- std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
- m_pFormFillEnv->GetInterForm()->GetWidgets(pFormField, &widgets);
- if (widgets.empty()) {
- vp << (int32_t)-1;
- return true;
- }
-
- CJS_Array PageArray;
- int i = 0;
- for (const auto& pObserved : widgets) {
- if (!pObserved) {
- sError = JSGetStringFromID(IDS_STRING_JSBADOBJECT);
- return false;
- }
-
- auto pWidget = static_cast<CPDFSDK_Widget*>(pObserved.Get());
- CPDFSDK_PageView* pPageView = pWidget->GetPageView();
- if (!pPageView)
- return false;
-
- PageArray.SetElement(
- pRuntime, i, CJS_Value(pRuntime, (int32_t)pPageView->GetPageIndex()));
- ++i;
- }
-
- vp << PageArray;
- return true;
-}
-
-bool Field::password(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- if (m_bDelay) {
- AddDelay_Bool(FP_PASSWORD, bVP);
- } else {
- Field::SetPassword(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- bVP);
- }
- return true;
- }
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD)
- return false;
-
- vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_PASSWORD);
- return true;
-}
-
-void Field::SetPassword(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b) {
- // Not supported.
-}
-
-bool Field::print(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
-
- for (CPDF_FormField* pFormField : FieldArray) {
- if (m_nFormControlIndex < 0) {
- bool bSet = false;
- for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
- if (CPDFSDK_Widget* pWidget =
- pInterForm->GetWidget(pFormField->GetControl(i))) {
- uint32_t dwFlags = pWidget->GetFlags();
- if (bVP)
- dwFlags |= ANNOTFLAG_PRINT;
- else
- dwFlags &= ~ANNOTFLAG_PRINT;
-
- if (dwFlags != pWidget->GetFlags()) {
- pWidget->SetFlags(dwFlags);
- bSet = true;
- }
- }
- }
-
- if (bSet)
- UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, false, true);
- } else {
- if (m_nFormControlIndex >= pFormField->CountControls())
- return false;
- if (CPDF_FormControl* pFormControl =
- pFormField->GetControl(m_nFormControlIndex)) {
- if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
- uint32_t dwFlags = pWidget->GetFlags();
- if (bVP)
- dwFlags |= ANNOTFLAG_PRINT;
- else
- dwFlags &= ~ANNOTFLAG_PRINT;
-
- if (dwFlags != pWidget->GetFlags()) {
- pWidget->SetFlags(dwFlags);
- UpdateFormControl(m_pFormFillEnv.Get(),
- pFormField->GetControl(m_nFormControlIndex),
- true, false, true);
- }
- }
- }
- }
- }
- return true;
- }
-
- CPDF_FormField* pFormField = FieldArray[0];
- CPDFSDK_Widget* pWidget =
- pInterForm->GetWidget(GetSmartFieldControl(pFormField));
- if (!pWidget)
- return false;
-
- vp << !!(pWidget->GetFlags() & ANNOTFLAG_PRINT);
- return true;
-}
-
-bool Field::radiosInUnison(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- return true;
- }
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_RADIOBUTTON)
- return false;
-
- vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_RADIOSINUNISON);
- return true;
-}
-
-bool Field::readonly(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- return true;
- }
- vp << !!(FieldArray[0]->GetFieldFlags() & FIELDFLAG_READONLY);
- return true;
-}
-
-bool Field::rect(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_Value Upper_Leftx(pRuntime);
- CJS_Value Upper_Lefty(pRuntime);
- CJS_Value Lower_Rightx(pRuntime);
- CJS_Value Lower_Righty(pRuntime);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
- if (!vp.GetJSValue()->IsArrayObject())
- return false;
-
- CJS_Array rcArray;
- vp >> rcArray;
- rcArray.GetElement(pRuntime, 0, Upper_Leftx);
- rcArray.GetElement(pRuntime, 1, Upper_Lefty);
- rcArray.GetElement(pRuntime, 2, Lower_Rightx);
- rcArray.GetElement(pRuntime, 3, Lower_Righty);
-
- FX_FLOAT pArray[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- pArray[0] = static_cast<FX_FLOAT>(Upper_Leftx.ToInt(pRuntime));
- pArray[1] = static_cast<FX_FLOAT>(Lower_Righty.ToInt(pRuntime));
- pArray[2] = static_cast<FX_FLOAT>(Lower_Rightx.ToInt(pRuntime));
- pArray[3] = static_cast<FX_FLOAT>(Upper_Lefty.ToInt(pRuntime));
-
- CFX_FloatRect crRect(pArray);
- if (m_bDelay) {
- AddDelay_Rect(FP_RECT, crRect);
- } else {
- Field::SetRect(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- crRect);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDFSDK_Widget* pWidget =
- pInterForm->GetWidget(GetSmartFieldControl(pFormField));
- if (!pWidget)
- return false;
-
- CFX_FloatRect crRect = pWidget->GetRect();
- Upper_Leftx = CJS_Value(pRuntime, static_cast<int32_t>(crRect.left));
- Upper_Lefty = CJS_Value(pRuntime, static_cast<int32_t>(crRect.top));
- Lower_Rightx = CJS_Value(pRuntime, static_cast<int32_t>(crRect.right));
- Lower_Righty = CJS_Value(pRuntime, static_cast<int32_t>(crRect.bottom));
-
- CJS_Array rcArray;
- rcArray.SetElement(pRuntime, 0, Upper_Leftx);
- rcArray.SetElement(pRuntime, 1, Upper_Lefty);
- rcArray.SetElement(pRuntime, 2, Lower_Rightx);
- rcArray.SetElement(pRuntime, 3, Lower_Righty);
- vp << rcArray;
- return true;
-}
-
-void Field::SetRect(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_FloatRect& rect) {
- CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
- std::vector<CPDF_FormField*> FieldArray =
- GetFormFields(pFormFillEnv, swFieldName);
- for (CPDF_FormField* pFormField : FieldArray) {
- if (nControlIndex < 0) {
- bool bSet = false;
- for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
- CPDF_FormControl* pFormControl = pFormField->GetControl(i);
- ASSERT(pFormControl);
-
- if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
- CFX_FloatRect crRect = rect;
-
- CPDF_Page* pPDFPage = pWidget->GetPDFPage();
- crRect.Intersect(pPDFPage->GetPageBBox());
-
- if (!crRect.IsEmpty()) {
- CFX_FloatRect rcOld = pWidget->GetRect();
- if (crRect.left != rcOld.left || crRect.right != rcOld.right ||
- crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) {
- pWidget->SetRect(crRect);
- bSet = true;
- }
- }
- }
- }
-
- if (bSet)
- UpdateFormField(pFormFillEnv, pFormField, true, true, true);
- } else {
- if (nControlIndex >= pFormField->CountControls())
- return;
- if (CPDF_FormControl* pFormControl =
- pFormField->GetControl(nControlIndex)) {
- if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
- CFX_FloatRect crRect = rect;
-
- CPDF_Page* pPDFPage = pWidget->GetPDFPage();
- crRect.Intersect(pPDFPage->GetPageBBox());
-
- if (!crRect.IsEmpty()) {
- CFX_FloatRect rcOld = pWidget->GetRect();
- if (crRect.left != rcOld.left || crRect.right != rcOld.right ||
- crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) {
- pWidget->SetRect(crRect);
- UpdateFormControl(pFormFillEnv, pFormControl, true, true, true);
- }
- }
- }
- }
- }
- }
-}
-
-bool Field::required(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- return true;
- }
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() == FIELDTYPE_PUSHBUTTON)
- return false;
-
- vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_REQUIRED);
- return true;
-}
-
-bool Field::richText(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- bool bVP;
- vp >> bVP;
- if (m_bDelay)
- AddDelay_Bool(FP_RICHTEXT, bVP);
-
- return true;
- }
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_TEXTFIELD)
- return false;
-
- vp << !!(pFormField->GetFieldFlags() & FIELDFLAG_RICHTEXT);
- return true;
-}
-
-bool Field::richValue(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Field::rotation(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
- if (m_bDelay) {
- AddDelay_Int(FP_ROTATION, nVP);
- } else {
- Field::SetRotation(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- nVP);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- vp << (int32_t)pFormControl->GetRotation();
- return true;
-}
-
-void Field::SetRotation(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::strokeColor(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_Array crArray;
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- if (!vp.GetJSValue()->IsArrayObject())
- return false;
-
- vp >> crArray;
-
- CPWL_Color color;
- color::ConvertArrayToPWLColor(pRuntime, crArray, &color);
- if (m_bDelay) {
- AddDelay_Color(FP_STROKECOLOR, color);
- } else {
- Field::SetStrokeColor(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, color);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- int iColorType;
- pFormControl->GetBorderColor(iColorType);
-
- CPWL_Color color;
- if (iColorType == COLORTYPE_TRANSPARENT) {
- color = CPWL_Color(COLORTYPE_TRANSPARENT);
- } else if (iColorType == COLORTYPE_GRAY) {
- color = CPWL_Color(COLORTYPE_GRAY, pFormControl->GetOriginalBorderColor(0));
- } else if (iColorType == COLORTYPE_RGB) {
- color = CPWL_Color(COLORTYPE_RGB, pFormControl->GetOriginalBorderColor(0),
- pFormControl->GetOriginalBorderColor(1),
- pFormControl->GetOriginalBorderColor(2));
- } else if (iColorType == COLORTYPE_CMYK) {
- color = CPWL_Color(COLORTYPE_CMYK, pFormControl->GetOriginalBorderColor(0),
- pFormControl->GetOriginalBorderColor(1),
- pFormControl->GetOriginalBorderColor(2),
- pFormControl->GetOriginalBorderColor(3));
- } else {
- return false;
- }
-
- color::ConvertPWLColorToArray(pRuntime, color, &crArray);
- vp << crArray;
- return true;
-}
-
-void Field::SetStrokeColor(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CPWL_Color& color) {
- // Not supported.
-}
-
-bool Field::style(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- CFX_ByteString csBCaption;
- vp >> csBCaption;
-
- if (m_bDelay) {
- AddDelay_String(FP_STYLE, csBCaption);
- } else {
- Field::SetStyle(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- csBCaption);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_RADIOBUTTON &&
- pFormField->GetFieldType() != FIELDTYPE_CHECKBOX) {
- return false;
- }
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- CFX_WideString csWCaption = pFormControl->GetNormalCaption();
- CFX_ByteString csBCaption;
-
- switch (csWCaption[0]) {
- case L'l':
- csBCaption = "circle";
- break;
- case L'8':
- csBCaption = "cross";
- break;
- case L'u':
- csBCaption = "diamond";
- break;
- case L'n':
- csBCaption = "square";
- break;
- case L'H':
- csBCaption = "star";
- break;
- default: // L'4'
- csBCaption = "check";
- break;
- }
- vp << csBCaption;
- return true;
-}
-
-void Field::SetStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string) {
- // Not supported.
-}
-
-bool Field::submitName(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Field::textColor(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_Array crArray;
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- if (!vp.GetJSValue()->IsArrayObject())
- return false;
-
- vp >> crArray;
-
- CPWL_Color color;
- color::ConvertArrayToPWLColor(pRuntime, crArray, &color);
- if (m_bDelay) {
- AddDelay_Color(FP_TEXTCOLOR, color);
- } else {
- Field::SetTextColor(m_pFormFillEnv.Get(), m_FieldName,
- m_nFormControlIndex, color);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- int iColorType;
- FX_ARGB color;
- CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance();
- FieldAppearance.GetColor(color, iColorType);
-
- int32_t a;
- int32_t r;
- int32_t g;
- int32_t b;
- ArgbDecode(color, a, r, g, b);
-
- CPWL_Color crRet =
- CPWL_Color(COLORTYPE_RGB, r / 255.0f, g / 255.0f, b / 255.0f);
-
- if (iColorType == COLORTYPE_TRANSPARENT)
- crRet = CPWL_Color(COLORTYPE_TRANSPARENT);
-
- color::ConvertPWLColorToArray(pRuntime, crRet, &crArray);
- vp << crArray;
- return true;
-}
-
-void Field::SetTextColor(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CPWL_Color& color) {
- // Not supported.
-}
-
-bool Field::textFont(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- CFX_ByteString csFontName;
- vp >> csFontName;
- if (csFontName.IsEmpty())
- return false;
-
- if (m_bDelay) {
- AddDelay_String(FP_TEXTFONT, csFontName);
- } else {
- Field::SetTextFont(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- csFontName);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- ASSERT(pFormField);
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- int nFieldType = pFormField->GetFieldType();
- if (nFieldType != FIELDTYPE_PUSHBUTTON && nFieldType != FIELDTYPE_COMBOBOX &&
- nFieldType != FIELDTYPE_LISTBOX && nFieldType != FIELDTYPE_TEXTFIELD) {
- return false;
- }
- CPDF_Font* pFont = pFormControl->GetDefaultControlFont();
- if (!pFont)
- return false;
-
- vp << pFont->GetBaseFont();
- return true;
-}
-
-void Field::SetTextFont(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string) {
- // Not supported.
-}
-
-bool Field::textSize(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- int nVP;
- vp >> nVP;
- if (m_bDelay) {
- AddDelay_Int(FP_TEXTSIZE, nVP);
- } else {
- Field::SetTextSize(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- nVP);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- ASSERT(pFormField);
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance();
-
- CFX_ByteString csFontNameTag;
- FX_FLOAT fFontSize;
- FieldAppearance.GetFont(csFontNameTag, fFontSize);
- vp << (int)fFontSize;
- return true;
-}
-
-void Field::SetTextSize(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number) {
- // Not supported.
-}
-
-bool Field::type(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- switch (pFormField->GetFieldType()) {
- case FIELDTYPE_UNKNOWN:
- vp << L"unknown";
- break;
- case FIELDTYPE_PUSHBUTTON:
- vp << L"button";
- break;
- case FIELDTYPE_CHECKBOX:
- vp << L"checkbox";
- break;
- case FIELDTYPE_RADIOBUTTON:
- vp << L"radiobutton";
- break;
- case FIELDTYPE_COMBOBOX:
- vp << L"combobox";
- break;
- case FIELDTYPE_LISTBOX:
- vp << L"listbox";
- break;
- case FIELDTYPE_TEXTFIELD:
- vp << L"text";
- break;
- case FIELDTYPE_SIGNATURE:
- vp << L"signature";
- break;
- default:
- vp << L"unknown";
- break;
- }
- return true;
-}
-
-bool Field::userName(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- ASSERT(m_pFormFillEnv);
-
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- CFX_WideString swName;
- vp >> swName;
-
- if (m_bDelay) {
- AddDelay_WideString(FP_USERNAME, swName);
- } else {
- Field::SetUserName(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- swName);
- }
- return true;
- }
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- vp << FieldArray[0]->GetAlternateName();
- return true;
-}
-
-void Field::SetUserName(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_WideString& string) {
- // Not supported.
-}
-
-bool Field::value(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- if (!m_bCanSet)
- return false;
-
- std::vector<CFX_WideString> strArray;
- if (vp.GetJSValue()->IsArrayObject()) {
- CJS_Array ValueArray;
- vp.GetJSValue()->ConvertToArray(pRuntime, ValueArray);
- for (int i = 0, sz = ValueArray.GetLength(pRuntime); i < sz; i++) {
- CJS_Value ElementValue(pRuntime);
- ValueArray.GetElement(pRuntime, i, ElementValue);
- strArray.push_back(ElementValue.ToCFXWideString(pRuntime));
- }
- } else {
- CFX_WideString swValue;
- vp >> swValue;
- strArray.push_back(swValue);
- }
-
- if (m_bDelay) {
- AddDelay_WideStringArray(FP_VALUE, strArray);
- } else {
- Field::SetValue(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
- strArray);
- }
- return true;
- }
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- switch (pFormField->GetFieldType()) {
- case FIELDTYPE_PUSHBUTTON:
- return false;
- case FIELDTYPE_COMBOBOX:
- case FIELDTYPE_TEXTFIELD: {
- vp << pFormField->GetValue();
- } break;
- case FIELDTYPE_LISTBOX: {
- if (pFormField->CountSelectedItems() > 1) {
- CJS_Array ValueArray;
- CJS_Value ElementValue(pRuntime);
- int iIndex;
- for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
- iIndex = pFormField->GetSelectedIndex(i);
- ElementValue =
- CJS_Value(pRuntime, pFormField->GetOptionValue(iIndex).c_str());
- if (FXSYS_wcslen(ElementValue.ToCFXWideString(pRuntime).c_str()) ==
- 0) {
- ElementValue =
- CJS_Value(pRuntime, pFormField->GetOptionLabel(iIndex).c_str());
- }
- ValueArray.SetElement(pRuntime, i, ElementValue);
- }
- vp << ValueArray;
- } else {
- vp << pFormField->GetValue();
- }
- } break;
- case FIELDTYPE_CHECKBOX:
- case FIELDTYPE_RADIOBUTTON: {
- bool bFind = false;
- for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
- if (pFormField->GetControl(i)->IsChecked()) {
- vp << pFormField->GetControl(i)->GetExportValue();
- bFind = true;
- break;
- }
- }
- if (!bFind)
- vp << L"Off";
- } break;
- default:
- vp << pFormField->GetValue();
- break;
- }
- vp.GetJSValue()->MaybeCoerceToNumber(pRuntime);
- return true;
-}
-
-void Field::SetValue(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const std::vector<CFX_WideString>& strArray) {
- ASSERT(pFormFillEnv);
- if (strArray.empty())
- return;
-
- std::vector<CPDF_FormField*> FieldArray =
- GetFormFields(pFormFillEnv, swFieldName);
-
- for (CPDF_FormField* pFormField : FieldArray) {
- if (pFormField->GetFullName().Compare(swFieldName) != 0)
- continue;
-
- switch (pFormField->GetFieldType()) {
- case FIELDTYPE_TEXTFIELD:
- case FIELDTYPE_COMBOBOX:
- if (pFormField->GetValue() != strArray[0]) {
- pFormField->SetValue(strArray[0], true);
- UpdateFormField(pFormFillEnv, pFormField, true, false, true);
- }
- break;
- case FIELDTYPE_CHECKBOX:
- case FIELDTYPE_RADIOBUTTON: {
- if (pFormField->GetValue() != strArray[0]) {
- pFormField->SetValue(strArray[0], true);
- UpdateFormField(pFormFillEnv, pFormField, true, false, true);
- }
- } break;
- case FIELDTYPE_LISTBOX: {
- bool bModified = false;
- for (const auto& str : strArray) {
- if (!pFormField->IsItemSelected(pFormField->FindOption(str))) {
- bModified = true;
- break;
- }
- }
- if (bModified) {
- pFormField->ClearSelection(true);
- for (const auto& str : strArray) {
- int index = pFormField->FindOption(str);
- if (!pFormField->IsItemSelected(index))
- pFormField->SetItemSelection(index, true, true);
- }
- UpdateFormField(pFormFillEnv, pFormField, true, false, true);
- }
- } break;
- default:
- break;
- }
- }
-}
-
-bool Field::valueAsString(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() == FIELDTYPE_PUSHBUTTON)
- return false;
-
- if (pFormField->GetFieldType() == FIELDTYPE_CHECKBOX) {
- if (!pFormField->CountControls())
- return false;
-
- if (pFormField->GetControl(0)->IsChecked())
- vp << L"Yes";
- else
- vp << L"Off";
- } else if (pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON &&
- !(pFormField->GetFieldFlags() & FIELDFLAG_RADIOSINUNISON)) {
- for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
- if (pFormField->GetControl(i)->IsChecked()) {
- vp << pFormField->GetControl(i)->GetExportValue().c_str();
- break;
- } else {
- vp << L"Off";
- }
- }
- } else if (pFormField->GetFieldType() == FIELDTYPE_LISTBOX &&
- (pFormField->CountSelectedItems() > 1)) {
- vp << L"";
- } else {
- vp << pFormField->GetValue().c_str();
- }
-
- return true;
-}
-
-bool Field::browseForFileToSubmit(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if ((pFormField->GetFieldFlags() & FIELDFLAG_FILESELECT) &&
- (pFormField->GetFieldType() == FIELDTYPE_TEXTFIELD)) {
- CFX_WideString wsFileName = m_pFormFillEnv->JS_fieldBrowse();
- if (!wsFileName.IsEmpty()) {
- pFormField->SetValue(wsFileName);
- UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, true, true);
- }
- return true;
- }
- return false;
-}
-
-bool Field::buttonGetCaption(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int nface = 0;
- int iSize = params.size();
- if (iSize >= 1)
- nface = params[0].ToInt(pRuntime);
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- if (nface == 0)
- vRet = CJS_Value(pRuntime, pFormControl->GetNormalCaption().c_str());
- else if (nface == 1)
- vRet = CJS_Value(pRuntime, pFormControl->GetDownCaption().c_str());
- else if (nface == 2)
- vRet = CJS_Value(pRuntime, pFormControl->GetRolloverCaption().c_str());
- else
- return false;
-
- return true;
-}
-
-bool Field::buttonGetIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() >= 1) {
- int nFace = params[0].ToInt(pRuntime);
- if (nFace < 0 || nFace > 2)
- return false;
- }
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_PUSHBUTTON)
- return false;
-
- CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
- if (!pFormControl)
- return false;
-
- v8::Local<v8::Object> pObj =
- pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID);
- if (pObj.IsEmpty())
- return false;
-
- CJS_Icon* pJS_Icon = static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj));
- vRet = CJS_Value(pRuntime, pJS_Icon);
- return true;
-}
-
-bool Field::buttonImportIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Field::buttonSetCaption(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::buttonSetIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::checkThisBox(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int iSize = params.size();
- if (iSize < 1)
- return false;
-
- if (!m_bCanSet)
- return false;
-
- int nWidget = params[0].ToInt(pRuntime);
- bool bCheckit = true;
- if (iSize >= 2)
- bCheckit = params[1].ToBool(pRuntime);
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (pFormField->GetFieldType() != FIELDTYPE_CHECKBOX &&
- pFormField->GetFieldType() != FIELDTYPE_RADIOBUTTON)
- return false;
- if (nWidget < 0 || nWidget >= pFormField->CountControls())
- return false;
- // TODO(weili): Check whether anything special needed for radio button,
- // otherwise merge these branches.
- if (pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON)
- pFormField->CheckControl(nWidget, bCheckit, true);
- else
- pFormField->CheckControl(nWidget, bCheckit, true);
-
- UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, true, true);
- return true;
-}
-
-bool Field::clearItems(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Field::defaultIsChecked(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (!m_bCanSet)
- return false;
-
- int iSize = params.size();
- if (iSize < 1)
- return false;
-
- int nWidget = params[0].ToInt(pRuntime);
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (nWidget < 0 || nWidget >= pFormField->CountControls())
- return false;
-
- vRet = CJS_Value(pRuntime,
- pFormField->GetFieldType() == FIELDTYPE_CHECKBOX ||
- pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON);
-
- return true;
-}
-
-bool Field::deleteItemAt(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Field::getArray(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- std::vector<std::unique_ptr<CFX_WideString>> swSort;
- for (CPDF_FormField* pFormField : FieldArray) {
- swSort.push_back(std::unique_ptr<CFX_WideString>(
- new CFX_WideString(pFormField->GetFullName())));
- }
-
- std::sort(
- swSort.begin(), swSort.end(),
- [](const std::unique_ptr<CFX_WideString>& p1,
- const std::unique_ptr<CFX_WideString>& p2) { return *p1 < *p2; });
-
- CJS_Array FormFieldArray;
-
- int j = 0;
- for (const auto& pStr : swSort) {
- v8::Local<v8::Object> pObj =
- pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID);
- if (pObj.IsEmpty())
- return false;
-
- CJS_Field* pJSField =
- static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pObj));
- Field* pField = static_cast<Field*>(pJSField->GetEmbedObject());
- pField->AttachField(m_pJSDoc, *pStr);
- FormFieldArray.SetElement(pRuntime, j++, CJS_Value(pRuntime, pJSField));
- }
-
- vRet = CJS_Value(pRuntime, FormFieldArray);
- return true;
-}
-
-bool Field::getItemAt(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int iSize = params.size();
- int nIdx = -1;
- if (iSize >= 1)
- nIdx = params[0].ToInt(pRuntime);
-
- bool bExport = true;
- if (iSize >= 2)
- bExport = params[1].ToBool(pRuntime);
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if ((pFormField->GetFieldType() == FIELDTYPE_LISTBOX) ||
- (pFormField->GetFieldType() == FIELDTYPE_COMBOBOX)) {
- if (nIdx == -1 || nIdx > pFormField->CountOptions())
- nIdx = pFormField->CountOptions() - 1;
- if (bExport) {
- CFX_WideString strval = pFormField->GetOptionValue(nIdx);
- if (strval.IsEmpty())
- vRet = CJS_Value(pRuntime, pFormField->GetOptionLabel(nIdx).c_str());
- else
- vRet = CJS_Value(pRuntime, strval.c_str());
- } else {
- vRet = CJS_Value(pRuntime, pFormField->GetOptionLabel(nIdx).c_str());
- }
- } else {
- return false;
- }
-
- return true;
-}
-
-bool Field::getLock(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::insertItemAt(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Field::isBoxChecked(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int nIndex = -1;
- if (params.size() >= 1)
- nIndex = params[0].ToInt(pRuntime);
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (nIndex < 0 || nIndex >= pFormField->CountControls()) {
- return false;
- }
-
- vRet = CJS_Value(pRuntime,
- ((pFormField->GetFieldType() == FIELDTYPE_CHECKBOX ||
- pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON) &&
- pFormField->GetControl(nIndex)->IsChecked() != 0));
- return true;
-}
-
-bool Field::isDefaultChecked(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int nIndex = -1;
- if (params.size() >= 1)
- nIndex = params[0].ToInt(pRuntime);
-
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- if (nIndex < 0 || nIndex >= pFormField->CountControls())
- return false;
-
- vRet = CJS_Value(pRuntime,
- ((pFormField->GetFieldType() == FIELDTYPE_CHECKBOX ||
- pFormField->GetFieldType() == FIELDTYPE_RADIOBUTTON) &&
- pFormField->GetControl(nIndex)->IsDefaultChecked() != 0));
- return true;
-}
-
-bool Field::setAction(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Field::setFocus(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
- if (FieldArray.empty())
- return false;
-
- CPDF_FormField* pFormField = FieldArray[0];
- int32_t nCount = pFormField->CountControls();
- if (nCount < 1)
- return false;
-
- CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
- CPDFSDK_Widget* pWidget = nullptr;
- if (nCount == 1) {
- pWidget = pInterForm->GetWidget(pFormField->GetControl(0));
- } else {
- UnderlyingPageType* pPage =
- UnderlyingFromFPDFPage(m_pFormFillEnv->GetCurrentPage(
- m_pFormFillEnv->GetUnderlyingDocument()));
- if (!pPage)
- return false;
- if (CPDFSDK_PageView* pCurPageView =
- m_pFormFillEnv->GetPageView(pPage, true)) {
- for (int32_t i = 0; i < nCount; i++) {
- if (CPDFSDK_Widget* pTempWidget =
- pInterForm->GetWidget(pFormField->GetControl(i))) {
- if (pTempWidget->GetPDFPage() == pCurPageView->GetPDFPage()) {
- pWidget = pTempWidget;
- break;
- }
- }
- }
- }
- }
-
- if (pWidget) {
- CPDFSDK_Annot::ObservedPtr pObserved(pWidget);
- m_pFormFillEnv->SetFocusAnnot(&pObserved);
- }
-
- return true;
-}
-
-bool Field::setItems(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool Field::setLock(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::signatureGetModifications(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::signatureGetSeedValue(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::signatureInfo(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::signatureSetSeedValue(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::signatureSign(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::signatureValidate(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool Field::source(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsGetting()) {
- vp << (CJS_Object*)nullptr;
- }
-
- return true;
-}
-
-void Field::AddDelay_Int(FIELD_PROP prop, int32_t n) {
- CJS_DelayData* pNewData =
- new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
- pNewData->num = n;
- m_pJSDoc->AddDelayData(pNewData);
-}
-
-void Field::AddDelay_Bool(FIELD_PROP prop, bool b) {
- CJS_DelayData* pNewData =
- new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
- pNewData->b = b;
- m_pJSDoc->AddDelayData(pNewData);
-}
-
-void Field::AddDelay_String(FIELD_PROP prop, const CFX_ByteString& string) {
- CJS_DelayData* pNewData =
- new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
- pNewData->string = string;
- m_pJSDoc->AddDelayData(pNewData);
-}
-
-void Field::AddDelay_WideString(FIELD_PROP prop, const CFX_WideString& string) {
- CJS_DelayData* pNewData =
- new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
- pNewData->widestring = string;
- m_pJSDoc->AddDelayData(pNewData);
-}
-
-void Field::AddDelay_Rect(FIELD_PROP prop, const CFX_FloatRect& rect) {
- CJS_DelayData* pNewData =
- new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
- pNewData->rect = rect;
- m_pJSDoc->AddDelayData(pNewData);
-}
-
-void Field::AddDelay_Color(FIELD_PROP prop, const CPWL_Color& color) {
- CJS_DelayData* pNewData =
- new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
- pNewData->color = color;
- m_pJSDoc->AddDelayData(pNewData);
-}
-
-void Field::AddDelay_WordArray(FIELD_PROP prop,
- const std::vector<uint32_t>& array) {
- CJS_DelayData* pNewData =
- new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
- pNewData->wordarray = array;
- m_pJSDoc->AddDelayData(pNewData);
-}
-
-void Field::AddDelay_WideStringArray(FIELD_PROP prop,
- const std::vector<CFX_WideString>& array) {
- CJS_DelayData* pNewData =
- new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
- pNewData->widestringarray = array;
- m_pJSDoc->AddDelayData(pNewData);
-}
-
-void Field::DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CJS_DelayData* pData) {
- ASSERT(pFormFillEnv);
- switch (pData->eProp) {
- case FP_ALIGNMENT:
- Field::SetAlignment(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->string);
- break;
- case FP_BORDERSTYLE:
- Field::SetBorderStyle(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->string);
- break;
- case FP_BUTTONALIGNX:
- Field::SetButtonAlignX(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->num);
- break;
- case FP_BUTTONALIGNY:
- Field::SetButtonAlignY(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->num);
- break;
- case FP_BUTTONFITBOUNDS:
- Field::SetButtonFitBounds(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->b);
- break;
- case FP_BUTTONPOSITION:
- Field::SetButtonPosition(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->num);
- break;
- case FP_BUTTONSCALEHOW:
- Field::SetButtonScaleHow(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->num);
- break;
- case FP_BUTTONSCALEWHEN:
- Field::SetButtonScaleWhen(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->num);
- break;
- case FP_CALCORDERINDEX:
- Field::SetCalcOrderIndex(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->num);
- break;
- case FP_CHARLIMIT:
- Field::SetCharLimit(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->num);
- break;
- case FP_COMB:
- Field::SetComb(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->b);
- break;
- case FP_COMMITONSELCHANGE:
- Field::SetCommitOnSelChange(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->b);
- break;
- case FP_CURRENTVALUEINDICES:
- Field::SetCurrentValueIndices(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->wordarray);
- break;
- case FP_DEFAULTVALUE:
- Field::SetDefaultValue(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->widestring);
- break;
- case FP_DONOTSCROLL:
- Field::SetDoNotScroll(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->b);
- break;
- case FP_DISPLAY:
- Field::SetDisplay(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->num);
- break;
- case FP_FILLCOLOR:
- Field::SetFillColor(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->color);
- break;
- case FP_HIDDEN:
- Field::SetHidden(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->b);
- break;
- case FP_HIGHLIGHT:
- Field::SetHighlight(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->string);
- break;
- case FP_LINEWIDTH:
- Field::SetLineWidth(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->num);
- break;
- case FP_MULTILINE:
- Field::SetMultiline(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->b);
- break;
- case FP_MULTIPLESELECTION:
- Field::SetMultipleSelection(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->b);
- break;
- case FP_PASSWORD:
- Field::SetPassword(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->b);
- break;
- case FP_RECT:
- Field::SetRect(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->rect);
- break;
- case FP_RICHTEXT:
- // Not supported.
- break;
- case FP_RICHVALUE:
- break;
- case FP_ROTATION:
- Field::SetRotation(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->num);
- break;
- case FP_STROKECOLOR:
- Field::SetStrokeColor(pFormFillEnv, pData->sFieldName,
- pData->nControlIndex, pData->color);
- break;
- case FP_STYLE:
- Field::SetStyle(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->string);
- break;
- case FP_TEXTCOLOR:
- Field::SetTextColor(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->color);
- break;
- case FP_TEXTFONT:
- Field::SetTextFont(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->string);
- break;
- case FP_TEXTSIZE:
- Field::SetTextSize(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->num);
- break;
- case FP_USERNAME:
- Field::SetUserName(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->widestring);
- break;
- case FP_VALUE:
- Field::SetValue(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
- pData->widestringarray);
- break;
- }
-}
-
-void Field::AddField(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- int nPageIndex,
- int nFieldType,
- const CFX_WideString& sName,
- const CFX_FloatRect& rcCoords) {
- // Not supported.
-}
diff --git a/fpdfsdk/javascript/Field.h b/fpdfsdk/javascript/Field.h
deleted file mode 100644
index 462c127..0000000
--- a/fpdfsdk/javascript/Field.h
+++ /dev/null
@@ -1,598 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_FIELD_H_
-#define FPDFSDK_JAVASCRIPT_FIELD_H_
-
-#include <string>
-#include <vector>
-
-#include "core/fxcrt/cfx_observable.h"
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h" // For CPWL_Color.
-
-class CPDFSDK_Widget;
-class Document;
-
-enum FIELD_PROP {
- FP_ALIGNMENT,
- FP_BORDERSTYLE,
- FP_BUTTONALIGNX,
- FP_BUTTONALIGNY,
- FP_BUTTONFITBOUNDS,
- FP_BUTTONPOSITION,
- FP_BUTTONSCALEHOW,
- FP_BUTTONSCALEWHEN,
- FP_CALCORDERINDEX,
- FP_CHARLIMIT,
- FP_COMB,
- FP_COMMITONSELCHANGE,
- FP_CURRENTVALUEINDICES,
- FP_DEFAULTVALUE,
- FP_DONOTSCROLL,
- FP_DISPLAY,
- FP_FILLCOLOR,
- FP_HIDDEN,
- FP_HIGHLIGHT,
- FP_LINEWIDTH,
- FP_MULTILINE,
- FP_MULTIPLESELECTION,
- FP_PASSWORD,
- FP_RECT,
- FP_RICHTEXT,
- FP_RICHVALUE,
- FP_ROTATION,
- FP_STROKECOLOR,
- FP_STYLE,
- FP_TEXTCOLOR,
- FP_TEXTFONT,
- FP_TEXTSIZE,
- FP_USERNAME,
- FP_VALUE
-};
-
-struct CJS_DelayData {
- CJS_DelayData(FIELD_PROP prop, int idx, const CFX_WideString& name);
- ~CJS_DelayData();
-
- FIELD_PROP eProp;
- int nControlIndex;
- CFX_WideString sFieldName;
- int32_t num;
- bool b;
- CFX_ByteString string;
- CFX_WideString widestring;
- CFX_FloatRect rect;
- CPWL_Color color;
- std::vector<uint32_t> wordarray;
- std::vector<CFX_WideString> widestringarray;
-};
-
-class Field : public CJS_EmbedObj {
- public:
- explicit Field(CJS_Object* pJSObject);
- ~Field() override;
-
- bool alignment(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool borderStyle(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool buttonAlignX(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool buttonAlignY(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool buttonFitBounds(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool buttonPosition(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool buttonScaleHow(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool buttonScaleWhen(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool calcOrderIndex(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool charLimit(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool comb(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool commitOnSelChange(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool currentValueIndices(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool defaultStyle(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool defaultValue(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool doNotScroll(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool doNotSpellCheck(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool delay(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool display(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool doc(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool editable(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool exportValues(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool fileSelect(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool fillColor(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool hidden(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool highlight(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool lineWidth(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool multiline(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool multipleSelection(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool name(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool numItems(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool page(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool password(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool print(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool radiosInUnison(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool readonly(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool rect(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool required(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool richText(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool richValue(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool rotation(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool strokeColor(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool style(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool submitName(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool textColor(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool textFont(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool textSize(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool type(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool userName(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool value(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool valueAsString(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool source(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
-
- bool browseForFileToSubmit(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool buttonGetCaption(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool buttonGetIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool buttonImportIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool buttonSetCaption(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool buttonSetIcon(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool checkThisBox(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool clearItems(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool defaultIsChecked(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool deleteItemAt(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getArray(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getItemAt(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool getLock(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool insertItemAt(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool isBoxChecked(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool isDefaultChecked(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool setAction(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool setFocus(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool setItems(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool setLock(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool signatureGetModifications(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool signatureGetSeedValue(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool signatureInfo(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool signatureSetSeedValue(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool signatureSign(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool signatureValidate(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
-
- static void SetAlignment(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string);
- static void SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string);
- static void SetButtonAlignX(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetButtonAlignY(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetButtonFitBounds(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b);
- static void SetButtonPosition(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetButtonScaleHow(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetButtonScaleWhen(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetCalcOrderIndex(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetCharLimit(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetComb(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b);
- static void SetCommitOnSelChange(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b);
- static void SetCurrentValueIndices(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const std::vector<uint32_t>& array);
- static void SetDefaultStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex);
- static void SetDefaultValue(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_WideString& string);
- static void SetDoNotScroll(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b);
- static void SetDisplay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetFillColor(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CPWL_Color& color);
- static void SetHidden(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b);
- static void SetHighlight(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string);
- static void SetLineWidth(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetMultiline(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b);
- static void SetMultipleSelection(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b);
- static void SetPassword(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- bool b);
- static void SetRect(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_FloatRect& rect);
- static void SetRotation(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetStrokeColor(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CPWL_Color& color);
- static void SetStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string);
- static void SetTextColor(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CPWL_Color& color);
- static void SetTextFont(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_ByteString& string);
- static void SetTextSize(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- int number);
- static void SetUserName(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const CFX_WideString& string);
- static void SetValue(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& swFieldName,
- int nControlIndex,
- const std::vector<CFX_WideString>& strArray);
-
- static void AddField(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- int nPageIndex,
- int nFieldType,
- const CFX_WideString& sName,
- const CFX_FloatRect& rcCoords);
-
- static void UpdateFormField(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDF_FormField* pFormField,
- bool bChangeMark,
- bool bResetAP,
- bool bRefresh);
- static void UpdateFormControl(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDF_FormControl* pFormControl,
- bool bChangeMark,
- bool bResetAP,
- bool bRefresh);
-
- static CPDFSDK_Widget* GetWidget(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CPDF_FormControl* pFormControl);
- static std::vector<CPDF_FormField*> GetFormFields(
- CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& csFieldName);
-
- static void DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CJS_DelayData* pData);
-
- bool AttachField(Document* pDocument, const CFX_WideString& csFieldName);
- void SetDelay(bool bDelay);
-
- protected:
- void ParseFieldName(const std::wstring& strFieldNameParsed,
- std::wstring& strFieldName,
- int& iControlNo);
- std::vector<CPDF_FormField*> GetFormFields(
- const CFX_WideString& csFieldName) const;
- CPDF_FormControl* GetSmartFieldControl(CPDF_FormField* pFormField);
- bool ValueIsOccur(CPDF_FormField* pFormField, CFX_WideString csOptLabel);
-
- void AddDelay_Int(FIELD_PROP prop, int32_t n);
- void AddDelay_Bool(FIELD_PROP prop, bool b);
- void AddDelay_String(FIELD_PROP prop, const CFX_ByteString& string);
- void AddDelay_WideString(FIELD_PROP prop, const CFX_WideString& string);
- void AddDelay_Rect(FIELD_PROP prop, const CFX_FloatRect& rect);
- void AddDelay_Color(FIELD_PROP prop, const CPWL_Color& color);
- void AddDelay_WordArray(FIELD_PROP prop, const std::vector<uint32_t>& array);
- void AddDelay_WideStringArray(FIELD_PROP prop,
- const std::vector<CFX_WideString>& array);
-
- void DoDelay();
-
- public:
- Document* m_pJSDoc;
- CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
- CFX_WideString m_FieldName;
- int m_nFormControlIndex;
- bool m_bCanSet;
- bool m_bDelay;
-};
-
-class CJS_Field : public CJS_Object {
- public:
- explicit CJS_Field(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Field() override {}
-
- void InitInstance(IJS_Runtime* pIRuntime) override;
-
- DECLARE_JS_CLASS();
- JS_STATIC_PROP(alignment, Field);
- JS_STATIC_PROP(borderStyle, Field);
- JS_STATIC_PROP(buttonAlignX, Field);
- JS_STATIC_PROP(buttonAlignY, Field);
- JS_STATIC_PROP(buttonFitBounds, Field);
- JS_STATIC_PROP(buttonPosition, Field);
- JS_STATIC_PROP(buttonScaleHow, Field);
- JS_STATIC_PROP(buttonScaleWhen, Field);
- JS_STATIC_PROP(calcOrderIndex, Field);
- JS_STATIC_PROP(charLimit, Field);
- JS_STATIC_PROP(comb, Field);
- JS_STATIC_PROP(commitOnSelChange, Field);
- JS_STATIC_PROP(currentValueIndices, Field);
- JS_STATIC_PROP(defaultStyle, Field);
- JS_STATIC_PROP(defaultValue, Field);
- JS_STATIC_PROP(doNotScroll, Field);
- JS_STATIC_PROP(doNotSpellCheck, Field);
- JS_STATIC_PROP(delay, Field);
- JS_STATIC_PROP(display, Field);
- JS_STATIC_PROP(doc, Field);
- JS_STATIC_PROP(editable, Field);
- JS_STATIC_PROP(exportValues, Field);
- JS_STATIC_PROP(fileSelect, Field);
- JS_STATIC_PROP(fillColor, Field);
- JS_STATIC_PROP(hidden, Field);
- JS_STATIC_PROP(highlight, Field);
- JS_STATIC_PROP(lineWidth, Field);
- JS_STATIC_PROP(multiline, Field);
- JS_STATIC_PROP(multipleSelection, Field);
- JS_STATIC_PROP(name, Field);
- JS_STATIC_PROP(numItems, Field);
- JS_STATIC_PROP(page, Field);
- JS_STATIC_PROP(password, Field);
- JS_STATIC_PROP(print, Field);
- JS_STATIC_PROP(radiosInUnison, Field);
- JS_STATIC_PROP(readonly, Field);
- JS_STATIC_PROP(rect, Field);
- JS_STATIC_PROP(required, Field);
- JS_STATIC_PROP(richText, Field);
- JS_STATIC_PROP(richValue, Field);
- JS_STATIC_PROP(rotation, Field);
- JS_STATIC_PROP(strokeColor, Field);
- JS_STATIC_PROP(style, Field);
- JS_STATIC_PROP(submitName, Field);
- JS_STATIC_PROP(textColor, Field);
- JS_STATIC_PROP(textFont, Field);
- JS_STATIC_PROP(textSize, Field);
- JS_STATIC_PROP(type, Field);
- JS_STATIC_PROP(userName, Field);
- JS_STATIC_PROP(value, Field);
- JS_STATIC_PROP(valueAsString, Field);
- JS_STATIC_PROP(source, Field);
-
- JS_STATIC_METHOD(browseForFileToSubmit, Field);
- JS_STATIC_METHOD(buttonGetCaption, Field);
- JS_STATIC_METHOD(buttonGetIcon, Field);
- JS_STATIC_METHOD(buttonImportIcon, Field);
- JS_STATIC_METHOD(buttonSetCaption, Field);
- JS_STATIC_METHOD(buttonSetIcon, Field);
- JS_STATIC_METHOD(checkThisBox, Field);
- JS_STATIC_METHOD(clearItems, Field);
- JS_STATIC_METHOD(defaultIsChecked, Field);
- JS_STATIC_METHOD(deleteItemAt, Field);
- JS_STATIC_METHOD(getArray, Field);
- JS_STATIC_METHOD(getItemAt, Field);
- JS_STATIC_METHOD(getLock, Field);
- JS_STATIC_METHOD(insertItemAt, Field);
- JS_STATIC_METHOD(isBoxChecked, Field);
- JS_STATIC_METHOD(isDefaultChecked, Field);
- JS_STATIC_METHOD(setAction, Field);
- JS_STATIC_METHOD(setFocus, Field);
- JS_STATIC_METHOD(setItems, Field);
- JS_STATIC_METHOD(setLock, Field);
- JS_STATIC_METHOD(signatureGetModifications, Field);
- JS_STATIC_METHOD(signatureGetSeedValue, Field);
- JS_STATIC_METHOD(signatureInfo, Field);
- JS_STATIC_METHOD(signatureSetSeedValue, Field);
- JS_STATIC_METHOD(signatureSign, Field);
- JS_STATIC_METHOD(signatureValidate, Field);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_FIELD_H_
diff --git a/fpdfsdk/javascript/Icon.cpp b/fpdfsdk/javascript/Icon.cpp
deleted file mode 100644
index fa2f92f..0000000
--- a/fpdfsdk/javascript/Icon.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 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/javascript/Icon.h"
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-
-JSConstSpec CJS_Icon::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Icon::PropertySpecs[] = {
- {"name", get_name_static, set_name_static},
- {0, 0, 0}};
-
-JSMethodSpec CJS_Icon::MethodSpecs[] = {{0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Icon, Icon)
-
-Icon::Icon(CJS_Object* pJSObject)
- : CJS_EmbedObj(pJSObject), m_swIconName(L"") {}
-
-Icon::~Icon() {}
-
-bool Icon::name(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- vp << m_swIconName;
- return true;
-}
diff --git a/fpdfsdk/javascript/Icon.h b/fpdfsdk/javascript/Icon.h
deleted file mode 100644
index 5580678..0000000
--- a/fpdfsdk/javascript/Icon.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_ICON_H_
-#define FPDFSDK_JAVASCRIPT_ICON_H_
-
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class CPDF_Stream;
-
-class Icon : public CJS_EmbedObj {
- public:
- explicit Icon(CJS_Object* pJSObject);
- ~Icon() override;
-
- bool name(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- CFX_WideString GetIconName() const { return m_swIconName; }
- void SetIconName(CFX_WideString name) { m_swIconName = name; }
-
- private:
- CFX_WideString m_swIconName;
-};
-
-class CJS_Icon : public CJS_Object {
- public:
- explicit CJS_Icon(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Icon() override {}
-
- DECLARE_JS_CLASS();
- JS_STATIC_PROP(name, Icon);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_ICON_H_
diff --git a/fpdfsdk/javascript/JS_Define.h b/fpdfsdk/javascript/JS_Define.h
deleted file mode 100644
index 375ca3a..0000000
--- a/fpdfsdk/javascript/JS_Define.h
+++ /dev/null
@@ -1,456 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_JS_DEFINE_H_
-#define FPDFSDK_JAVASCRIPT_JS_DEFINE_H_
-
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/resource.h"
-#include "fxjs/fxjs_v8.h"
-
-struct JSConstSpec {
- enum Type { Number = 0, String = 1 };
-
- const char* pName;
- Type eType;
- double number;
- const char* pStr;
-};
-
-struct JSPropertySpec {
- const char* pName;
- v8::AccessorGetterCallback pPropGet;
- v8::AccessorSetterCallback pPropPut;
-};
-
-struct JSMethodSpec {
- const char* pName;
- v8::FunctionCallback pMethodCall;
-};
-
-template <class C, bool (C::*M)(CJS_Runtime*, CJS_PropValue&, CFX_WideString&)>
-void JSPropGetter(const char* prop_name_string,
- const char* class_name_string,
- v8::Local<v8::String> property,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- CJS_Runtime* pRuntime =
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
- if (!pRuntime)
- return;
- CJS_Object* pJSObj =
- static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
- if (!pJSObj)
- return;
- C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
- CFX_WideString sError;
- CJS_PropValue value(pRuntime);
- value.StartGetting();
- if (!(pObj->*M)(pRuntime, value, sError)) {
- pRuntime->Error(
- JSFormatErrorString(class_name_string, prop_name_string, sError));
- return;
- }
- info.GetReturnValue().Set(value.GetJSValue()->ToV8Value(pRuntime));
-}
-
-template <class C, bool (C::*M)(CJS_Runtime*, CJS_PropValue&, CFX_WideString&)>
-void JSPropSetter(const char* prop_name_string,
- const char* class_name_string,
- v8::Local<v8::String> property,
- v8::Local<v8::Value> value,
- const v8::PropertyCallbackInfo<void>& info) {
- CJS_Runtime* pRuntime =
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
- if (!pRuntime)
- return;
- CJS_Object* pJSObj =
- static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
- if (!pJSObj)
- return;
- C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
- CFX_WideString sError;
- CJS_PropValue propValue(pRuntime, CJS_Value(pRuntime, value));
- propValue.StartSetting();
- if (!(pObj->*M)(pRuntime, propValue, sError)) {
- pRuntime->Error(
- JSFormatErrorString(class_name_string, prop_name_string, sError));
- }
-}
-
-#define JS_STATIC_PROP(prop_name, class_name) \
- static void get_##prop_name##_static( \
- v8::Local<v8::String> property, \
- const v8::PropertyCallbackInfo<v8::Value>& info) { \
- JSPropGetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
- property, info); \
- } \
- static void set_##prop_name##_static( \
- v8::Local<v8::String> property, v8::Local<v8::Value> value, \
- const v8::PropertyCallbackInfo<void>& info) { \
- JSPropSetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
- property, value, info); \
- }
-
-template <class C,
- bool (C::*M)(CJS_Runtime*,
- const std::vector<CJS_Value>&,
- CJS_Value&,
- CFX_WideString&)>
-void JSMethod(const char* method_name_string,
- const char* class_name_string,
- const v8::FunctionCallbackInfo<v8::Value>& info) {
- CJS_Runtime* pRuntime =
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
- if (!pRuntime)
- return;
- std::vector<CJS_Value> parameters;
- for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
- parameters.push_back(CJS_Value(pRuntime, info[i]));
- }
- CJS_Object* pJSObj =
- static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
- if (!pJSObj)
- return;
- C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
- CFX_WideString sError;
- CJS_Value valueRes(pRuntime);
- if (!(pObj->*M)(pRuntime, parameters, valueRes, sError)) {
- pRuntime->Error(
- JSFormatErrorString(class_name_string, method_name_string, sError));
- return;
- }
- info.GetReturnValue().Set(valueRes.ToV8Value(pRuntime));
-}
-
-#define JS_STATIC_METHOD(method_name, class_name) \
- static void method_name##_static( \
- const v8::FunctionCallbackInfo<v8::Value>& info) { \
- JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
- info); \
- }
-
-#define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \
- static void method_name##_static( \
- const v8::FunctionCallbackInfo<v8::Value>& info) { \
- JSMethod<class_alternate, &class_alternate::method_name>( \
- #method_name, #class_name, info); \
- }
-
-// All JS classes have a name, an object defintion ID, and the ability to
-// register themselves with FXJS_V8. We never make a BASE class on its own
-// because it can't really do anything.
-#define DECLARE_JS_CLASS_BASE_PART() \
- static const char* g_pClassName; \
- static int g_nObjDefnID; \
- static void DefineJSObjects(CFXJS_Engine* pEngine, FXJSOBJTYPE eObjType);
-
-#define IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
- const char* js_class_name::g_pClassName = #class_name; \
- int js_class_name::g_nObjDefnID = -1;
-
-// CONST classes provide constants, but not constructors, methods, or props.
-#define DECLARE_JS_CLASS_CONST() \
- DECLARE_JS_CLASS_BASE_PART() \
- DECLARE_JS_CLASS_CONST_PART()
-
-#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
- IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
- IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
- void js_class_name::DefineJSObjects(CFXJS_Engine* pEngine, \
- FXJSOBJTYPE eObjType) { \
- g_nObjDefnID = pEngine->DefineObj(js_class_name::g_pClassName, eObjType, \
- nullptr, nullptr); \
- DefineConsts(pEngine); \
- }
-
-#define DECLARE_JS_CLASS_CONST_PART() \
- static JSConstSpec ConstSpecs[]; \
- static void DefineConsts(CFXJS_Engine* pEngine);
-
-#define IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
- void js_class_name::DefineConsts(CFXJS_Engine* pEngine) { \
- for (size_t i = 0; i < FX_ArraySize(ConstSpecs) - 1; ++i) { \
- pEngine->DefineObjConst(g_nObjDefnID, ConstSpecs[i].pName, \
- ConstSpecs[i].eType == JSConstSpec::Number \
- ? pEngine->NewNumber(ConstSpecs[i].number) \
- : pEngine->NewString(ConstSpecs[i].pStr)); \
- } \
- }
-
-// Convenience macros for declaring classes without an alternate.
-#define DECLARE_JS_CLASS() DECLARE_JS_CLASS_RICH()
-#define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
- IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
-
-// Rich JS classes provide constants, methods, properties, and the ability
-// to construct native object state.
-#define DECLARE_JS_CLASS_RICH() \
- DECLARE_JS_CLASS_BASE_PART() \
- DECLARE_JS_CLASS_CONST_PART() \
- DECLARE_JS_CLASS_RICH_PART()
-
-#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
- IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
- IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
- IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
- void js_class_name::DefineJSObjects(CFXJS_Engine* pEngine, \
- FXJSOBJTYPE eObjType) { \
- g_nObjDefnID = pEngine->DefineObj(js_class_name::g_pClassName, eObjType, \
- JSConstructor, JSDestructor); \
- DefineConsts(pEngine); \
- DefineProps(pEngine); \
- DefineMethods(pEngine); \
- }
-
-#define DECLARE_JS_CLASS_RICH_PART() \
- static void JSConstructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj); \
- static void JSDestructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj); \
- static void DefineProps(CFXJS_Engine* pEngine); \
- static void DefineMethods(CFXJS_Engine* pEngine); \
- static JSPropertySpec PropertySpecs[]; \
- static JSMethodSpec MethodSpecs[];
-
-#define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, \
- class_name) \
- void js_class_name::JSConstructor(CFXJS_Engine* pEngine, \
- v8::Local<v8::Object> obj) { \
- CJS_Object* pObj = new js_class_name(obj); \
- pObj->SetEmbedObject(new class_alternate(pObj)); \
- pEngine->SetObjectPrivate(obj, (void*)pObj); \
- pObj->InitInstance(static_cast<CJS_Runtime*>(pEngine)); \
- } \
- void js_class_name::JSDestructor(CFXJS_Engine* pEngine, \
- v8::Local<v8::Object> obj) { \
- delete static_cast<js_class_name*>(pEngine->GetObjectPrivate(obj)); \
- } \
- void js_class_name::DefineProps(CFXJS_Engine* pEngine) { \
- for (size_t i = 0; i < FX_ArraySize(PropertySpecs) - 1; ++i) { \
- pEngine->DefineObjProperty(g_nObjDefnID, PropertySpecs[i].pName, \
- PropertySpecs[i].pPropGet, \
- PropertySpecs[i].pPropPut); \
- } \
- } \
- void js_class_name::DefineMethods(CFXJS_Engine* pEngine) { \
- for (size_t i = 0; i < FX_ArraySize(MethodSpecs) - 1; ++i) { \
- pEngine->DefineObjMethod(g_nObjDefnID, MethodSpecs[i].pName, \
- MethodSpecs[i].pMethodCall); \
- } \
- }
-
-// Special JS classes implement methods, props, and queries, but not consts.
-#define DECLARE_SPECIAL_JS_CLASS() \
- DECLARE_JS_CLASS_BASE_PART() \
- DECLARE_JS_CLASS_CONST_PART() \
- DECLARE_JS_CLASS_RICH_PART() \
- DECLARE_SPECIAL_JS_CLASS_PART()
-
-#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
- IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name) \
- IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name) \
- IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name) \
- IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, class_name) \
- void js_class_name::DefineJSObjects(CFXJS_Engine* pEngine, \
- FXJSOBJTYPE eObjType) { \
- g_nObjDefnID = pEngine->DefineObj(js_class_name::g_pClassName, eObjType, \
- JSConstructor, JSDestructor); \
- DefineConsts(pEngine); \
- DefineProps(pEngine); \
- DefineMethods(pEngine); \
- DefineAllProperties(pEngine); \
- }
-
-#define DECLARE_SPECIAL_JS_CLASS_PART() \
- static void queryprop_static( \
- v8::Local<v8::String> property, \
- const v8::PropertyCallbackInfo<v8::Integer>& info); \
- static void getprop_static(v8::Local<v8::String> property, \
- const v8::PropertyCallbackInfo<v8::Value>& info); \
- static void putprop_static(v8::Local<v8::String> property, \
- v8::Local<v8::Value> value, \
- const v8::PropertyCallbackInfo<v8::Value>& info); \
- static void delprop_static( \
- v8::Local<v8::String> property, \
- const v8::PropertyCallbackInfo<v8::Boolean>& info); \
- static void DefineAllProperties(CFXJS_Engine* pEngine);
-
-#define IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, \
- class_name) \
- void js_class_name::queryprop_static( \
- v8::Local<v8::String> property, \
- const v8::PropertyCallbackInfo<v8::Integer>& info) { \
- JSSpecialPropQuery<class_alternate>(#class_name, property, info); \
- } \
- void js_class_name::getprop_static( \
- v8::Local<v8::String> property, \
- const v8::PropertyCallbackInfo<v8::Value>& info) { \
- JSSpecialPropGet<class_alternate>(#class_name, property, info); \
- } \
- void js_class_name::putprop_static( \
- v8::Local<v8::String> property, v8::Local<v8::Value> value, \
- const v8::PropertyCallbackInfo<v8::Value>& info) { \
- JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
- } \
- void js_class_name::delprop_static( \
- v8::Local<v8::String> property, \
- const v8::PropertyCallbackInfo<v8::Boolean>& info) { \
- JSSpecialPropDel<class_alternate>(#class_name, property, info); \
- } \
- void js_class_name::DefineAllProperties(CFXJS_Engine* pEngine) { \
- pEngine->DefineObjAllProperties( \
- g_nObjDefnID, js_class_name::queryprop_static, \
- js_class_name::getprop_static, js_class_name::putprop_static, \
- js_class_name::delprop_static); \
- }
-
-template <class Alt>
-void JSSpecialPropQuery(const char*,
- v8::Local<v8::String> property,
- const v8::PropertyCallbackInfo<v8::Integer>& info) {
- CJS_Runtime* pRuntime =
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
- if (!pRuntime)
- return;
-
- CJS_Object* pJSObj =
- static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
- if (!pJSObj)
- return;
-
- Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
- v8::String::Utf8Value utf8_value(property);
- CFX_WideString propname = CFX_WideString::FromUTF8(
- CFX_ByteStringC(*utf8_value, utf8_value.length()));
- bool bRet = pObj->QueryProperty(propname.c_str());
- info.GetReturnValue().Set(bRet ? 4 : 0);
-}
-
-template <class Alt>
-void JSSpecialPropGet(const char* class_name,
- v8::Local<v8::String> property,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- CJS_Runtime* pRuntime =
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
- if (!pRuntime)
- return;
-
- CJS_Object* pJSObj =
- static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
- if (!pJSObj)
- return;
-
- Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
- v8::String::Utf8Value utf8_value(property);
- CFX_WideString propname = CFX_WideString::FromUTF8(
- CFX_ByteStringC(*utf8_value, utf8_value.length()));
- CFX_WideString sError;
- CJS_PropValue value(pRuntime);
- value.StartGetting();
- if (!pObj->DoProperty(pRuntime, propname.c_str(), value, sError)) {
- pRuntime->Error(JSFormatErrorString(class_name, "GetProperty", sError));
- return;
- }
- info.GetReturnValue().Set(value.GetJSValue()->ToV8Value(pRuntime));
-}
-
-template <class Alt>
-void JSSpecialPropPut(const char* class_name,
- v8::Local<v8::String> property,
- v8::Local<v8::Value> value,
- const v8::PropertyCallbackInfo<v8::Value>& info) {
- CJS_Runtime* pRuntime =
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
- if (!pRuntime)
- return;
-
- CJS_Object* pJSObj =
- static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
- if (!pJSObj)
- return;
-
- Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
- v8::String::Utf8Value utf8_value(property);
- CFX_WideString propname = CFX_WideString::FromUTF8(
- CFX_ByteStringC(*utf8_value, utf8_value.length()));
- CFX_WideString sError;
- CJS_PropValue PropValue(pRuntime, CJS_Value(pRuntime, value));
- PropValue.StartSetting();
- if (!pObj->DoProperty(pRuntime, propname.c_str(), PropValue, sError)) {
- pRuntime->Error(JSFormatErrorString(class_name, "PutProperty", sError));
- }
-}
-
-template <class Alt>
-void JSSpecialPropDel(const char* class_name,
- v8::Local<v8::String> property,
- const v8::PropertyCallbackInfo<v8::Boolean>& info) {
- CJS_Runtime* pRuntime =
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
- if (!pRuntime)
- return;
-
- CJS_Object* pJSObj =
- static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
- if (!pJSObj)
- return;
-
- Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
- v8::String::Utf8Value utf8_value(property);
- CFX_WideString propname = CFX_WideString::FromUTF8(
- CFX_ByteStringC(*utf8_value, utf8_value.length()));
- CFX_WideString sError;
- if (!pObj->DelProperty(pRuntime, propname.c_str(), sError)) {
- CFX_ByteString cbName;
- cbName.Format("%s.%s", class_name, "DelProperty");
- // Probably a missing call to JSFX_Error().
- }
-}
-
-template <bool (*F)(CJS_Runtime*,
- const std::vector<CJS_Value>&,
- CJS_Value&,
- CFX_WideString&)>
-void JSGlobalFunc(const char* func_name_string,
- const v8::FunctionCallbackInfo<v8::Value>& info) {
- CJS_Runtime* pRuntime =
- CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
- if (!pRuntime)
- return;
- std::vector<CJS_Value> parameters;
- for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
- parameters.push_back(CJS_Value(pRuntime, info[i]));
- }
- CJS_Value valueRes(pRuntime);
- CFX_WideString sError;
- if (!(*F)(pRuntime, parameters, valueRes, sError)) {
- pRuntime->Error(JSFormatErrorString(func_name_string, nullptr, sError));
- return;
- }
- info.GetReturnValue().Set(valueRes.ToV8Value(pRuntime));
-}
-
-#define JS_STATIC_GLOBAL_FUN(fun_name) \
- static void fun_name##_static( \
- const v8::FunctionCallbackInfo<v8::Value>& info) { \
- JSGlobalFunc<fun_name>(#fun_name, info); \
- }
-
-#define JS_STATIC_DECLARE_GLOBAL_FUN() \
- static JSMethodSpec GlobalFunctionSpecs[]; \
- static void DefineJSObjects(CFXJS_Engine* pEngine)
-
-#define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
- void js_class_name::DefineJSObjects(CFXJS_Engine* pEngine) { \
- for (size_t i = 0; i < FX_ArraySize(GlobalFunctionSpecs) - 1; ++i) { \
- pEngine->DefineGlobalMethod( \
- js_class_name::GlobalFunctionSpecs[i].pName, \
- js_class_name::GlobalFunctionSpecs[i].pMethodCall); \
- } \
- }
-
-#endif // FPDFSDK_JAVASCRIPT_JS_DEFINE_H_
diff --git a/fpdfsdk/javascript/JS_EventHandler.cpp b/fpdfsdk/javascript/JS_EventHandler.cpp
deleted file mode 100644
index bd1c8e2..0000000
--- a/fpdfsdk/javascript/JS_EventHandler.cpp
+++ /dev/null
@@ -1,653 +0,0 @@
-// Copyright 2014 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/javascript/JS_EventHandler.h"
-
-#include "fpdfsdk/javascript/Document.h"
-#include "fpdfsdk/javascript/Field.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-
-CJS_EventHandler::CJS_EventHandler(CJS_EventContext* pContext)
- : m_pJSEventContext(pContext),
- m_eEventType(JET_UNKNOWN),
- m_bValid(false),
- m_pWideStrChange(nullptr),
- m_nCommitKey(-1),
- m_bKeyDown(false),
- m_bModifier(false),
- m_bShift(false),
- m_pISelEnd(nullptr),
- m_nSelEndDu(0),
- m_pISelStart(nullptr),
- m_nSelStartDu(0),
- m_bWillCommit(false),
- m_pValue(nullptr),
- m_bFieldFull(false),
- m_pbRc(nullptr),
- m_bRcDu(false),
- m_pTargetBookMark(nullptr),
- m_pTargetFormFillEnv(nullptr),
- m_pTargetAnnot(nullptr) {}
-
-CJS_EventHandler::~CJS_EventHandler() {}
-
-void CJS_EventHandler::OnApp_Init() {
- Initial(JET_APP_INIT);
-}
-
-void CJS_EventHandler::OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName) {
- Initial(JET_DOC_OPEN);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
- m_strTargetName = strTargetName;
-}
-
-void CJS_EventHandler::OnDoc_WillPrint(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_DOC_WILLPRINT);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnDoc_DidPrint(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_DOC_DIDPRINT);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnDoc_WillSave(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_DOC_WILLSAVE);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnDoc_DidSave(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_DOC_DIDSAVE);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnDoc_WillClose(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_DOC_WILLCLOSE);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_PAGE_OPEN);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_PAGE_CLOSE);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnPage_InView(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_PAGE_INVIEW);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnPage_OutView(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- Initial(JET_PAGE_OUTVIEW);
- m_pTargetFormFillEnv.Reset(pFormFillEnv);
-}
-
-void CJS_EventHandler::OnField_MouseEnter(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) {
- Initial(JET_FIELD_MOUSEENTER);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
-
- m_strTargetName = pTarget->GetFullName();
-}
-
-void CJS_EventHandler::OnField_MouseExit(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) {
- Initial(JET_FIELD_MOUSEEXIT);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_strTargetName = pTarget->GetFullName();
-}
-
-void CJS_EventHandler::OnField_MouseDown(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) {
- Initial(JET_FIELD_MOUSEDOWN);
- m_eEventType = JET_FIELD_MOUSEDOWN;
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_strTargetName = pTarget->GetFullName();
-}
-
-void CJS_EventHandler::OnField_MouseUp(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) {
- Initial(JET_FIELD_MOUSEUP);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_strTargetName = pTarget->GetFullName();
-}
-
-void CJS_EventHandler::OnField_Focus(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) {
- Initial(JET_FIELD_FOCUS);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_strTargetName = pTarget->GetFullName();
- m_pValue = (CFX_WideString*)&Value;
-}
-
-void CJS_EventHandler::OnField_Blur(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) {
- Initial(JET_FIELD_BLUR);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_strTargetName = pTarget->GetFullName();
- m_pValue = (CFX_WideString*)&Value;
-}
-
-void CJS_EventHandler::OnField_Keystroke(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool KeyDown,
- bool bModifier,
- int& nSelEnd,
- int& nSelStart,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit,
- bool bFieldFull,
- bool& bRc) {
- Initial(JET_FIELD_KEYSTROKE);
-
- m_nCommitKey = 0;
- m_pWideStrChange = &strChange;
- m_WideStrChangeEx = strChangeEx;
- m_bKeyDown = KeyDown;
- m_bModifier = bModifier;
- m_pISelEnd = &nSelEnd;
- m_pISelStart = &nSelStart;
- m_bShift = bShift;
- m_strTargetName = pTarget->GetFullName();
- m_pValue = &Value;
- m_bWillCommit = bWillCommit;
- m_pbRc = &bRc;
- m_bFieldFull = bFieldFull;
-}
-
-void CJS_EventHandler::OnField_Validate(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool bKeyDown,
- bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) {
- Initial(JET_FIELD_VALIDATE);
-
- m_pWideStrChange = &strChange;
- m_WideStrChangeEx = strChangeEx;
- m_bKeyDown = bKeyDown;
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_strTargetName = pTarget->GetFullName();
- m_pValue = &Value;
- m_pbRc = &bRc;
-}
-
-void CJS_EventHandler::OnField_Calculate(CPDF_FormField* pSource,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) {
- Initial(JET_FIELD_CALCULATE);
-
- if (pSource)
- m_strSourceName = pSource->GetFullName();
- m_strTargetName = pTarget->GetFullName();
- m_pValue = &Value;
- m_pbRc = &bRc;
-}
-
-void CJS_EventHandler::OnField_Format(CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit) {
- Initial(JET_FIELD_FORMAT);
-
- m_nCommitKey = 0;
- m_strTargetName = pTarget->GetFullName();
- m_pValue = &Value;
- m_bWillCommit = bWillCommit;
-}
-
-void CJS_EventHandler::OnScreen_Focus(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_FOCUS);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_Blur(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_BLUR);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_Open(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_OPEN);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_Close(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_CLOSE);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_MouseDown(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_MOUSEDOWN);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_MouseUp(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_MOUSEUP);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_MouseEnter(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_MOUSEENTER);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_MouseExit(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_MOUSEEXIT);
-
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_InView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_INVIEW);
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnScreen_OutView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- Initial(JET_SCREEN_OUTVIEW);
- m_bModifier = bModifier;
- m_bShift = bShift;
- m_pTargetAnnot.Reset(pScreen);
-}
-
-void CJS_EventHandler::OnLink_MouseUp(
- CPDFSDK_FormFillEnvironment* pTargetFormFillEnv) {
- Initial(JET_LINK_MOUSEUP);
- m_pTargetFormFillEnv.Reset(pTargetFormFillEnv);
-}
-
-void CJS_EventHandler::OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) {
- Initial(JET_BOOKMARK_MOUSEUP);
- m_pTargetBookMark = pBookMark;
-}
-
-void CJS_EventHandler::OnMenu_Exec(
- CPDFSDK_FormFillEnvironment* pTargetFormFillEnv,
- const CFX_WideString& strTargetName) {
- Initial(JET_MENU_EXEC);
- m_pTargetFormFillEnv.Reset(pTargetFormFillEnv);
- m_strTargetName = strTargetName;
-}
-
-void CJS_EventHandler::OnExternal_Exec() {
- Initial(JET_EXTERNAL_EXEC);
-}
-
-void CJS_EventHandler::OnBatchExec(
- CPDFSDK_FormFillEnvironment* pTargetFormFillEnv) {
- Initial(JET_BATCH_EXEC);
- m_pTargetFormFillEnv.Reset(pTargetFormFillEnv);
-}
-
-void CJS_EventHandler::OnConsole_Exec() {
- Initial(JET_CONSOLE_EXEC);
-}
-
-void CJS_EventHandler::Initial(JS_EVENT_T type) {
- m_eEventType = type;
-
- m_strTargetName = L"";
- m_strSourceName = L"";
- m_pWideStrChange = nullptr;
- m_WideStrChangeDu = L"";
- m_WideStrChangeEx = L"";
- m_nCommitKey = -1;
- m_bKeyDown = false;
- m_bModifier = false;
- m_bShift = false;
- m_pISelEnd = nullptr;
- m_nSelEndDu = 0;
- m_pISelStart = nullptr;
- m_nSelStartDu = 0;
- m_bWillCommit = false;
- m_pValue = nullptr;
- m_bFieldFull = false;
- m_pbRc = nullptr;
- m_bRcDu = false;
-
- m_pTargetBookMark = nullptr;
- m_pTargetFormFillEnv.Reset();
- m_pTargetAnnot.Reset();
-
- m_bValid = true;
-}
-
-void CJS_EventHandler::Destroy() {
- m_bValid = false;
-}
-
-bool CJS_EventHandler::IsValid() {
- return m_bValid;
-}
-
-CFX_WideString& CJS_EventHandler::Change() {
- if (m_pWideStrChange) {
- return *m_pWideStrChange;
- }
- return m_WideStrChangeDu;
-}
-
-CFX_WideString CJS_EventHandler::ChangeEx() {
- return m_WideStrChangeEx;
-}
-
-int CJS_EventHandler::CommitKey() {
- return m_nCommitKey;
-}
-
-bool CJS_EventHandler::FieldFull() {
- return m_bFieldFull;
-}
-
-bool CJS_EventHandler::KeyDown() {
- return m_bKeyDown;
-}
-
-bool CJS_EventHandler::Modifier() {
- return m_bModifier;
-}
-
-const FX_WCHAR* CJS_EventHandler::Name() {
- switch (m_eEventType) {
- case JET_APP_INIT:
- return L"Init";
- case JET_BATCH_EXEC:
- return L"Exec";
- case JET_BOOKMARK_MOUSEUP:
- return L"Mouse Up";
- case JET_CONSOLE_EXEC:
- return L"Exec";
- case JET_DOC_DIDPRINT:
- return L"DidPrint";
- case JET_DOC_DIDSAVE:
- return L"DidSave";
- case JET_DOC_OPEN:
- return L"Open";
- case JET_DOC_WILLCLOSE:
- return L"WillClose";
- case JET_DOC_WILLPRINT:
- return L"WillPrint";
- case JET_DOC_WILLSAVE:
- return L"WillSave";
- case JET_EXTERNAL_EXEC:
- return L"Exec";
- case JET_FIELD_FOCUS:
- case JET_SCREEN_FOCUS:
- return L"Focus";
- case JET_FIELD_BLUR:
- case JET_SCREEN_BLUR:
- return L"Blur";
- case JET_FIELD_MOUSEDOWN:
- case JET_SCREEN_MOUSEDOWN:
- return L"Mouse Down";
- case JET_FIELD_MOUSEUP:
- case JET_SCREEN_MOUSEUP:
- return L"Mouse Up";
- case JET_FIELD_MOUSEENTER:
- case JET_SCREEN_MOUSEENTER:
- return L"Mouse Enter";
- case JET_FIELD_MOUSEEXIT:
- case JET_SCREEN_MOUSEEXIT:
- return L"Mouse Exit";
- case JET_FIELD_CALCULATE:
- return L"Calculate";
- case JET_FIELD_FORMAT:
- return L"Format";
- case JET_FIELD_KEYSTROKE:
- return L"Keystroke";
- case JET_FIELD_VALIDATE:
- return L"Validate";
- case JET_LINK_MOUSEUP:
- return L"Mouse Up";
- case JET_MENU_EXEC:
- return L"Exec";
- case JET_PAGE_OPEN:
- case JET_SCREEN_OPEN:
- return L"Open";
- case JET_PAGE_CLOSE:
- case JET_SCREEN_CLOSE:
- return L"Close";
- case JET_SCREEN_INVIEW:
- case JET_PAGE_INVIEW:
- return L"InView";
- case JET_PAGE_OUTVIEW:
- case JET_SCREEN_OUTVIEW:
- return L"OutView";
- default:
- return L"";
- }
-}
-
-const FX_WCHAR* CJS_EventHandler::Type() {
- switch (m_eEventType) {
- case JET_APP_INIT:
- return L"App";
- case JET_BATCH_EXEC:
- return L"Batch";
- case JET_BOOKMARK_MOUSEUP:
- return L"BookMark";
- case JET_CONSOLE_EXEC:
- return L"Console";
- case JET_DOC_DIDPRINT:
- case JET_DOC_DIDSAVE:
- case JET_DOC_OPEN:
- case JET_DOC_WILLCLOSE:
- case JET_DOC_WILLPRINT:
- case JET_DOC_WILLSAVE:
- return L"Doc";
- case JET_EXTERNAL_EXEC:
- return L"External";
- case JET_FIELD_BLUR:
- case JET_FIELD_FOCUS:
- case JET_FIELD_MOUSEDOWN:
- case JET_FIELD_MOUSEENTER:
- case JET_FIELD_MOUSEEXIT:
- case JET_FIELD_MOUSEUP:
- case JET_FIELD_CALCULATE:
- case JET_FIELD_FORMAT:
- case JET_FIELD_KEYSTROKE:
- case JET_FIELD_VALIDATE:
- return L"Field";
- case JET_SCREEN_FOCUS:
- case JET_SCREEN_BLUR:
- case JET_SCREEN_OPEN:
- case JET_SCREEN_CLOSE:
- case JET_SCREEN_MOUSEDOWN:
- case JET_SCREEN_MOUSEUP:
- case JET_SCREEN_MOUSEENTER:
- case JET_SCREEN_MOUSEEXIT:
- case JET_SCREEN_INVIEW:
- case JET_SCREEN_OUTVIEW:
- return L"Screen";
- case JET_LINK_MOUSEUP:
- return L"Link";
- case JET_MENU_EXEC:
- return L"Menu";
- case JET_PAGE_OPEN:
- case JET_PAGE_CLOSE:
- case JET_PAGE_INVIEW:
- case JET_PAGE_OUTVIEW:
- return L"Page";
- default:
- return L"";
- }
-}
-
-bool& CJS_EventHandler::Rc() {
- if (m_pbRc) {
- return *m_pbRc;
- }
- return m_bRcDu;
-}
-
-int& CJS_EventHandler::SelEnd() {
- if (m_pISelEnd) {
- return *m_pISelEnd;
- }
- return m_nSelEndDu;
-}
-
-int& CJS_EventHandler::SelStart() {
- if (m_pISelStart) {
- return *m_pISelStart;
- }
- return m_nSelStartDu;
-}
-
-bool CJS_EventHandler::Shift() {
- return m_bShift;
-}
-
-Field* CJS_EventHandler::Source() {
- CJS_Runtime* pRuntime = m_pJSEventContext->GetJSRuntime();
- v8::Local<v8::Object> pDocObj =
- pRuntime->NewFxDynamicObj(CJS_Document::g_nObjDefnID);
- if (pDocObj.IsEmpty())
- return nullptr;
-
- v8::Local<v8::Object> pFieldObj =
- pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID);
- if (pFieldObj.IsEmpty())
- return nullptr;
-
- CJS_Document* pJSDocument =
- static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pDocObj));
- CJS_Field* pJSField =
- static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj));
-
- Document* pDocument = static_cast<Document*>(pJSDocument->GetEmbedObject());
- pDocument->SetFormFillEnv(m_pTargetFormFillEnv
- ? m_pTargetFormFillEnv.Get()
- : m_pJSEventContext->GetFormFillEnv());
-
- Field* pField = static_cast<Field*>(pJSField->GetEmbedObject());
- pField->AttachField(pDocument, m_strSourceName);
- return pField;
-}
-
-Field* CJS_EventHandler::Target_Field() {
- CJS_Runtime* pRuntime = m_pJSEventContext->GetJSRuntime();
- v8::Local<v8::Object> pDocObj =
- pRuntime->NewFxDynamicObj(CJS_Document::g_nObjDefnID);
- if (pDocObj.IsEmpty())
- return nullptr;
-
- v8::Local<v8::Object> pFieldObj =
- pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID);
- if (pFieldObj.IsEmpty())
- return nullptr;
-
- CJS_Document* pJSDocument =
- static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pDocObj));
- CJS_Field* pJSField =
- static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj));
-
- Document* pDocument = static_cast<Document*>(pJSDocument->GetEmbedObject());
- pDocument->SetFormFillEnv(m_pTargetFormFillEnv
- ? m_pTargetFormFillEnv.Get()
- : m_pJSEventContext->GetFormFillEnv());
-
- Field* pField = static_cast<Field*>(pJSField->GetEmbedObject());
- pField->AttachField(pDocument, m_strTargetName);
- return pField;
-}
-
-CFX_WideString& CJS_EventHandler::Value() {
- return *m_pValue;
-}
-
-bool CJS_EventHandler::WillCommit() {
- return m_bWillCommit;
-}
-
-CFX_WideString CJS_EventHandler::TargetName() {
- return m_strTargetName;
-}
diff --git a/fpdfsdk/javascript/JS_EventHandler.h b/fpdfsdk/javascript/JS_EventHandler.h
deleted file mode 100644
index b9836b0..0000000
--- a/fpdfsdk/javascript/JS_EventHandler.h
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_JS_EVENTHANDLER_H_
-#define FPDFSDK_JAVASCRIPT_JS_EVENTHANDLER_H_
-
-#include "core/fxcrt/fx_string.h"
-#include "core/fxcrt/fx_system.h"
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-
-class CJS_EventContext;
-class CPDFSDK_Annot;
-class CPDF_Bookmark;
-class CPDF_FormField;
-class Field;
-
-enum JS_EVENT_T {
- JET_UNKNOWN,
- JET_APP_INIT,
- JET_DOC_OPEN,
- JET_DOC_WILLPRINT,
- JET_DOC_DIDPRINT,
- JET_DOC_WILLSAVE,
- JET_DOC_DIDSAVE,
- JET_DOC_WILLCLOSE,
- JET_PAGE_OPEN,
- JET_PAGE_CLOSE,
- JET_PAGE_INVIEW,
- JET_PAGE_OUTVIEW,
- JET_FIELD_MOUSEDOWN,
- JET_FIELD_MOUSEUP,
- JET_FIELD_MOUSEENTER,
- JET_FIELD_MOUSEEXIT,
- JET_FIELD_FOCUS,
- JET_FIELD_BLUR,
- JET_FIELD_KEYSTROKE,
- JET_FIELD_VALIDATE,
- JET_FIELD_CALCULATE,
- JET_FIELD_FORMAT,
- JET_SCREEN_FOCUS,
- JET_SCREEN_BLUR,
- JET_SCREEN_OPEN,
- JET_SCREEN_CLOSE,
- JET_SCREEN_MOUSEDOWN,
- JET_SCREEN_MOUSEUP,
- JET_SCREEN_MOUSEENTER,
- JET_SCREEN_MOUSEEXIT,
- JET_SCREEN_INVIEW,
- JET_SCREEN_OUTVIEW,
- JET_BATCH_EXEC,
- JET_MENU_EXEC,
- JET_CONSOLE_EXEC,
- JET_EXTERNAL_EXEC,
- JET_BOOKMARK_MOUSEUP,
- JET_LINK_MOUSEUP
-};
-
-class CJS_EventHandler {
- public:
- explicit CJS_EventHandler(CJS_EventContext* pContext);
- virtual ~CJS_EventHandler();
-
- void OnApp_Init();
-
- void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName);
- void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void OnDoc_DidSave(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void OnDoc_WillClose(CPDFSDK_FormFillEnvironment* pFormFillEnv);
-
- void OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void OnPage_InView(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void OnPage_OutView(CPDFSDK_FormFillEnvironment* pFormFillEnv);
-
- void OnField_Calculate(CPDF_FormField* pSource,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc);
- void OnField_Format(CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit);
- void OnField_Keystroke(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool KeyDown,
- bool bModifier,
- int& nSelEnd,
- int& nSelStart,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit,
- bool bFieldFull,
- bool& bRc);
- void OnField_Validate(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool bKeyDown,
- bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc);
-
- void OnField_MouseDown(bool bModifier, bool bShift, CPDF_FormField* pTarget);
- void OnField_MouseEnter(bool bModifier, bool bShift, CPDF_FormField* pTarget);
- void OnField_MouseExit(bool bModifier, bool bShift, CPDF_FormField* pTarget);
- void OnField_MouseUp(bool bModifier, bool bShift, CPDF_FormField* pTarget);
- void OnField_Blur(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value);
- void OnField_Focus(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value);
-
- void OnScreen_Focus(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_Blur(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_Open(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_Close(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_MouseDown(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_MouseUp(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_MouseEnter(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_MouseExit(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_InView(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
- void OnScreen_OutView(bool bModifier, bool bShift, CPDFSDK_Annot* pScreen);
-
- void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark);
- void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv);
-
- void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName);
- void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- void OnConsole_Exec();
- void OnExternal_Exec();
-
- public:
- void Initial(JS_EVENT_T type);
- void Destroy();
- bool IsValid();
-
- CFX_WideString& Change();
- CFX_WideString ChangeEx();
- int CommitKey();
- bool FieldFull();
- bool KeyDown();
- bool Modifier();
- const FX_WCHAR* Name();
- const FX_WCHAR* Type();
- bool& Rc();
- int& SelEnd();
- int& SelStart();
- bool Shift();
- Field* Source();
- Field* Target_Field();
- CFX_WideString& Value();
- bool WillCommit();
- CFX_WideString TargetName();
-
- JS_EVENT_T EventType() { return m_eEventType; }
-
- public:
- CJS_EventContext* const m_pJSEventContext; // Not Owned.
- JS_EVENT_T m_eEventType;
- bool m_bValid;
-
- CFX_WideString m_strTargetName;
- CFX_WideString m_strSourceName;
- CFX_WideString* m_pWideStrChange;
- CFX_WideString m_WideStrChangeDu;
- CFX_WideString m_WideStrChangeEx;
- int m_nCommitKey;
- bool m_bKeyDown;
- bool m_bModifier;
- bool m_bShift;
- int* m_pISelEnd;
- int m_nSelEndDu;
- int* m_pISelStart;
- int m_nSelStartDu;
- bool m_bWillCommit;
- CFX_WideString* m_pValue;
- bool m_bFieldFull;
- bool* m_pbRc;
- bool m_bRcDu;
-
- CPDF_Bookmark* m_pTargetBookMark;
- CPDFSDK_FormFillEnvironment::ObservedPtr m_pTargetFormFillEnv;
- CPDFSDK_Annot::ObservedPtr m_pTargetAnnot;
-};
-
-#endif // FPDFSDK_JAVASCRIPT_JS_EVENTHANDLER_H_
diff --git a/fpdfsdk/javascript/JS_GlobalData.cpp b/fpdfsdk/javascript/JS_GlobalData.cpp
deleted file mode 100644
index 68d929f..0000000
--- a/fpdfsdk/javascript/JS_GlobalData.cpp
+++ /dev/null
@@ -1,396 +0,0 @@
-// Copyright 2014 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/javascript/JS_GlobalData.h"
-
-#include <utility>
-
-#include "core/fdrm/crypto/fx_crypt.h"
-#include "third_party/base/stl_util.h"
-
-#define JS_MAXGLOBALDATA (1024 * 4 - 8)
-
-#define READER_JS_GLOBALDATA_FILENAME L"Reader_JsGlobal.Data"
-#define PHANTOM_JS_GLOBALDATA_FILENAME L"Phantom_JsGlobal.Data"
-#define SDK_JS_GLOBALDATA_FILENAME L"SDK_JsGlobal.Data"
-
-namespace {
-
-const uint8_t JS_RC4KEY[] = {
- 0x19, 0xa8, 0xe8, 0x01, 0xf6, 0xa8, 0xb6, 0x4d, 0x82, 0x04, 0x45, 0x6d,
- 0xb4, 0xcf, 0xd7, 0x77, 0x67, 0xf9, 0x75, 0x9f, 0xf0, 0xe0, 0x1e, 0x51,
- 0xee, 0x46, 0xfd, 0x0b, 0xc9, 0x93, 0x25, 0x55, 0x4a, 0xee, 0xe0, 0x16,
- 0xd0, 0xdf, 0x8c, 0xfa, 0x2a, 0xa9, 0x49, 0xfd, 0x97, 0x1c, 0x0e, 0x22,
- 0x13, 0x28, 0x7c, 0xaf, 0xc4, 0xfc, 0x9c, 0x12, 0x65, 0x8c, 0x4e, 0x5b,
- 0x04, 0x75, 0x89, 0xc9, 0xb1, 0xed, 0x50, 0xca, 0x96, 0x6f, 0x1a, 0x7a,
- 0xfe, 0x58, 0x5d, 0xec, 0x19, 0x4a, 0xf6, 0x35, 0x6a, 0x97, 0x14, 0x00,
- 0x0e, 0xd0, 0x6b, 0xbb, 0xd5, 0x75, 0x55, 0x8b, 0x6e, 0x6b, 0x19, 0xa0,
- 0xf8, 0x77, 0xd5, 0xa3};
-
-// Returns true if non-empty, setting sPropName
-bool TrimPropName(CFX_ByteString* sPropName) {
- sPropName->TrimLeft();
- sPropName->TrimRight();
- return sPropName->GetLength() != 0;
-}
-
-CJS_GlobalData* g_pInstance = nullptr;
-
-} // namespace
-
-// static
-CJS_GlobalData* CJS_GlobalData::GetRetainedInstance(
- CPDFSDK_FormFillEnvironment* pApp) {
- if (!g_pInstance) {
- g_pInstance = new CJS_GlobalData();
- }
- ++g_pInstance->m_RefCount;
- return g_pInstance;
-}
-
-void CJS_GlobalData::Release() {
- if (!--m_RefCount) {
- delete g_pInstance;
- g_pInstance = nullptr;
- }
-}
-
-CJS_GlobalData::CJS_GlobalData()
- : m_RefCount(0), m_sFilePath(SDK_JS_GLOBALDATA_FILENAME) {
- LoadGlobalPersistentVariables();
-}
-
-CJS_GlobalData::~CJS_GlobalData() {
- SaveGlobalPersisitentVariables();
-}
-
-CJS_GlobalData::iterator CJS_GlobalData::FindGlobalVariable(
- const CFX_ByteString& propname) {
- for (auto it = m_arrayGlobalData.begin(); it != m_arrayGlobalData.end();
- ++it) {
- if ((*it)->data.sKey == propname)
- return it;
- }
- return m_arrayGlobalData.end();
-}
-
-CJS_GlobalData::const_iterator CJS_GlobalData::FindGlobalVariable(
- const CFX_ByteString& propname) const {
- for (auto it = m_arrayGlobalData.begin(); it != m_arrayGlobalData.end();
- ++it) {
- if ((*it)->data.sKey == propname)
- return it;
- }
- return m_arrayGlobalData.end();
-}
-
-CJS_GlobalData_Element* CJS_GlobalData::GetGlobalVariable(
- const CFX_ByteString& propname) {
- auto iter = FindGlobalVariable(propname);
- return iter != m_arrayGlobalData.end() ? iter->get() : nullptr;
-}
-
-void CJS_GlobalData::SetGlobalVariableNumber(const CFX_ByteString& propname,
- double dData) {
- CFX_ByteString sPropName(propname);
- if (!TrimPropName(&sPropName))
- return;
-
- if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) {
- pData->data.nType = JS_GlobalDataType::NUMBER;
- pData->data.dData = dData;
- return;
- }
- std::unique_ptr<CJS_GlobalData_Element> pNewData(new CJS_GlobalData_Element);
- pNewData->data.sKey = sPropName;
- pNewData->data.nType = JS_GlobalDataType::NUMBER;
- pNewData->data.dData = dData;
- m_arrayGlobalData.push_back(std::move(pNewData));
-}
-
-void CJS_GlobalData::SetGlobalVariableBoolean(const CFX_ByteString& propname,
- bool bData) {
- CFX_ByteString sPropName(propname);
- if (!TrimPropName(&sPropName))
- return;
-
- if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) {
- pData->data.nType = JS_GlobalDataType::BOOLEAN;
- pData->data.bData = bData;
- return;
- }
- std::unique_ptr<CJS_GlobalData_Element> pNewData(new CJS_GlobalData_Element);
- pNewData->data.sKey = sPropName;
- pNewData->data.nType = JS_GlobalDataType::BOOLEAN;
- pNewData->data.bData = bData;
- m_arrayGlobalData.push_back(std::move(pNewData));
-}
-
-void CJS_GlobalData::SetGlobalVariableString(const CFX_ByteString& propname,
- const CFX_ByteString& sData) {
- CFX_ByteString sPropName(propname);
- if (!TrimPropName(&sPropName))
- return;
-
- if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) {
- pData->data.nType = JS_GlobalDataType::STRING;
- pData->data.sData = sData;
- return;
- }
- std::unique_ptr<CJS_GlobalData_Element> pNewData(new CJS_GlobalData_Element);
- pNewData->data.sKey = sPropName;
- pNewData->data.nType = JS_GlobalDataType::STRING;
- pNewData->data.sData = sData;
- m_arrayGlobalData.push_back(std::move(pNewData));
-}
-
-void CJS_GlobalData::SetGlobalVariableObject(
- const CFX_ByteString& propname,
- const CJS_GlobalVariableArray& array) {
- CFX_ByteString sPropName(propname);
- if (!TrimPropName(&sPropName))
- return;
-
- if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) {
- pData->data.nType = JS_GlobalDataType::OBJECT;
- pData->data.objData.Copy(array);
- return;
- }
- std::unique_ptr<CJS_GlobalData_Element> pNewData(new CJS_GlobalData_Element);
- pNewData->data.sKey = sPropName;
- pNewData->data.nType = JS_GlobalDataType::OBJECT;
- pNewData->data.objData.Copy(array);
- m_arrayGlobalData.push_back(std::move(pNewData));
-}
-
-void CJS_GlobalData::SetGlobalVariableNull(const CFX_ByteString& propname) {
- CFX_ByteString sPropName(propname);
- if (!TrimPropName(&sPropName))
- return;
-
- if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName)) {
- pData->data.nType = JS_GlobalDataType::NULLOBJ;
- return;
- }
- std::unique_ptr<CJS_GlobalData_Element> pNewData(new CJS_GlobalData_Element);
- pNewData->data.sKey = sPropName;
- pNewData->data.nType = JS_GlobalDataType::NULLOBJ;
- m_arrayGlobalData.push_back(std::move(pNewData));
-}
-
-bool CJS_GlobalData::SetGlobalVariablePersistent(const CFX_ByteString& propname,
- bool bPersistent) {
- CFX_ByteString sPropName(propname);
- if (!TrimPropName(&sPropName))
- return false;
-
- CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName);
- if (!pData)
- return false;
-
- pData->bPersistent = bPersistent;
- return true;
-}
-
-bool CJS_GlobalData::DeleteGlobalVariable(const CFX_ByteString& propname) {
- CFX_ByteString sPropName(propname);
- if (!TrimPropName(&sPropName))
- return false;
-
- auto iter = FindGlobalVariable(sPropName);
- if (iter == m_arrayGlobalData.end())
- return false;
-
- m_arrayGlobalData.erase(iter);
- return true;
-}
-
-int32_t CJS_GlobalData::GetSize() const {
- return pdfium::CollectionSize<int32_t>(m_arrayGlobalData);
-}
-
-CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const {
- if (index < 0 || index >= GetSize())
- return nullptr;
- return m_arrayGlobalData[index].get();
-}
-
-void CJS_GlobalData::LoadGlobalPersistentVariables() {
- uint8_t* pBuffer = nullptr;
- int32_t nLength = 0;
-
- LoadFileBuffer(m_sFilePath.c_str(), pBuffer, nLength);
- CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY));
-
- if (pBuffer) {
- uint8_t* p = pBuffer;
- uint16_t wType = *((uint16_t*)p);
- p += sizeof(uint16_t);
-
- if (wType == (uint16_t)(('X' << 8) | 'F')) {
- uint16_t wVersion = *((uint16_t*)p);
- p += sizeof(uint16_t);
-
- ASSERT(wVersion <= 2);
-
- uint32_t dwCount = *((uint32_t*)p);
- p += sizeof(uint32_t);
-
- uint32_t dwSize = *((uint32_t*)p);
- p += sizeof(uint32_t);
-
- if (dwSize == nLength - sizeof(uint16_t) * 2 - sizeof(uint32_t) * 2) {
- for (int32_t i = 0, sz = dwCount; i < sz; i++) {
- if (p > pBuffer + nLength)
- break;
-
- uint32_t dwNameLen = *((uint32_t*)p);
- p += sizeof(uint32_t);
-
- if (p + dwNameLen > pBuffer + nLength)
- break;
-
- CFX_ByteString sEntry = CFX_ByteString(p, dwNameLen);
- p += sizeof(char) * dwNameLen;
-
- JS_GlobalDataType wDataType =
- static_cast<JS_GlobalDataType>(*((uint16_t*)p));
- p += sizeof(uint16_t);
-
- switch (wDataType) {
- case JS_GlobalDataType::NUMBER: {
- double dData = 0;
- switch (wVersion) {
- case 1: {
- uint32_t dwData = *((uint32_t*)p);
- p += sizeof(uint32_t);
- dData = dwData;
- } break;
- case 2: {
- dData = *((double*)p);
- p += sizeof(double);
- } break;
- }
- SetGlobalVariableNumber(sEntry, dData);
- SetGlobalVariablePersistent(sEntry, true);
- } break;
- case JS_GlobalDataType::BOOLEAN: {
- uint16_t wData = *((uint16_t*)p);
- p += sizeof(uint16_t);
- SetGlobalVariableBoolean(sEntry, (bool)(wData == 1));
- SetGlobalVariablePersistent(sEntry, true);
- } break;
- case JS_GlobalDataType::STRING: {
- uint32_t dwLength = *((uint32_t*)p);
- p += sizeof(uint32_t);
-
- if (p + dwLength > pBuffer + nLength)
- break;
-
- SetGlobalVariableString(sEntry, CFX_ByteString(p, dwLength));
- SetGlobalVariablePersistent(sEntry, true);
- p += sizeof(char) * dwLength;
- } break;
- case JS_GlobalDataType::NULLOBJ: {
- SetGlobalVariableNull(sEntry);
- SetGlobalVariablePersistent(sEntry, true);
- }
- case JS_GlobalDataType::OBJECT:
- break;
- }
- }
- }
- }
- FX_Free(pBuffer);
- }
-}
-
-void CJS_GlobalData::SaveGlobalPersisitentVariables() {
- uint32_t nCount = 0;
- CFX_BinaryBuf sData;
- for (const auto& pElement : m_arrayGlobalData) {
- if (pElement->bPersistent) {
- CFX_BinaryBuf sElement;
- MakeByteString(pElement->data.sKey, &pElement->data, sElement);
- if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALDATA)
- break;
-
- sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize());
- nCount++;
- }
- }
-
- CFX_BinaryBuf sFile;
- uint16_t wType = (uint16_t)(('X' << 8) | 'F');
- sFile.AppendBlock(&wType, sizeof(uint16_t));
- uint16_t wVersion = 2;
- sFile.AppendBlock(&wVersion, sizeof(uint16_t));
- sFile.AppendBlock(&nCount, sizeof(uint32_t));
- uint32_t dwSize = sData.GetSize();
- sFile.AppendBlock(&dwSize, sizeof(uint32_t));
-
- sFile.AppendBlock(sData.GetBuffer(), sData.GetSize());
-
- CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY,
- sizeof(JS_RC4KEY));
- WriteFileBuffer(m_sFilePath.c_str(), (const FX_CHAR*)sFile.GetBuffer(),
- sFile.GetSize());
-}
-
-void CJS_GlobalData::LoadFileBuffer(const FX_WCHAR* sFilePath,
- uint8_t*& pBuffer,
- int32_t& nLength) {
- // UnSupport.
-}
-
-void CJS_GlobalData::WriteFileBuffer(const FX_WCHAR* sFilePath,
- const FX_CHAR* pBuffer,
- int32_t nLength) {
- // UnSupport.
-}
-
-void CJS_GlobalData::MakeByteString(const CFX_ByteString& name,
- CJS_KeyValue* pData,
- CFX_BinaryBuf& sData) {
- switch (pData->nType) {
- case JS_GlobalDataType::NUMBER: {
- uint32_t dwNameLen = (uint32_t)name.GetLength();
- sData.AppendBlock(&dwNameLen, sizeof(uint32_t));
- sData.AppendString(name);
- sData.AppendBlock(&pData->nType, sizeof(uint16_t));
-
- double dData = pData->dData;
- sData.AppendBlock(&dData, sizeof(double));
- } break;
- case JS_GlobalDataType::BOOLEAN: {
- uint32_t dwNameLen = (uint32_t)name.GetLength();
- sData.AppendBlock(&dwNameLen, sizeof(uint32_t));
- sData.AppendString(name);
- sData.AppendBlock(&pData->nType, sizeof(uint16_t));
-
- uint16_t wData = (uint16_t)pData->bData;
- sData.AppendBlock(&wData, sizeof(uint16_t));
- } break;
- case JS_GlobalDataType::STRING: {
- uint32_t dwNameLen = (uint32_t)name.GetLength();
- sData.AppendBlock(&dwNameLen, sizeof(uint32_t));
- sData.AppendString(name);
- sData.AppendBlock(&pData->nType, sizeof(uint16_t));
-
- uint32_t dwDataLen = (uint32_t)pData->sData.GetLength();
- sData.AppendBlock(&dwDataLen, sizeof(uint32_t));
- sData.AppendString(pData->sData);
- } break;
- case JS_GlobalDataType::NULLOBJ: {
- uint32_t dwNameLen = (uint32_t)name.GetLength();
- sData.AppendBlock(&dwNameLen, sizeof(uint32_t));
- sData.AppendString(name);
- sData.AppendBlock(&pData->nType, sizeof(uint32_t));
- } break;
- default:
- break;
- }
-}
diff --git a/fpdfsdk/javascript/JS_GlobalData.h b/fpdfsdk/javascript/JS_GlobalData.h
deleted file mode 100644
index c8947cd..0000000
--- a/fpdfsdk/javascript/JS_GlobalData.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_JS_GLOBALDATA_H_
-#define FPDFSDK_JAVASCRIPT_JS_GLOBALDATA_H_
-
-#include <memory>
-#include <vector>
-
-#include "core/fxcrt/fx_basic.h"
-#include "fpdfsdk/javascript/JS_KeyValue.h"
-
-class CPDFSDK_FormFillEnvironment;
-
-class CJS_GlobalData_Element {
- public:
- CJS_GlobalData_Element() {}
- ~CJS_GlobalData_Element() {}
-
- CJS_KeyValue data;
- bool bPersistent;
-};
-
-class CJS_GlobalData {
- public:
- static CJS_GlobalData* GetRetainedInstance(CPDFSDK_FormFillEnvironment* pApp);
- void Release();
-
- void SetGlobalVariableNumber(const CFX_ByteString& propname, double dData);
- void SetGlobalVariableBoolean(const CFX_ByteString& propname, bool bData);
- void SetGlobalVariableString(const CFX_ByteString& propname,
- const CFX_ByteString& sData);
- void SetGlobalVariableObject(const CFX_ByteString& propname,
- const CJS_GlobalVariableArray& array);
- void SetGlobalVariableNull(const CFX_ByteString& propname);
- bool SetGlobalVariablePersistent(const CFX_ByteString& propname,
- bool bPersistent);
- bool DeleteGlobalVariable(const CFX_ByteString& propname);
-
- int32_t GetSize() const;
- CJS_GlobalData_Element* GetAt(int index) const;
-
- private:
- using iterator =
- std::vector<std::unique_ptr<CJS_GlobalData_Element>>::iterator;
- using const_iterator =
- std::vector<std::unique_ptr<CJS_GlobalData_Element>>::const_iterator;
-
- CJS_GlobalData();
- ~CJS_GlobalData();
-
- void LoadGlobalPersistentVariables();
- void SaveGlobalPersisitentVariables();
-
- CJS_GlobalData_Element* GetGlobalVariable(const CFX_ByteString& sPropname);
- iterator FindGlobalVariable(const CFX_ByteString& sPropname);
- const_iterator FindGlobalVariable(const CFX_ByteString& sPropname) const;
-
- void LoadFileBuffer(const FX_WCHAR* sFilePath,
- uint8_t*& pBuffer,
- int32_t& nLength);
- void WriteFileBuffer(const FX_WCHAR* sFilePath,
- const FX_CHAR* pBuffer,
- int32_t nLength);
- void MakeByteString(const CFX_ByteString& name,
- CJS_KeyValue* pData,
- CFX_BinaryBuf& sData);
-
- size_t m_RefCount;
- std::vector<std::unique_ptr<CJS_GlobalData_Element>> m_arrayGlobalData;
- CFX_WideString m_sFilePath;
-};
-
-#endif // FPDFSDK_JAVASCRIPT_JS_GLOBALDATA_H_
diff --git a/fpdfsdk/javascript/JS_KeyValue.cpp b/fpdfsdk/javascript/JS_KeyValue.cpp
deleted file mode 100644
index 7d1e575..0000000
--- a/fpdfsdk/javascript/JS_KeyValue.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 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/javascript/JS_KeyValue.h"
-
-CJS_GlobalVariableArray::CJS_GlobalVariableArray() {}
-
-CJS_GlobalVariableArray::~CJS_GlobalVariableArray() {}
-
-void CJS_GlobalVariableArray::Copy(const CJS_GlobalVariableArray& array) {
- m_Array.clear();
- for (int i = 0, sz = array.Count(); i < sz; i++) {
- CJS_KeyValue* pOldObjData = array.GetAt(i);
- switch (pOldObjData->nType) {
- case JS_GlobalDataType::NUMBER: {
- CJS_KeyValue* pNewObjData = new CJS_KeyValue;
- pNewObjData->sKey = pOldObjData->sKey;
- pNewObjData->nType = pOldObjData->nType;
- pNewObjData->dData = pOldObjData->dData;
- Add(pNewObjData);
- } break;
- case JS_GlobalDataType::BOOLEAN: {
- CJS_KeyValue* pNewObjData = new CJS_KeyValue;
- pNewObjData->sKey = pOldObjData->sKey;
- pNewObjData->nType = pOldObjData->nType;
- pNewObjData->bData = pOldObjData->bData;
- Add(pNewObjData);
- } break;
- case JS_GlobalDataType::STRING: {
- CJS_KeyValue* pNewObjData = new CJS_KeyValue;
- pNewObjData->sKey = pOldObjData->sKey;
- pNewObjData->nType = pOldObjData->nType;
- pNewObjData->sData = pOldObjData->sData;
- Add(pNewObjData);
- } break;
- case JS_GlobalDataType::OBJECT: {
- CJS_KeyValue* pNewObjData = new CJS_KeyValue;
- pNewObjData->sKey = pOldObjData->sKey;
- pNewObjData->nType = pOldObjData->nType;
- pNewObjData->objData.Copy(pOldObjData->objData);
- Add(pNewObjData);
- } break;
- case JS_GlobalDataType::NULLOBJ: {
- CJS_KeyValue* pNewObjData = new CJS_KeyValue;
- pNewObjData->sKey = pOldObjData->sKey;
- pNewObjData->nType = pOldObjData->nType;
- Add(pNewObjData);
- } break;
- }
- }
-}
-
-void CJS_GlobalVariableArray::Add(CJS_KeyValue* p) {
- m_Array.push_back(std::unique_ptr<CJS_KeyValue>(p));
-}
-
-int CJS_GlobalVariableArray::Count() const {
- return m_Array.size();
-}
-
-CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const {
- return m_Array.at(index).get();
-}
-
-CJS_KeyValue::CJS_KeyValue() {}
-
-CJS_KeyValue::~CJS_KeyValue() {}
diff --git a/fpdfsdk/javascript/JS_KeyValue.h b/fpdfsdk/javascript/JS_KeyValue.h
deleted file mode 100644
index a571588..0000000
--- a/fpdfsdk/javascript/JS_KeyValue.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2016 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_JAVASCRIPT_JS_KEYVALUE_H_
-#define FPDFSDK_JAVASCRIPT_JS_KEYVALUE_H_
-
-#include <memory>
-#include <vector>
-
-#include "core/fxcrt/fx_basic.h"
-
-enum class JS_GlobalDataType { NUMBER = 0, BOOLEAN, STRING, OBJECT, NULLOBJ };
-
-class CJS_KeyValue;
-
-class CJS_GlobalVariableArray {
- public:
- CJS_GlobalVariableArray();
- ~CJS_GlobalVariableArray();
-
- void Add(CJS_KeyValue* p);
- int Count() const;
- CJS_KeyValue* GetAt(int index) const;
- void Copy(const CJS_GlobalVariableArray& array);
-
- private:
- std::vector<std::unique_ptr<CJS_KeyValue>> m_Array;
-};
-
-class CJS_KeyValue {
- public:
- CJS_KeyValue();
- ~CJS_KeyValue();
-
- CFX_ByteString sKey;
- JS_GlobalDataType nType;
- double dData;
- bool bData;
- CFX_ByteString sData;
- CJS_GlobalVariableArray objData;
-};
-
-#endif // FPDFSDK_JAVASCRIPT_JS_KEYVALUE_H_
diff --git a/fpdfsdk/javascript/JS_Object.cpp b/fpdfsdk/javascript/JS_Object.cpp
deleted file mode 100644
index cd86889..0000000
--- a/fpdfsdk/javascript/JS_Object.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 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/javascript/JS_Object.h"
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-
-CJS_EmbedObj::CJS_EmbedObj(CJS_Object* pJSObject) : m_pJSObject(pJSObject) {}
-
-CJS_EmbedObj::~CJS_EmbedObj() {
-}
-
-void FreeObject(const v8::WeakCallbackInfo<CJS_Object>& data) {
- CJS_Object* pJSObj = data.GetParameter();
- delete pJSObj;
- CFXJS_Engine::FreeObjectPrivate(data.GetInternalField(0));
-}
-
-void DisposeObject(const v8::WeakCallbackInfo<CJS_Object>& data) {
- CJS_Object* pJSObj = data.GetParameter();
- pJSObj->Dispose();
- data.SetSecondPassCallback(FreeObject);
-}
-
-CJS_Object::CJS_Object(v8::Local<v8::Object> pObject) {
- m_pIsolate = pObject->GetIsolate();
- m_pV8Object.Reset(m_pIsolate, pObject);
-}
-
-CJS_Object::~CJS_Object() {}
-
-void CJS_Object::MakeWeak() {
- m_pV8Object.SetWeak(this, DisposeObject,
- v8::WeakCallbackType::kInternalFields);
-}
-
-void CJS_Object::Dispose() {
- m_pV8Object.Reset();
-}
-
-void CJS_Object::InitInstance(IJS_Runtime* pIRuntime) {}
diff --git a/fpdfsdk/javascript/JS_Object.h b/fpdfsdk/javascript/JS_Object.h
deleted file mode 100644
index 2e5c75c..0000000
--- a/fpdfsdk/javascript/JS_Object.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_JS_OBJECT_H_
-#define FPDFSDK_JAVASCRIPT_JS_OBJECT_H_
-
-#include <map>
-#include <memory>
-
-#include "fpdfsdk/fsdk_define.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fxjs/fxjs_v8.h"
-
-class CJS_EventContext;
-class CJS_Object;
-class CPDFSDK_FormFillEnvironment;
-
-class CJS_EmbedObj {
- public:
- explicit CJS_EmbedObj(CJS_Object* pJSObject);
- virtual ~CJS_EmbedObj();
-
- CJS_Object* GetJSObject() const { return m_pJSObject; }
-
- protected:
- CJS_Object* const m_pJSObject;
-};
-
-class CJS_Object {
- public:
- explicit CJS_Object(v8::Local<v8::Object> pObject);
- virtual ~CJS_Object();
-
- void MakeWeak();
- void Dispose();
-
- virtual void InitInstance(IJS_Runtime* pIRuntime);
-
- v8::Local<v8::Object> ToV8Object() { return m_pV8Object.Get(m_pIsolate); }
-
- // Takes ownership of |pObj|.
- void SetEmbedObject(CJS_EmbedObj* pObj) { m_pEmbedObj.reset(pObj); }
- CJS_EmbedObj* GetEmbedObject() const { return m_pEmbedObj.get(); }
-
- v8::Isolate* GetIsolate() const { return m_pIsolate; }
-
- protected:
- std::unique_ptr<CJS_EmbedObj> m_pEmbedObj;
- v8::Global<v8::Object> m_pV8Object;
- v8::Isolate* m_pIsolate;
-};
-
-
-#endif // FPDFSDK_JAVASCRIPT_JS_OBJECT_H_
diff --git a/fpdfsdk/javascript/JS_Runtime_Stub.cpp b/fpdfsdk/javascript/JS_Runtime_Stub.cpp
deleted file mode 100644
index dcd8ceb..0000000
--- a/fpdfsdk/javascript/JS_Runtime_Stub.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2015 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 <memory>
-
-#include "fpdfsdk/javascript/ijs_event_context.h"
-#include "fpdfsdk/javascript/ijs_runtime.h"
-#include "third_party/base/ptr_util.h"
-
-class CJS_EventContextStub final : public IJS_EventContext {
- public:
- CJS_EventContextStub() {}
- ~CJS_EventContextStub() override {}
-
- // IJS_EventContext:
- bool RunScript(const CFX_WideString& script, CFX_WideString* info) override {
- return false;
- }
-
- void OnApp_Init() override {}
- void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName) override {}
- void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnDoc_DidSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnDoc_WillClose(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnPage_InView(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnPage_OutView(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnField_MouseDown(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) override {}
- void OnField_MouseEnter(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) override {}
- void OnField_MouseExit(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) override {}
- void OnField_MouseUp(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) override {}
- void OnField_Focus(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) override {}
- void OnField_Blur(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) override {}
- void OnField_Calculate(CPDF_FormField* pSource,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) override {}
- void OnField_Format(CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit) override {}
- void OnField_Keystroke(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool KeyDown,
- bool bModifier,
- int& nSelEnd,
- int& nSelStart,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit,
- bool bFieldFull,
- bool& bRc) override {}
- void OnField_Validate(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool bKeyDown,
- bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) override {}
- void OnScreen_Focus(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_Blur(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_Open(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_Close(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_MouseDown(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_MouseUp(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_MouseEnter(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_MouseExit(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_InView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnScreen_OutView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override {}
- void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) override {}
- void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString&) override {}
- void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) override {}
- void OnConsole_Exec() override {}
- void OnExternal_Exec() override {}
-};
-
-class CJS_RuntimeStub final : public IJS_Runtime {
- public:
- explicit CJS_RuntimeStub(CPDFSDK_FormFillEnvironment* pFormFillEnv)
- : m_pFormFillEnv(pFormFillEnv) {}
- ~CJS_RuntimeStub() override {}
-
- IJS_EventContext* NewEventContext() override {
- if (!m_pContext)
- m_pContext = pdfium::MakeUnique<CJS_EventContextStub>();
- return m_pContext.get();
- }
-
- void ReleaseEventContext(IJS_EventContext* pContext) override {}
-
- CPDFSDK_FormFillEnvironment* GetFormFillEnv() const override {
- return m_pFormFillEnv;
- }
-
-#ifdef PDF_ENABLE_XFA
- bool GetValueByName(const CFX_ByteStringC&, CFXJSE_Value*) override {
- return false;
- }
-
- bool SetValueByName(const CFX_ByteStringC&, CFXJSE_Value*) override {
- return false;
- }
-#endif // PDF_ENABLE_XFA
-
- int ExecuteScript(const CFX_WideString& script,
- CFX_WideString* info) override {
- return 0;
- }
-
- protected:
- CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
- std::unique_ptr<CJS_EventContextStub> m_pContext;
-};
-
-// static
-void IJS_Runtime::Initialize(unsigned int slot, void* isolate) {}
-
-// static
-void IJS_Runtime::Destroy() {}
-
-// static
-IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- return new CJS_RuntimeStub(pFormFillEnv);
-}
diff --git a/fpdfsdk/javascript/JS_Value.cpp b/fpdfsdk/javascript/JS_Value.cpp
deleted file mode 100644
index b058847..0000000
--- a/fpdfsdk/javascript/JS_Value.cpp
+++ /dev/null
@@ -1,770 +0,0 @@
-// Copyright 2014 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/javascript/JS_Value.h"
-
-#include <time.h>
-
-#include <algorithm>
-#include <cmath>
-#include <limits>
-#include <vector>
-
-#include "fpdfsdk/javascript/Document.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-
-namespace {
-
-const uint32_t g_nan[2] = {0, 0x7FF80000};
-
-double GetNan() {
- return *(double*)g_nan;
-}
-
-double
-MakeDate(int year, int mon, int day, int hour, int min, int sec, int ms) {
- return JS_MakeDate(JS_MakeDay(year, mon, day),
- JS_MakeTime(hour, min, sec, ms));
-}
-
-} // namespace
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, v8::Local<v8::Value> pValue)
- : m_pValue(pValue) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const int& iValue)
- : m_pValue(pRuntime->NewNumber(iValue)) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const bool& bValue)
- : m_pValue(pRuntime->NewBoolean(bValue)) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const float& fValue)
- : m_pValue(pRuntime->NewNumber(fValue)) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const double& dValue)
- : m_pValue(pRuntime->NewNumber(dValue)) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, CJS_Object* pObj) {
- if (pObj)
- m_pValue = pObj->ToV8Object();
-}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_WCHAR* pWstr)
- : m_pValue(pRuntime->NewString(pWstr)) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_CHAR* pStr)
- : m_pValue(pRuntime->NewString(CFX_WideString::FromLocal(pStr).c_str())) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const CJS_Array& array)
- : m_pValue(array.ToV8Array(pRuntime)) {}
-
-CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const CJS_Date& date)
- : m_pValue(date.ToV8Date(pRuntime)) {}
-
-CJS_Value::~CJS_Value() {}
-
-CJS_Value::CJS_Value(const CJS_Value& other) = default;
-
-void CJS_Value::Attach(v8::Local<v8::Value> pValue) {
- m_pValue = pValue;
-}
-
-void CJS_Value::Detach() {
- m_pValue = v8::Local<v8::Value>();
-}
-
-int CJS_Value::ToInt(CJS_Runtime* pRuntime) const {
- return pRuntime->ToInt32(m_pValue);
-}
-
-bool CJS_Value::ToBool(CJS_Runtime* pRuntime) const {
- return pRuntime->ToBoolean(m_pValue);
-}
-
-double CJS_Value::ToDouble(CJS_Runtime* pRuntime) const {
- return pRuntime->ToDouble(m_pValue);
-}
-
-float CJS_Value::ToFloat(CJS_Runtime* pRuntime) const {
- return (float)ToDouble(pRuntime);
-}
-
-CJS_Object* CJS_Value::ToCJSObject(CJS_Runtime* pRuntime) const {
- v8::Local<v8::Object> pObj = pRuntime->ToObject(m_pValue);
- return static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(pObj));
-}
-
-v8::Local<v8::Object> CJS_Value::ToV8Object(CJS_Runtime* pRuntime) const {
- return pRuntime->ToObject(m_pValue);
-}
-
-CFX_WideString CJS_Value::ToCFXWideString(CJS_Runtime* pRuntime) const {
- return pRuntime->ToWideString(m_pValue);
-}
-
-CFX_ByteString CJS_Value::ToCFXByteString(CJS_Runtime* pRuntime) const {
- return CFX_ByteString::FromUnicode(ToCFXWideString(pRuntime));
-}
-
-v8::Local<v8::Value> CJS_Value::ToV8Value(CJS_Runtime* pRuntime) const {
- return m_pValue;
-}
-
-v8::Local<v8::Array> CJS_Value::ToV8Array(CJS_Runtime* pRuntime) const {
- return pRuntime->ToArray(m_pValue);
-}
-
-void CJS_Value::SetNull(CJS_Runtime* pRuntime) {
- m_pValue = pRuntime->NewNull();
-}
-
-void CJS_Value::MaybeCoerceToNumber(CJS_Runtime* pRuntime) {
- bool bAllowNaN = false;
- if (GetType() == VT_string) {
- CFX_ByteString bstr = ToCFXByteString(pRuntime);
- if (bstr.GetLength() == 0)
- return;
- if (bstr == "NaN")
- bAllowNaN = true;
- }
- v8::Isolate* pIsolate = pRuntime->GetIsolate();
- v8::TryCatch try_catch(pIsolate);
- v8::MaybeLocal<v8::Number> maybeNum =
- m_pValue->ToNumber(pIsolate->GetCurrentContext());
- if (maybeNum.IsEmpty())
- return;
- v8::Local<v8::Number> num = maybeNum.ToLocalChecked();
- if (std::isnan(num->Value()) && !bAllowNaN)
- return;
- m_pValue = num;
-}
-
-// static
-CJS_Value::Type CJS_Value::GetValueType(v8::Local<v8::Value> value) {
- if (value.IsEmpty())
- return VT_unknown;
- if (value->IsString())
- return VT_string;
- if (value->IsNumber())
- return VT_number;
- if (value->IsBoolean())
- return VT_boolean;
- if (value->IsDate())
- return VT_date;
- if (value->IsObject())
- return VT_object;
- if (value->IsNull())
- return VT_null;
- if (value->IsUndefined())
- return VT_undefined;
- return VT_unknown;
-}
-
-bool CJS_Value::IsArrayObject() const {
- return !m_pValue.IsEmpty() && m_pValue->IsArray();
-}
-
-bool CJS_Value::IsDateObject() const {
- return !m_pValue.IsEmpty() && m_pValue->IsDate();
-}
-
-bool CJS_Value::ConvertToArray(CJS_Runtime* pRuntime, CJS_Array& array) const {
- if (!IsArrayObject())
- return false;
- array.Attach(pRuntime->ToArray(m_pValue));
- return true;
-}
-
-bool CJS_Value::ConvertToDate(CJS_Runtime* pRuntime, CJS_Date& date) const {
- if (!IsDateObject())
- return false;
- v8::Local<v8::Value> mutable_value = m_pValue;
- date.Attach(mutable_value.As<v8::Date>());
- return true;
-}
-
-CJS_PropValue::CJS_PropValue(CJS_Runtime* pRuntime)
- : m_bIsSetting(0), m_Value(pRuntime), m_pJSRuntime(pRuntime) {}
-
-CJS_PropValue::CJS_PropValue(CJS_Runtime* pRuntime, const CJS_Value& value)
- : m_bIsSetting(0), m_Value(value), m_pJSRuntime(pRuntime) {}
-
-CJS_PropValue::~CJS_PropValue() {}
-
-void CJS_PropValue::operator<<(int iValue) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, iValue);
-}
-
-void CJS_PropValue::operator>>(int& iValue) const {
- ASSERT(m_bIsSetting);
- iValue = m_Value.ToInt(m_pJSRuntime);
-}
-
-void CJS_PropValue::operator<<(bool bValue) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, bValue);
-}
-
-void CJS_PropValue::operator>>(bool& bValue) const {
- ASSERT(m_bIsSetting);
- bValue = m_Value.ToBool(m_pJSRuntime);
-}
-
-void CJS_PropValue::operator<<(double dValue) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, dValue);
-}
-
-void CJS_PropValue::operator>>(double& dValue) const {
- ASSERT(m_bIsSetting);
- dValue = m_Value.ToDouble(m_pJSRuntime);
-}
-
-void CJS_PropValue::operator<<(CJS_Object* pObj) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, pObj);
-}
-
-void CJS_PropValue::operator>>(CJS_Object*& ppObj) const {
- ASSERT(m_bIsSetting);
- ppObj = m_Value.ToCJSObject(m_pJSRuntime);
-}
-
-void CJS_PropValue::operator<<(CJS_Document* pJsDoc) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, pJsDoc);
-}
-
-void CJS_PropValue::operator>>(CJS_Document*& ppJsDoc) const {
- ASSERT(m_bIsSetting);
- ppJsDoc = static_cast<CJS_Document*>(m_Value.ToCJSObject(m_pJSRuntime));
-}
-
-void CJS_PropValue::operator<<(v8::Local<v8::Object> pObj) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, pObj);
-}
-
-void CJS_PropValue::operator>>(v8::Local<v8::Object>& ppObj) const {
- ASSERT(m_bIsSetting);
- ppObj = m_Value.ToV8Object(m_pJSRuntime);
-}
-
-void CJS_PropValue::operator<<(CFX_ByteString str) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, str.c_str());
-}
-
-void CJS_PropValue::operator>>(CFX_ByteString& str) const {
- ASSERT(m_bIsSetting);
- str = m_Value.ToCFXByteString(m_pJSRuntime);
-}
-
-void CJS_PropValue::operator<<(const FX_WCHAR* str) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, str);
-}
-
-void CJS_PropValue::operator>>(CFX_WideString& wide_string) const {
- ASSERT(m_bIsSetting);
- wide_string = m_Value.ToCFXWideString(m_pJSRuntime);
-}
-
-void CJS_PropValue::operator<<(CFX_WideString wide_string) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, wide_string.c_str());
-}
-
-void CJS_PropValue::operator>>(CJS_Array& array) const {
- ASSERT(m_bIsSetting);
- m_Value.ConvertToArray(m_pJSRuntime, array);
-}
-
-void CJS_PropValue::operator<<(CJS_Array& array) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, array.ToV8Array(m_pJSRuntime));
-}
-
-void CJS_PropValue::operator>>(CJS_Date& date) const {
- ASSERT(m_bIsSetting);
- m_Value.ConvertToDate(m_pJSRuntime, date);
-}
-
-void CJS_PropValue::operator<<(CJS_Date& date) {
- ASSERT(!m_bIsSetting);
- m_Value = CJS_Value(m_pJSRuntime, date);
-}
-
-CJS_Array::CJS_Array() {}
-
-CJS_Array::CJS_Array(const CJS_Array& other) = default;
-
-CJS_Array::~CJS_Array() {}
-
-void CJS_Array::Attach(v8::Local<v8::Array> pArray) {
- m_pArray = pArray;
-}
-
-void CJS_Array::GetElement(CJS_Runtime* pRuntime,
- unsigned index,
- CJS_Value& value) const {
- if (!m_pArray.IsEmpty())
- value.Attach(pRuntime->GetArrayElement(m_pArray, index));
-}
-
-void CJS_Array::SetElement(CJS_Runtime* pRuntime,
- unsigned index,
- const CJS_Value& value) {
- if (m_pArray.IsEmpty())
- m_pArray = pRuntime->NewArray();
-
- pRuntime->PutArrayElement(m_pArray, index, value.ToV8Value(pRuntime));
-}
-
-int CJS_Array::GetLength(CJS_Runtime* pRuntime) const {
- if (m_pArray.IsEmpty())
- return 0;
- return pRuntime->GetArrayLength(m_pArray);
-}
-
-v8::Local<v8::Array> CJS_Array::ToV8Array(CJS_Runtime* pRuntime) const {
- if (m_pArray.IsEmpty())
- m_pArray = pRuntime->NewArray();
-
- return m_pArray;
-}
-
-CJS_Date::CJS_Date() {}
-
-CJS_Date::CJS_Date(CJS_Runtime* pRuntime, double dMsecTime)
- : m_pDate(pRuntime->NewDate(dMsecTime)) {}
-
-CJS_Date::CJS_Date(CJS_Runtime* pRuntime,
- int year,
- int mon,
- int day,
- int hour,
- int min,
- int sec)
- : m_pDate(pRuntime->NewDate(MakeDate(year, mon, day, hour, min, sec, 0))) {}
-
-CJS_Date::~CJS_Date() {}
-
-bool CJS_Date::IsValidDate(CJS_Runtime* pRuntime) const {
- return !m_pDate.IsEmpty() && !JS_PortIsNan(pRuntime->ToDouble(m_pDate));
-}
-
-void CJS_Date::Attach(v8::Local<v8::Date> pDate) {
- m_pDate = pDate;
-}
-
-int CJS_Date::GetYear(CJS_Runtime* pRuntime) const {
- if (!IsValidDate(pRuntime))
- return 0;
-
- return JS_GetYearFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
-}
-
-void CJS_Date::SetYear(CJS_Runtime* pRuntime, int iYear) {
- m_pDate = pRuntime->NewDate(
- MakeDate(iYear, GetMonth(pRuntime), GetDay(pRuntime), GetHours(pRuntime),
- GetMinutes(pRuntime), GetSeconds(pRuntime), 0));
-}
-
-int CJS_Date::GetMonth(CJS_Runtime* pRuntime) const {
- if (!IsValidDate(pRuntime))
- return 0;
-
- return JS_GetMonthFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
-}
-
-void CJS_Date::SetMonth(CJS_Runtime* pRuntime, int iMonth) {
- m_pDate = pRuntime->NewDate(
- MakeDate(GetYear(pRuntime), iMonth, GetDay(pRuntime), GetHours(pRuntime),
- GetMinutes(pRuntime), GetSeconds(pRuntime), 0));
-}
-
-int CJS_Date::GetDay(CJS_Runtime* pRuntime) const {
- if (!IsValidDate(pRuntime))
- return 0;
-
- return JS_GetDayFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
-}
-
-void CJS_Date::SetDay(CJS_Runtime* pRuntime, int iDay) {
- m_pDate = pRuntime->NewDate(
- MakeDate(GetYear(pRuntime), GetMonth(pRuntime), iDay, GetHours(pRuntime),
- GetMinutes(pRuntime), GetSeconds(pRuntime), 0));
-}
-
-int CJS_Date::GetHours(CJS_Runtime* pRuntime) const {
- if (!IsValidDate(pRuntime))
- return 0;
-
- return JS_GetHourFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
-}
-
-void CJS_Date::SetHours(CJS_Runtime* pRuntime, int iHours) {
- m_pDate = pRuntime->NewDate(
- MakeDate(GetYear(pRuntime), GetMonth(pRuntime), GetDay(pRuntime), iHours,
- GetMinutes(pRuntime), GetSeconds(pRuntime), 0));
-}
-
-int CJS_Date::GetMinutes(CJS_Runtime* pRuntime) const {
- if (!IsValidDate(pRuntime))
- return 0;
-
- return JS_GetMinFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
-}
-
-void CJS_Date::SetMinutes(CJS_Runtime* pRuntime, int minutes) {
- m_pDate = pRuntime->NewDate(MakeDate(GetYear(pRuntime), GetMonth(pRuntime),
- GetDay(pRuntime), GetHours(pRuntime),
- minutes, GetSeconds(pRuntime), 0));
-}
-
-int CJS_Date::GetSeconds(CJS_Runtime* pRuntime) const {
- if (!IsValidDate(pRuntime))
- return 0;
-
- return JS_GetSecFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
-}
-
-void CJS_Date::SetSeconds(CJS_Runtime* pRuntime, int seconds) {
- m_pDate = pRuntime->NewDate(MakeDate(GetYear(pRuntime), GetMonth(pRuntime),
- GetDay(pRuntime), GetHours(pRuntime),
- GetMinutes(pRuntime), seconds, 0));
-}
-
-double CJS_Date::ToDouble(CJS_Runtime* pRuntime) const {
- return !m_pDate.IsEmpty() ? pRuntime->ToDouble(m_pDate) : 0.0;
-}
-
-CFX_WideString CJS_Date::ToString(CJS_Runtime* pRuntime) const {
- return !m_pDate.IsEmpty() ? pRuntime->ToWideString(m_pDate)
- : CFX_WideString();
-}
-
-v8::Local<v8::Date> CJS_Date::ToV8Date(CJS_Runtime* pRuntime) const {
- return m_pDate;
-}
-
-double _getLocalTZA() {
- if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
- return 0;
- time_t t = 0;
- time(&t);
- localtime(&t);
-#if _MSC_VER >= 1900
- // In gcc and in Visual Studio prior to VS 2015 'timezone' is a global
- // variable declared in time.h. That variable was deprecated and in VS 2015
- // is removed, with _get_timezone replacing it.
- long timezone = 0;
- _get_timezone(&timezone);
-#endif
- return (double)(-(timezone * 1000));
-}
-
-int _getDaylightSavingTA(double d) {
- if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
- return 0;
- time_t t = (time_t)(d / 1000);
- struct tm* tmp = localtime(&t);
- if (!tmp)
- return 0;
- if (tmp->tm_isdst > 0)
- // One hour.
- return (int)60 * 60 * 1000;
- return 0;
-}
-
-double _Mod(double x, double y) {
- double r = fmod(x, y);
- if (r < 0)
- r += y;
- return r;
-}
-
-int _isfinite(double v) {
-#if _MSC_VER
- return ::_finite(v);
-#else
- return std::fabs(v) < std::numeric_limits<double>::max();
-#endif
-}
-
-double _toInteger(double n) {
- return (n >= 0) ? FXSYS_floor(n) : -FXSYS_floor(-n);
-}
-
-bool _isLeapYear(int year) {
- return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0));
-}
-
-int _DayFromYear(int y) {
- return (int)(365 * (y - 1970.0) + FXSYS_floor((y - 1969.0) / 4) -
- FXSYS_floor((y - 1901.0) / 100) +
- FXSYS_floor((y - 1601.0) / 400));
-}
-
-double _TimeFromYear(int y) {
- return 86400000.0 * _DayFromYear(y);
-}
-
-static const uint16_t daysMonth[12] = {0, 31, 59, 90, 120, 151,
- 181, 212, 243, 273, 304, 334};
-static const uint16_t leapDaysMonth[12] = {0, 31, 60, 91, 121, 152,
- 182, 213, 244, 274, 305, 335};
-
-double _TimeFromYearMonth(int y, int m) {
- const uint16_t* pMonth = _isLeapYear(y) ? leapDaysMonth : daysMonth;
- return _TimeFromYear(y) + ((double)pMonth[m]) * 86400000;
-}
-
-int _Day(double t) {
- return (int)FXSYS_floor(t / 86400000);
-}
-
-int _YearFromTime(double t) {
- // estimate the time.
- int y = 1970 + static_cast<int>(t / (365.2425 * 86400000));
- if (_TimeFromYear(y) <= t) {
- while (_TimeFromYear(y + 1) <= t)
- y++;
- } else {
- while (_TimeFromYear(y) > t)
- y--;
- }
- return y;
-}
-
-int _DayWithinYear(double t) {
- int year = _YearFromTime(t);
- int day = _Day(t);
- return day - _DayFromYear(year);
-}
-
-int _MonthFromTime(double t) {
- int day = _DayWithinYear(t);
- int year = _YearFromTime(t);
- if (0 <= day && day < 31)
- return 0;
- if (31 <= day && day < 59 + _isLeapYear(year))
- return 1;
- if ((59 + _isLeapYear(year)) <= day && day < (90 + _isLeapYear(year)))
- return 2;
- if ((90 + _isLeapYear(year)) <= day && day < (120 + _isLeapYear(year)))
- return 3;
- if ((120 + _isLeapYear(year)) <= day && day < (151 + _isLeapYear(year)))
- return 4;
- if ((151 + _isLeapYear(year)) <= day && day < (181 + _isLeapYear(year)))
- return 5;
- if ((181 + _isLeapYear(year)) <= day && day < (212 + _isLeapYear(year)))
- return 6;
- if ((212 + _isLeapYear(year)) <= day && day < (243 + _isLeapYear(year)))
- return 7;
- if ((243 + _isLeapYear(year)) <= day && day < (273 + _isLeapYear(year)))
- return 8;
- if ((273 + _isLeapYear(year)) <= day && day < (304 + _isLeapYear(year)))
- return 9;
- if ((304 + _isLeapYear(year)) <= day && day < (334 + _isLeapYear(year)))
- return 10;
- if ((334 + _isLeapYear(year)) <= day && day < (365 + _isLeapYear(year)))
- return 11;
-
- return -1;
-}
-
-int _DateFromTime(double t) {
- int day = _DayWithinYear(t);
- int year = _YearFromTime(t);
- int leap = _isLeapYear(year);
- int month = _MonthFromTime(t);
- switch (month) {
- case 0:
- return day + 1;
- case 1:
- return day - 30;
- case 2:
- return day - 58 - leap;
- case 3:
- return day - 89 - leap;
- case 4:
- return day - 119 - leap;
- case 5:
- return day - 150 - leap;
- case 6:
- return day - 180 - leap;
- case 7:
- return day - 211 - leap;
- case 8:
- return day - 242 - leap;
- case 9:
- return day - 272 - leap;
- case 10:
- return day - 303 - leap;
- case 11:
- return day - 333 - leap;
- default:
- return 0;
- }
-}
-
-double JS_GetDateTime() {
- if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
- return 0;
- time_t t = time(nullptr);
- struct tm* pTm = localtime(&t);
-
- int year = pTm->tm_year + 1900;
- double t1 = _TimeFromYear(year);
-
- return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 +
- pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0;
-}
-
-int JS_GetYearFromTime(double dt) {
- return _YearFromTime(dt);
-}
-
-int JS_GetMonthFromTime(double dt) {
- return _MonthFromTime(dt);
-}
-
-int JS_GetDayFromTime(double dt) {
- return _DateFromTime(dt);
-}
-
-int JS_GetHourFromTime(double dt) {
- return (int)_Mod(floor(dt / (60 * 60 * 1000)), 24);
-}
-
-int JS_GetMinFromTime(double dt) {
- return (int)_Mod(floor(dt / (60 * 1000)), 60);
-}
-
-int JS_GetSecFromTime(double dt) {
- return (int)_Mod(floor(dt / 1000), 60);
-}
-
-double JS_DateParse(const CFX_WideString& str) {
- v8::Isolate* pIsolate = v8::Isolate::GetCurrent();
- v8::Isolate::Scope isolate_scope(pIsolate);
- v8::HandleScope scope(pIsolate);
-
- v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
-
- // Use the built-in object method.
- v8::Local<v8::Value> v =
- context->Global()
- ->Get(context, v8::String::NewFromUtf8(pIsolate, "Date",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .ToLocalChecked();
- if (v->IsObject()) {
- v8::Local<v8::Object> o = v->ToObject(context).ToLocalChecked();
- v = o->Get(context, v8::String::NewFromUtf8(pIsolate, "parse",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .ToLocalChecked();
- if (v->IsFunction()) {
- v8::Local<v8::Function> funC = v8::Local<v8::Function>::Cast(v);
- const int argc = 1;
- v8::Local<v8::Value> timeStr =
- CJS_Runtime::CurrentRuntimeFromIsolate(pIsolate)->NewString(
- str.AsStringC());
- v8::Local<v8::Value> argv[argc] = {timeStr};
- v = funC->Call(context, context->Global(), argc, argv).ToLocalChecked();
- if (v->IsNumber()) {
- double date = v->ToNumber(context).ToLocalChecked()->Value();
- if (!_isfinite(date))
- return date;
- return JS_LocalTime(date);
- }
- }
- }
- return 0;
-}
-
-double JS_MakeDay(int nYear, int nMonth, int nDate) {
- if (!_isfinite(nYear) || !_isfinite(nMonth) || !_isfinite(nDate))
- return GetNan();
- double y = _toInteger(nYear);
- double m = _toInteger(nMonth);
- double dt = _toInteger(nDate);
- double ym = y + FXSYS_floor((double)m / 12);
- double mn = _Mod(m, 12);
-
- double t = _TimeFromYearMonth((int)ym, (int)mn);
-
- if (_YearFromTime(t) != ym || _MonthFromTime(t) != mn ||
- _DateFromTime(t) != 1)
- return GetNan();
- return _Day(t) + dt - 1;
-}
-
-double JS_MakeTime(int nHour, int nMin, int nSec, int nMs) {
- if (!_isfinite(nHour) || !_isfinite(nMin) || !_isfinite(nSec) ||
- !_isfinite(nMs))
- return GetNan();
-
- double h = _toInteger(nHour);
- double m = _toInteger(nMin);
- double s = _toInteger(nSec);
- double milli = _toInteger(nMs);
-
- return h * 3600000 + m * 60000 + s * 1000 + milli;
-}
-
-double JS_MakeDate(double day, double time) {
- if (!_isfinite(day) || !_isfinite(time))
- return GetNan();
-
- return day * 86400000 + time;
-}
-
-bool JS_PortIsNan(double d) {
- return d != d;
-}
-
-double JS_LocalTime(double d) {
- return d + _getLocalTZA() + _getDaylightSavingTA(d);
-}
-
-std::vector<CJS_Value> JS_ExpandKeywordParams(
- CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& originals,
- size_t nKeywords,
- ...) {
- ASSERT(nKeywords);
-
- std::vector<CJS_Value> result(nKeywords, CJS_Value(pRuntime));
- size_t size = std::min(originals.size(), nKeywords);
- for (size_t i = 0; i < size; ++i)
- result[i] = originals[i];
-
- if (originals.size() != 1 || originals[0].GetType() != CJS_Value::VT_object ||
- originals[0].IsArrayObject()) {
- return result;
- }
- v8::Local<v8::Object> pObj = originals[0].ToV8Object(pRuntime);
- result[0] = CJS_Value(pRuntime); // Make unknown.
-
- va_list ap;
- va_start(ap, nKeywords);
- for (size_t i = 0; i < nKeywords; ++i) {
- const wchar_t* property = va_arg(ap, const wchar_t*);
- v8::Local<v8::Value> v8Value = pRuntime->GetObjectProperty(pObj, property);
- if (!v8Value->IsUndefined())
- result[i] = CJS_Value(pRuntime, v8Value);
- }
- va_end(ap);
- return result;
-}
diff --git a/fpdfsdk/javascript/JS_Value.h b/fpdfsdk/javascript/JS_Value.h
deleted file mode 100644
index 313f0c3..0000000
--- a/fpdfsdk/javascript/JS_Value.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_JS_VALUE_H_
-#define FPDFSDK_JAVASCRIPT_JS_VALUE_H_
-
-#include <vector>
-
-#include "core/fxcrt/fx_basic.h"
-#include "fxjs/fxjs_v8.h"
-
-class CJS_Array;
-class CJS_Date;
-class CJS_Document;
-class CJS_Object;
-class CJS_Runtime;
-
-class CJS_Value {
- public:
- enum Type {
- VT_unknown,
- VT_string,
- VT_number,
- VT_boolean,
- VT_date,
- VT_object,
- VT_null,
- VT_undefined
- };
-
- explicit CJS_Value(CJS_Runtime* pRuntime);
- CJS_Value(CJS_Runtime* pRuntime, v8::Local<v8::Value> pValue);
- CJS_Value(CJS_Runtime* pRuntime, const int& iValue);
- CJS_Value(CJS_Runtime* pRuntime, const double& dValue);
- CJS_Value(CJS_Runtime* pRuntime, const float& fValue);
- CJS_Value(CJS_Runtime* pRuntime, const bool& bValue);
- CJS_Value(CJS_Runtime* pRuntime, CJS_Object* pObj);
- CJS_Value(CJS_Runtime* pRuntime, const FX_CHAR* pStr);
- CJS_Value(CJS_Runtime* pRuntime, const FX_WCHAR* pWstr);
- CJS_Value(CJS_Runtime* pRuntime, const CJS_Array& array);
- CJS_Value(CJS_Runtime* pRuntime, const CJS_Date& date);
- CJS_Value(CJS_Runtime* pRuntime, const CJS_Object* object);
- CJS_Value(const CJS_Value& other);
-
- ~CJS_Value();
-
- void SetNull(CJS_Runtime* pRuntime);
- void SetValue(const CJS_Value& other);
- void Attach(v8::Local<v8::Value> pValue);
- void Detach();
-
- static Type GetValueType(v8::Local<v8::Value> value);
- Type GetType() const { return GetValueType(m_pValue); }
-
- int ToInt(CJS_Runtime* pRuntime) const;
- bool ToBool(CJS_Runtime* pRuntime) const;
- double ToDouble(CJS_Runtime* pRuntime) const;
- float ToFloat(CJS_Runtime* pRuntime) const;
- CJS_Object* ToCJSObject(CJS_Runtime* pRuntime) const;
- CFX_WideString ToCFXWideString(CJS_Runtime* pRuntime) const;
- CFX_ByteString ToCFXByteString(CJS_Runtime* pRuntime) const;
- v8::Local<v8::Object> ToV8Object(CJS_Runtime* pRuntime) const;
- v8::Local<v8::Array> ToV8Array(CJS_Runtime* pRuntime) const;
- v8::Local<v8::Value> ToV8Value(CJS_Runtime* pRuntime) const;
-
- // Replace the current |m_pValue| with a v8::Number if possible
- // to make one from the current |m_pValue|.
- void MaybeCoerceToNumber(CJS_Runtime* pRuntime);
-
- bool IsArrayObject() const;
- bool IsDateObject() const;
- bool ConvertToArray(CJS_Runtime* pRuntime, CJS_Array&) const;
- bool ConvertToDate(CJS_Runtime* pRuntime, CJS_Date&) const;
-
- protected:
- v8::Local<v8::Value> m_pValue;
-};
-
-class CJS_PropValue {
- public:
- explicit CJS_PropValue(CJS_Runtime* pRuntime);
- CJS_PropValue(CJS_Runtime* pRuntime, const CJS_Value&);
- ~CJS_PropValue();
-
- void StartSetting() { m_bIsSetting = true; }
- void StartGetting() { m_bIsSetting = false; }
- bool IsSetting() const { return m_bIsSetting; }
- bool IsGetting() const { return !m_bIsSetting; }
- CJS_Runtime* GetJSRuntime() const { return m_pJSRuntime; }
- CJS_Value* GetJSValue() { return &m_Value; }
-
- // These calls may re-enter JS (and hence invalidate objects).
- void operator<<(int val);
- void operator>>(int&) const;
- void operator<<(bool val);
- void operator>>(bool&) const;
- void operator<<(double val);
- void operator>>(double&) const;
- void operator<<(CJS_Object* pObj);
- void operator>>(CJS_Object*& ppObj) const;
- void operator<<(CJS_Document* pJsDoc);
- void operator>>(CJS_Document*& ppJsDoc) const;
- void operator<<(CFX_ByteString);
- void operator>>(CFX_ByteString&) const;
- void operator<<(CFX_WideString);
- void operator>>(CFX_WideString&) const;
- void operator<<(const FX_WCHAR* c_string);
- void operator<<(v8::Local<v8::Object>);
- void operator>>(v8::Local<v8::Object>&) const;
- void operator>>(CJS_Array& array) const;
- void operator<<(CJS_Array& array);
- void operator<<(CJS_Date& date);
- void operator>>(CJS_Date& date) const;
-
- private:
- bool m_bIsSetting;
- CJS_Value m_Value;
- CJS_Runtime* const m_pJSRuntime;
-};
-
-class CJS_Array {
- public:
- CJS_Array();
- CJS_Array(const CJS_Array& other);
- virtual ~CJS_Array();
-
- void Attach(v8::Local<v8::Array> pArray);
- int GetLength(CJS_Runtime* pRuntime) const;
-
- // These two calls may re-enter JS (and hence invalidate objects).
- void GetElement(CJS_Runtime* pRuntime,
- unsigned index,
- CJS_Value& value) const;
- void SetElement(CJS_Runtime* pRuntime,
- unsigned index,
- const CJS_Value& value);
-
- v8::Local<v8::Array> ToV8Array(CJS_Runtime* pRuntime) const;
-
- private:
- mutable v8::Local<v8::Array> m_pArray;
-};
-
-class CJS_Date {
- public:
- CJS_Date();
- CJS_Date(CJS_Runtime* pRuntime, double dMsec_time);
- CJS_Date(CJS_Runtime* pRuntime,
- int year,
- int mon,
- int day,
- int hour,
- int min,
- int sec);
- virtual ~CJS_Date();
-
- void Attach(v8::Local<v8::Date> pDate);
- bool IsValidDate(CJS_Runtime* pRuntime) const;
-
- int GetYear(CJS_Runtime* pRuntime) const;
- void SetYear(CJS_Runtime* pRuntime, int iYear);
-
- int GetMonth(CJS_Runtime* pRuntime) const;
- void SetMonth(CJS_Runtime* pRuntime, int iMonth);
-
- int GetDay(CJS_Runtime* pRuntime) const;
- void SetDay(CJS_Runtime* pRuntime, int iDay);
-
- int GetHours(CJS_Runtime* pRuntime) const;
- void SetHours(CJS_Runtime* pRuntime, int iHours);
-
- int GetMinutes(CJS_Runtime* pRuntime) const;
- void SetMinutes(CJS_Runtime* pRuntime, int minutes);
-
- int GetSeconds(CJS_Runtime* pRuntime) const;
- void SetSeconds(CJS_Runtime* pRuntime, int seconds);
-
- v8::Local<v8::Date> ToV8Date(CJS_Runtime* pRuntime) const;
- double ToDouble(CJS_Runtime* pRuntime) const;
- CFX_WideString ToString(CJS_Runtime* pRuntime) const;
-
- protected:
- v8::Local<v8::Date> m_pDate;
-};
-
-double JS_GetDateTime();
-int JS_GetYearFromTime(double dt);
-int JS_GetMonthFromTime(double dt);
-int JS_GetDayFromTime(double dt);
-int JS_GetHourFromTime(double dt);
-int JS_GetMinFromTime(double dt);
-int JS_GetSecFromTime(double dt);
-double JS_DateParse(const CFX_WideString& str);
-double JS_MakeDay(int nYear, int nMonth, int nDay);
-double JS_MakeTime(int nHour, int nMin, int nSec, int nMs);
-double JS_MakeDate(double day, double time);
-bool JS_PortIsNan(double d);
-double JS_LocalTime(double d);
-
-// Some JS methods have the bizarre convention that they may also be called
-// with a single argument which is an object containing the actual arguments
-// as its properties. The varying arguments to this method are the property
-// names as wchar_t string literals corresponding to each positional argument.
-// The result will always contain |nKeywords| value, with unspecified ones
-// being set to type VT_unknown.
-std::vector<CJS_Value> JS_ExpandKeywordParams(
- CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& originals,
- size_t nKeywords,
- ...);
-
-#endif // FPDFSDK_JAVASCRIPT_JS_VALUE_H_
diff --git a/fpdfsdk/javascript/PublicMethods.cpp b/fpdfsdk/javascript/PublicMethods.cpp
deleted file mode 100644
index 3bcbc34..0000000
--- a/fpdfsdk/javascript/PublicMethods.cpp
+++ /dev/null
@@ -1,1801 +0,0 @@
-// Copyright 2014 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/javascript/PublicMethods.h"
-
-#include <algorithm>
-#include <iomanip>
-#include <limits>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "core/fpdfdoc/cpdf_interform.h"
-#include "core/fxcrt/fx_ext.h"
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/cpdfsdk_interform.h"
-#include "fpdfsdk/javascript/Field.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fpdfsdk/javascript/color.h"
-#include "fpdfsdk/javascript/resource.h"
-#include "fpdfsdk/javascript/util.h"
-
-#define DOUBLE_CORRECT 0.000000000000001
-
-JSMethodSpec CJS_PublicMethods::GlobalFunctionSpecs[] = {
- {"AFNumber_Format", AFNumber_Format_static},
- {"AFNumber_Keystroke", AFNumber_Keystroke_static},
- {"AFPercent_Format", AFPercent_Format_static},
- {"AFPercent_Keystroke", AFPercent_Keystroke_static},
- {"AFDate_FormatEx", AFDate_FormatEx_static},
- {"AFDate_KeystrokeEx", AFDate_KeystrokeEx_static},
- {"AFDate_Format", AFDate_Format_static},
- {"AFDate_Keystroke", AFDate_Keystroke_static},
- {"AFTime_FormatEx", AFTime_FormatEx_static},
- {"AFTime_KeystrokeEx", AFTime_KeystrokeEx_static},
- {"AFTime_Format", AFTime_Format_static},
- {"AFTime_Keystroke", AFTime_Keystroke_static},
- {"AFSpecial_Format", AFSpecial_Format_static},
- {"AFSpecial_Keystroke", AFSpecial_Keystroke_static},
- {"AFSpecial_KeystrokeEx", AFSpecial_KeystrokeEx_static},
- {"AFSimple", AFSimple_static},
- {"AFMakeNumber", AFMakeNumber_static},
- {"AFSimple_Calculate", AFSimple_Calculate_static},
- {"AFRange_Validate", AFRange_Validate_static},
- {"AFMergeChange", AFMergeChange_static},
- {"AFParseDateEx", AFParseDateEx_static},
- {"AFExtractNums", AFExtractNums_static},
- {0, 0}};
-
-IMPLEMENT_JS_STATIC_GLOBAL_FUN(CJS_PublicMethods)
-
-namespace {
-
-const FX_WCHAR* const months[] = {L"Jan", L"Feb", L"Mar", L"Apr",
- L"May", L"Jun", L"Jul", L"Aug",
- L"Sep", L"Oct", L"Nov", L"Dec"};
-
-const FX_WCHAR* const fullmonths[] = {L"January", L"February", L"March",
- L"April", L"May", L"June",
- L"July", L"August", L"September",
- L"October", L"November", L"December"};
-
-CFX_ByteString StrTrim(const CFX_ByteString& pStr) {
- CFX_ByteString result(pStr);
- result.TrimLeft(' ');
- result.TrimRight(' ');
- return result;
-}
-
-CFX_WideString StrTrim(const CFX_WideString& pStr) {
- CFX_WideString result(pStr);
- result.TrimLeft(' ');
- result.TrimRight(' ');
- return result;
-}
-
-void AlertIfPossible(CJS_EventContext* pContext, const FX_WCHAR* swMsg) {
- CPDFSDK_FormFillEnvironment* pFormFillEnv = pContext->GetFormFillEnv();
- if (pFormFillEnv)
- pFormFillEnv->JS_appAlert(swMsg, nullptr, 0, 3);
-}
-
-#if _FX_OS_ != _FX_ANDROID_
-CFX_ByteString CalculateString(double dValue,
- int iDec,
- int* iDec2,
- bool* bNegative) {
- *bNegative = dValue < 0;
- if (*bNegative)
- dValue = -dValue;
-
- // Make sure the number of precision characters will fit.
- if (iDec > std::numeric_limits<double>::digits10)
- iDec = std::numeric_limits<double>::digits10;
-
- std::stringstream ss;
- ss << std::fixed << std::setprecision(iDec) << dValue;
- std::string stringValue = ss.str();
- size_t iDecimalPos = stringValue.find(".");
- *iDec2 = iDecimalPos == std::string::npos ? stringValue.size()
- : static_cast<int>(iDecimalPos);
- return CFX_ByteString(stringValue.c_str());
-}
-#endif
-
-} // namespace
-
-bool CJS_PublicMethods::IsNumber(const CFX_WideString& str) {
- CFX_WideString sTrim = StrTrim(str);
- const FX_WCHAR* pTrim = sTrim.c_str();
- const FX_WCHAR* p = pTrim;
- bool bDot = false;
- bool bKXJS = false;
-
- wchar_t c;
- while ((c = *p) != L'\0') {
- if (c == L'.' || c == L',') {
- if (bDot)
- return false;
- bDot = true;
- } else if (c == L'-' || c == L'+') {
- if (p != pTrim)
- return false;
- } else if (c == L'e' || c == L'E') {
- if (bKXJS)
- return false;
-
- p++;
- c = *p;
- if (c == L'+' || c == L'-') {
- bKXJS = true;
- } else {
- return false;
- }
- } else if (!FXSYS_iswdigit(c)) {
- return false;
- }
- p++;
- }
-
- return true;
-}
-
-bool CJS_PublicMethods::maskSatisfied(wchar_t c_Change, wchar_t c_Mask) {
- switch (c_Mask) {
- case L'9':
- return FXSYS_iswdigit(c_Change);
- case L'A':
- return FXSYS_iswalpha(c_Change);
- case L'O':
- return FXSYS_iswalnum(c_Change);
- case L'X':
- return true;
- default:
- return (c_Change == c_Mask);
- }
-}
-
-bool CJS_PublicMethods::isReservedMaskChar(wchar_t ch) {
- return ch == L'9' || ch == L'A' || ch == L'O' || ch == L'X';
-}
-
-double CJS_PublicMethods::AF_Simple(const FX_WCHAR* sFuction,
- double dValue1,
- double dValue2) {
- if (FXSYS_wcsicmp(sFuction, L"AVG") == 0 ||
- FXSYS_wcsicmp(sFuction, L"SUM") == 0) {
- return dValue1 + dValue2;
- }
- if (FXSYS_wcsicmp(sFuction, L"PRD") == 0) {
- return dValue1 * dValue2;
- }
- if (FXSYS_wcsicmp(sFuction, L"MIN") == 0) {
- return std::min(dValue1, dValue2);
- }
- if (FXSYS_wcsicmp(sFuction, L"MAX") == 0) {
- return std::max(dValue1, dValue2);
- }
- return dValue1;
-}
-
-CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime,
- CJS_Value val) {
- CJS_Array StrArray;
- if (val.IsArrayObject()) {
- val.ConvertToArray(pRuntime, StrArray);
- return StrArray;
- }
- CFX_WideString wsStr = val.ToCFXWideString(pRuntime);
- CFX_ByteString t = CFX_ByteString::FromUnicode(wsStr);
- const char* p = t.c_str();
-
- int ch = ',';
- int nIndex = 0;
-
- while (*p) {
- const char* pTemp = strchr(p, ch);
- if (!pTemp) {
- StrArray.SetElement(
- pRuntime, nIndex,
- CJS_Value(pRuntime, StrTrim(CFX_ByteString(p)).c_str()));
- break;
- }
-
- char* pSub = new char[pTemp - p + 1];
- strncpy(pSub, p, pTemp - p);
- *(pSub + (pTemp - p)) = '\0';
-
- StrArray.SetElement(
- pRuntime, nIndex,
- CJS_Value(pRuntime, StrTrim(CFX_ByteString(pSub)).c_str()));
- delete[] pSub;
-
- nIndex++;
- p = ++pTemp;
- }
- return StrArray;
-}
-
-int CJS_PublicMethods::ParseStringInteger(const CFX_WideString& str,
- int nStart,
- int& nSkip,
- int nMaxStep) {
- int nRet = 0;
- nSkip = 0;
- for (int i = nStart, sz = str.GetLength(); i < sz; i++) {
- if (i - nStart > 10)
- break;
-
- FX_WCHAR c = str.GetAt(i);
- if (!FXSYS_iswdigit(c))
- break;
-
- nRet = nRet * 10 + FXSYS_toDecimalDigit(c);
- nSkip = i - nStart + 1;
- if (nSkip >= nMaxStep)
- break;
- }
-
- return nRet;
-}
-
-CFX_WideString CJS_PublicMethods::ParseStringString(const CFX_WideString& str,
- int nStart,
- int& nSkip) {
- CFX_WideString swRet;
- nSkip = 0;
- for (int i = nStart, sz = str.GetLength(); i < sz; i++) {
- FX_WCHAR c = str.GetAt(i);
- if (!FXSYS_iswdigit(c))
- break;
-
- swRet += c;
- nSkip = i - nStart + 1;
- }
-
- return swRet;
-}
-
-double CJS_PublicMethods::ParseNormalDate(const CFX_WideString& value,
- bool* bWrongFormat) {
- double dt = JS_GetDateTime();
-
- int nYear = JS_GetYearFromTime(dt);
- int nMonth = JS_GetMonthFromTime(dt) + 1;
- int nDay = JS_GetDayFromTime(dt);
- int nHour = JS_GetHourFromTime(dt);
- int nMin = JS_GetMinFromTime(dt);
- int nSec = JS_GetSecFromTime(dt);
-
- int number[3];
-
- int nSkip = 0;
- int nLen = value.GetLength();
- int nIndex = 0;
- int i = 0;
- while (i < nLen) {
- if (nIndex > 2)
- break;
-
- FX_WCHAR c = value.GetAt(i);
- if (FXSYS_iswdigit(c)) {
- number[nIndex++] = ParseStringInteger(value, i, nSkip, 4);
- i += nSkip;
- } else {
- i++;
- }
- }
-
- if (nIndex == 2) {
- // case2: month/day
- // case3: day/month
- if ((number[0] >= 1 && number[0] <= 12) &&
- (number[1] >= 1 && number[1] <= 31)) {
- nMonth = number[0];
- nDay = number[1];
- } else if ((number[0] >= 1 && number[0] <= 31) &&
- (number[1] >= 1 && number[1] <= 12)) {
- nDay = number[0];
- nMonth = number[1];
- }
-
- if (bWrongFormat)
- *bWrongFormat = false;
- } else if (nIndex == 3) {
- // case1: year/month/day
- // case2: month/day/year
- // case3: day/month/year
-
- if (number[0] > 12 && (number[1] >= 1 && number[1] <= 12) &&
- (number[2] >= 1 && number[2] <= 31)) {
- nYear = number[0];
- nMonth = number[1];
- nDay = number[2];
- } else if ((number[0] >= 1 && number[0] <= 12) &&
- (number[1] >= 1 && number[1] <= 31) && number[2] > 31) {
- nMonth = number[0];
- nDay = number[1];
- nYear = number[2];
- } else if ((number[0] >= 1 && number[0] <= 31) &&
- (number[1] >= 1 && number[1] <= 12) && number[2] > 31) {
- nDay = number[0];
- nMonth = number[1];
- nYear = number[2];
- }
-
- if (bWrongFormat)
- *bWrongFormat = false;
- } else {
- if (bWrongFormat)
- *bWrongFormat = true;
- return dt;
- }
-
- CFX_WideString swTemp;
- swTemp.Format(L"%d/%d/%d %d:%d:%d", nMonth, nDay, nYear, nHour, nMin, nSec);
- return JS_DateParse(swTemp);
-}
-
-double CJS_PublicMethods::MakeRegularDate(const CFX_WideString& value,
- const CFX_WideString& format,
- bool* bWrongFormat) {
- double dt = JS_GetDateTime();
-
- if (format.IsEmpty() || value.IsEmpty())
- return dt;
-
- int nYear = JS_GetYearFromTime(dt);
- int nMonth = JS_GetMonthFromTime(dt) + 1;
- int nDay = JS_GetDayFromTime(dt);
- int nHour = JS_GetHourFromTime(dt);
- int nMin = JS_GetMinFromTime(dt);
- int nSec = JS_GetSecFromTime(dt);
-
- int nYearSub = 99; // nYear - 2000;
-
- bool bPm = false;
- bool bExit = false;
- bool bBadFormat = false;
-
- int i = 0;
- int j = 0;
-
- while (i < format.GetLength()) {
- if (bExit)
- break;
-
- FX_WCHAR c = format.GetAt(i);
- switch (c) {
- case ':':
- case '.':
- case '-':
- case '\\':
- case '/':
- i++;
- j++;
- break;
-
- case 'y':
- case 'm':
- case 'd':
- case 'H':
- case 'h':
- case 'M':
- case 's':
- case 't': {
- int oldj = j;
- int nSkip = 0;
- int remaining = format.GetLength() - i - 1;
-
- if (remaining == 0 || format.GetAt(i + 1) != c) {
- switch (c) {
- case 'y':
- i++;
- j++;
- break;
- case 'm':
- nMonth = ParseStringInteger(value, j, nSkip, 2);
- i++;
- j += nSkip;
- break;
- case 'd':
- nDay = ParseStringInteger(value, j, nSkip, 2);
- i++;
- j += nSkip;
- break;
- case 'H':
- nHour = ParseStringInteger(value, j, nSkip, 2);
- i++;
- j += nSkip;
- break;
- case 'h':
- nHour = ParseStringInteger(value, j, nSkip, 2);
- i++;
- j += nSkip;
- break;
- case 'M':
- nMin = ParseStringInteger(value, j, nSkip, 2);
- i++;
- j += nSkip;
- break;
- case 's':
- nSec = ParseStringInteger(value, j, nSkip, 2);
- i++;
- j += nSkip;
- break;
- case 't':
- bPm = (j < value.GetLength() && value.GetAt(j) == 'p');
- i++;
- j++;
- break;
- }
- } else if (remaining == 1 || format.GetAt(i + 2) != c) {
- switch (c) {
- case 'y':
- nYear = ParseStringInteger(value, j, nSkip, 4);
- i += 2;
- j += nSkip;
- break;
- case 'm':
- nMonth = ParseStringInteger(value, j, nSkip, 2);
- i += 2;
- j += nSkip;
- break;
- case 'd':
- nDay = ParseStringInteger(value, j, nSkip, 2);
- i += 2;
- j += nSkip;
- break;
- case 'H':
- nHour = ParseStringInteger(value, j, nSkip, 2);
- i += 2;
- j += nSkip;
- break;
- case 'h':
- nHour = ParseStringInteger(value, j, nSkip, 2);
- i += 2;
- j += nSkip;
- break;
- case 'M':
- nMin = ParseStringInteger(value, j, nSkip, 2);
- i += 2;
- j += nSkip;
- break;
- case 's':
- nSec = ParseStringInteger(value, j, nSkip, 2);
- i += 2;
- j += nSkip;
- break;
- case 't':
- bPm = (j + 1 < value.GetLength() && value.GetAt(j) == 'p' &&
- value.GetAt(j + 1) == 'm');
- i += 2;
- j += 2;
- break;
- }
- } else if (remaining == 2 || format.GetAt(i + 3) != c) {
- switch (c) {
- case 'm': {
- CFX_WideString sMonth = ParseStringString(value, j, nSkip);
- bool bFind = false;
- for (int m = 0; m < 12; m++) {
- if (sMonth.CompareNoCase(months[m]) == 0) {
- nMonth = m + 1;
- i += 3;
- j += nSkip;
- bFind = true;
- break;
- }
- }
-
- if (!bFind) {
- nMonth = ParseStringInteger(value, j, nSkip, 3);
- i += 3;
- j += nSkip;
- }
- } break;
- case 'y':
- break;
- default:
- i += 3;
- j += 3;
- break;
- }
- } else if (remaining == 3 || format.GetAt(i + 4) != c) {
- switch (c) {
- case 'y':
- nYear = ParseStringInteger(value, j, nSkip, 4);
- j += nSkip;
- i += 4;
- break;
- case 'm': {
- bool bFind = false;
-
- CFX_WideString sMonth = ParseStringString(value, j, nSkip);
- sMonth.MakeLower();
-
- for (int m = 0; m < 12; m++) {
- CFX_WideString sFullMonths = fullmonths[m];
- sFullMonths.MakeLower();
-
- if (sFullMonths.Find(sMonth.c_str(), 0) != -1) {
- nMonth = m + 1;
- i += 4;
- j += nSkip;
- bFind = true;
- break;
- }
- }
-
- if (!bFind) {
- nMonth = ParseStringInteger(value, j, nSkip, 4);
- i += 4;
- j += nSkip;
- }
- } break;
- default:
- i += 4;
- j += 4;
- break;
- }
- } else {
- if (j >= value.GetLength() || format.GetAt(i) != value.GetAt(j)) {
- bBadFormat = true;
- bExit = true;
- }
- i++;
- j++;
- }
-
- if (oldj == j) {
- bBadFormat = true;
- bExit = true;
- }
- }
-
- break;
- default:
- if (value.GetLength() <= j) {
- bExit = true;
- } else if (format.GetAt(i) != value.GetAt(j)) {
- bBadFormat = true;
- bExit = true;
- }
-
- i++;
- j++;
- break;
- }
- }
-
- if (bPm)
- nHour += 12;
-
- if (nYear >= 0 && nYear <= nYearSub)
- nYear += 2000;
-
- if (nMonth < 1 || nMonth > 12)
- bBadFormat = true;
-
- if (nDay < 1 || nDay > 31)
- bBadFormat = true;
-
- if (nHour < 0 || nHour > 24)
- bBadFormat = true;
-
- if (nMin < 0 || nMin > 60)
- bBadFormat = true;
-
- if (nSec < 0 || nSec > 60)
- bBadFormat = true;
-
- double dRet = 0;
- if (bBadFormat) {
- dRet = ParseNormalDate(value, &bBadFormat);
- } else {
- dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
- JS_MakeTime(nHour, nMin, nSec, 0));
- if (JS_PortIsNan(dRet))
- dRet = JS_DateParse(value);
- }
-
- if (JS_PortIsNan(dRet))
- dRet = ParseNormalDate(value, &bBadFormat);
-
- if (bWrongFormat)
- *bWrongFormat = bBadFormat;
-
- return dRet;
-}
-
-CFX_WideString CJS_PublicMethods::MakeFormatDate(double dDate,
- const CFX_WideString& format) {
- CFX_WideString sRet = L"", sPart = L"";
-
- int nYear = JS_GetYearFromTime(dDate);
- int nMonth = JS_GetMonthFromTime(dDate) + 1;
- int nDay = JS_GetDayFromTime(dDate);
- int nHour = JS_GetHourFromTime(dDate);
- int nMin = JS_GetMinFromTime(dDate);
- int nSec = JS_GetSecFromTime(dDate);
-
- int i = 0;
- while (i < format.GetLength()) {
- FX_WCHAR c = format.GetAt(i);
- int remaining = format.GetLength() - i - 1;
- sPart = L"";
- switch (c) {
- case 'y':
- case 'm':
- case 'd':
- case 'H':
- case 'h':
- case 'M':
- case 's':
- case 't':
- if (remaining == 0 || format.GetAt(i + 1) != c) {
- switch (c) {
- case 'y':
- sPart += c;
- break;
- case 'm':
- sPart.Format(L"%d", nMonth);
- break;
- case 'd':
- sPart.Format(L"%d", nDay);
- break;
- case 'H':
- sPart.Format(L"%d", nHour);
- break;
- case 'h':
- sPart.Format(L"%d", nHour > 12 ? nHour - 12 : nHour);
- break;
- case 'M':
- sPart.Format(L"%d", nMin);
- break;
- case 's':
- sPart.Format(L"%d", nSec);
- break;
- case 't':
- sPart += nHour > 12 ? 'p' : 'a';
- break;
- }
- i++;
- } else if (remaining == 1 || format.GetAt(i + 2) != c) {
- switch (c) {
- case 'y':
- sPart.Format(L"%02d", nYear - (nYear / 100) * 100);
- break;
- case 'm':
- sPart.Format(L"%02d", nMonth);
- break;
- case 'd':
- sPart.Format(L"%02d", nDay);
- break;
- case 'H':
- sPart.Format(L"%02d", nHour);
- break;
- case 'h':
- sPart.Format(L"%02d", nHour > 12 ? nHour - 12 : nHour);
- break;
- case 'M':
- sPart.Format(L"%02d", nMin);
- break;
- case 's':
- sPart.Format(L"%02d", nSec);
- break;
- case 't':
- sPart = nHour > 12 ? L"pm" : L"am";
- break;
- }
- i += 2;
- } else if (remaining == 2 || format.GetAt(i + 3) != c) {
- switch (c) {
- case 'm':
- i += 3;
- if (nMonth > 0 && nMonth <= 12)
- sPart += months[nMonth - 1];
- break;
- default:
- i += 3;
- sPart += c;
- sPart += c;
- sPart += c;
- break;
- }
- } else if (remaining == 3 || format.GetAt(i + 4) != c) {
- switch (c) {
- case 'y':
- sPart.Format(L"%04d", nYear);
- i += 4;
- break;
- case 'm':
- i += 4;
- if (nMonth > 0 && nMonth <= 12)
- sPart += fullmonths[nMonth - 1];
- break;
- default:
- i += 4;
- sPart += c;
- sPart += c;
- sPart += c;
- sPart += c;
- break;
- }
- } else {
- i++;
- sPart += c;
- }
- break;
- default:
- i++;
- sPart += c;
- break;
- }
-
- sRet += sPart;
- }
-
- return sRet;
-}
-
-// function AFNumber_Format(nDec, sepStyle, negStyle, currStyle, strCurrency,
-// bCurrencyPrepend)
-bool CJS_PublicMethods::AFNumber_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
-#if _FX_OS_ != _FX_ANDROID_
- if (params.size() != 6) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
- if (!pEvent->m_pValue)
- return false;
-
- CFX_WideString& Value = pEvent->Value();
- CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
- if (strValue.IsEmpty())
- return true;
-
- int iDec = params[0].ToInt(pRuntime);
- int iSepStyle = params[1].ToInt(pRuntime);
- int iNegStyle = params[2].ToInt(pRuntime);
- // params[3] is iCurrStyle, it's not used.
- CFX_WideString wstrCurrency = params[4].ToCFXWideString(pRuntime);
- bool bCurrencyPrepend = params[5].ToBool(pRuntime);
-
- if (iDec < 0)
- iDec = -iDec;
-
- if (iSepStyle < 0 || iSepStyle > 3)
- iSepStyle = 0;
-
- if (iNegStyle < 0 || iNegStyle > 3)
- iNegStyle = 0;
-
- // Processing decimal places
- strValue.Replace(",", ".");
- double dValue = atof(strValue.c_str());
- if (iDec > 0)
- dValue += DOUBLE_CORRECT;
-
- // Calculating number string
- bool bNegative;
- int iDec2;
- strValue = CalculateString(dValue, iDec, &iDec2, &bNegative);
- if (strValue.IsEmpty()) {
- dValue = 0;
- strValue = CalculateString(dValue, iDec, &iDec2, &bNegative);
- if (strValue.IsEmpty()) {
- strValue = "0";
- iDec2 = 1;
- }
- }
-
- // Processing separator style
- if (iDec2 < strValue.GetLength()) {
- if (iSepStyle == 2 || iSepStyle == 3)
- strValue.Replace(".", ",");
-
- if (iDec2 == 0)
- strValue.Insert(iDec2, '0');
- }
- if (iSepStyle == 0 || iSepStyle == 2) {
- char cSeparator;
- if (iSepStyle == 0)
- cSeparator = ',';
- else
- cSeparator = '.';
-
- for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3)
- strValue.Insert(iDecPositive, cSeparator);
- }
-
- // Processing currency string
- Value = CFX_WideString::FromLocal(strValue.AsStringC());
-
- if (bCurrencyPrepend)
- Value = wstrCurrency + Value;
- else
- Value = Value + wstrCurrency;
-
- // Processing negative style
- if (bNegative) {
- if (iNegStyle == 0)
- Value = L"-" + Value;
- else if (iNegStyle == 2 || iNegStyle == 3)
- Value = L"(" + Value + L")";
- if (iNegStyle == 1 || iNegStyle == 3) {
- if (Field* fTarget = pEvent->Target_Field()) {
- CJS_Array arColor;
- CJS_Value vColElm(pRuntime);
- vColElm = CJS_Value(pRuntime, L"RGB");
- arColor.SetElement(pRuntime, 0, vColElm);
- vColElm = CJS_Value(pRuntime, 1);
- arColor.SetElement(pRuntime, 1, vColElm);
- vColElm = CJS_Value(pRuntime, 0);
- arColor.SetElement(pRuntime, 2, vColElm);
- arColor.SetElement(pRuntime, 3, vColElm);
-
- CJS_PropValue vProp(pRuntime);
- vProp.StartGetting();
- vProp << arColor;
- vProp.StartSetting();
- fTarget->textColor(pRuntime, vProp, sError); // red
- }
- }
- } else {
- if (iNegStyle == 1 || iNegStyle == 3) {
- if (Field* fTarget = pEvent->Target_Field()) {
- CJS_Array arColor;
- CJS_Value vColElm(pRuntime);
- vColElm = CJS_Value(pRuntime, L"RGB");
- arColor.SetElement(pRuntime, 0, vColElm);
- vColElm = CJS_Value(pRuntime, 0);
- arColor.SetElement(pRuntime, 1, vColElm);
- arColor.SetElement(pRuntime, 2, vColElm);
- arColor.SetElement(pRuntime, 3, vColElm);
-
- CJS_PropValue vProp(pRuntime);
- vProp.StartGetting();
- fTarget->textColor(pRuntime, vProp, sError);
-
- CJS_Array aProp;
- vProp.GetJSValue()->ConvertToArray(pRuntime, aProp);
-
- CPWL_Color crProp;
- CPWL_Color crColor;
- color::ConvertArrayToPWLColor(pRuntime, aProp, &crProp);
- color::ConvertArrayToPWLColor(pRuntime, arColor, &crColor);
-
- if (crColor != crProp) {
- CJS_PropValue vProp2(pRuntime);
- vProp2.StartGetting();
- vProp2 << arColor;
- vProp2.StartSetting();
- fTarget->textColor(pRuntime, vProp2, sError);
- }
- }
- }
- }
-#endif
- return true;
-}
-
-// function AFNumber_Keystroke(nDec, sepStyle, negStyle, currStyle, strCurrency,
-// bCurrencyPrepend)
-bool CJS_PublicMethods::AFNumber_Keystroke(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() < 2)
- return false;
-
- CJS_EventContext* pContext = pRuntime->GetCurrentEventContext();
- CJS_EventHandler* pEvent = pContext->GetEventHandler();
- if (!pEvent->m_pValue)
- return false;
-
- CFX_WideString& val = pEvent->Value();
- CFX_WideString& wstrChange = pEvent->Change();
- CFX_WideString wstrValue = val;
-
- if (pEvent->WillCommit()) {
- CFX_WideString swTemp = StrTrim(wstrValue);
- if (swTemp.IsEmpty())
- return true;
-
- swTemp.Replace(L",", L".");
- if (!IsNumber(swTemp.c_str())) {
- pEvent->Rc() = false;
- sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE);
- AlertIfPossible(pContext, sError.c_str());
- }
- return true; // it happens after the last keystroke and before validating,
- }
-
- CFX_WideString wstrSelected;
- if (pEvent->SelStart() != -1) {
- wstrSelected = wstrValue.Mid(pEvent->SelStart(),
- pEvent->SelEnd() - pEvent->SelStart());
- }
-
- bool bHasSign = wstrValue.Find(L'-') != -1 && wstrSelected.Find(L'-') == -1;
- if (bHasSign) {
- // can't insert "change" in front to sign postion.
- if (pEvent->SelStart() == 0) {
- bool& bRc = pEvent->Rc();
- bRc = false;
- return true;
- }
- }
-
- int iSepStyle = params[1].ToInt(pRuntime);
- if (iSepStyle < 0 || iSepStyle > 3)
- iSepStyle = 0;
- const FX_WCHAR cSep = iSepStyle < 2 ? L'.' : L',';
-
- bool bHasSep = wstrValue.Find(cSep) != -1;
- for (FX_STRSIZE i = 0; i < wstrChange.GetLength(); ++i) {
- if (wstrChange[i] == cSep) {
- if (bHasSep) {
- bool& bRc = pEvent->Rc();
- bRc = false;
- return true;
- }
- bHasSep = true;
- continue;
- }
- if (wstrChange[i] == L'-') {
- if (bHasSign) {
- bool& bRc = pEvent->Rc();
- bRc = false;
- return true;
- }
- // sign's position is not correct
- if (i != 0) {
- bool& bRc = pEvent->Rc();
- bRc = false;
- return true;
- }
- if (pEvent->SelStart() != 0) {
- bool& bRc = pEvent->Rc();
- bRc = false;
- return true;
- }
- bHasSign = true;
- continue;
- }
-
- if (!FXSYS_iswdigit(wstrChange[i])) {
- bool& bRc = pEvent->Rc();
- bRc = false;
- return true;
- }
- }
-
- CFX_WideString wprefix = wstrValue.Mid(0, pEvent->SelStart());
- CFX_WideString wpostfix;
- if (pEvent->SelEnd() < wstrValue.GetLength())
- wpostfix = wstrValue.Mid(pEvent->SelEnd());
- val = wprefix + wstrChange + wpostfix;
- return true;
-}
-
-// function AFPercent_Format(nDec, sepStyle)
-bool CJS_PublicMethods::AFPercent_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
-#if _FX_OS_ != _FX_ANDROID_
- if (params.size() != 2) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
- if (!pEvent->m_pValue)
- return false;
-
- CFX_WideString& Value = pEvent->Value();
- CFX_ByteString strValue = StrTrim(CFX_ByteString::FromUnicode(Value));
- if (strValue.IsEmpty())
- return true;
-
- int iDec = params[0].ToInt(pRuntime);
- if (iDec < 0)
- iDec = -iDec;
-
- int iSepStyle = params[1].ToInt(pRuntime);
- if (iSepStyle < 0 || iSepStyle > 3)
- iSepStyle = 0;
-
- // for processing decimal places
- double dValue = atof(strValue.c_str());
- dValue *= 100;
- if (iDec > 0)
- dValue += DOUBLE_CORRECT;
-
- int iDec2;
- int iNegative = 0;
- strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
- if (strValue.IsEmpty()) {
- dValue = 0;
- strValue = fcvt(dValue, iDec, &iDec2, &iNegative);
- }
-
- if (iDec2 < 0) {
- for (int iNum = 0; iNum < abs(iDec2); iNum++) {
- strValue = "0" + strValue;
- }
- iDec2 = 0;
- }
- int iMax = strValue.GetLength();
- if (iDec2 > iMax) {
- for (int iNum = 0; iNum <= iDec2 - iMax; iNum++) {
- strValue += "0";
- }
- iMax = iDec2 + 1;
- }
-
- // for processing seperator style
- if (iDec2 < iMax) {
- if (iSepStyle == 0 || iSepStyle == 1) {
- strValue.Insert(iDec2, '.');
- iMax++;
- } else if (iSepStyle == 2 || iSepStyle == 3) {
- strValue.Insert(iDec2, ',');
- iMax++;
- }
-
- if (iDec2 == 0)
- strValue.Insert(iDec2, '0');
- }
- if (iSepStyle == 0 || iSepStyle == 2) {
- char cSeperator;
- if (iSepStyle == 0)
- cSeperator = ',';
- else
- cSeperator = '.';
-
- for (int iDecPositive = iDec2 - 3; iDecPositive > 0; iDecPositive -= 3) {
- strValue.Insert(iDecPositive, cSeperator);
- iMax++;
- }
- }
-
- // negative mark
- if (iNegative)
- strValue = "-" + strValue;
- strValue += "%";
- Value = CFX_WideString::FromLocal(strValue.AsStringC());
-#endif
- return true;
-}
-// AFPercent_Keystroke(nDec, sepStyle)
-bool CJS_PublicMethods::AFPercent_Keystroke(
- CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return AFNumber_Keystroke(pRuntime, params, vRet, sError);
-}
-
-// function AFDate_FormatEx(cFormat)
-bool CJS_PublicMethods::AFDate_FormatEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CJS_EventContext* pContext = pRuntime->GetCurrentEventContext();
- CJS_EventHandler* pEvent = pContext->GetEventHandler();
- if (!pEvent->m_pValue)
- return false;
-
- CFX_WideString& val = pEvent->Value();
- CFX_WideString strValue = val;
- if (strValue.IsEmpty())
- return true;
-
- CFX_WideString sFormat = params[0].ToCFXWideString(pRuntime);
- double dDate = 0.0f;
-
- if (strValue.Find(L"GMT") != -1) {
- // for GMT format time
- // such as "Tue Aug 11 14:24:16 GMT+08002009"
- dDate = MakeInterDate(strValue);
- } else {
- dDate = MakeRegularDate(strValue, sFormat, nullptr);
- }
-
- if (JS_PortIsNan(dDate)) {
- CFX_WideString swMsg;
- swMsg.Format(JSGetStringFromID(IDS_STRING_JSPARSEDATE).c_str(),
- sFormat.c_str());
- AlertIfPossible(pContext, swMsg.c_str());
- return false;
- }
-
- val = MakeFormatDate(dDate, sFormat);
- return true;
-}
-
-double CJS_PublicMethods::MakeInterDate(const CFX_WideString& strValue) {
- std::vector<CFX_WideString> wsArray;
- CFX_WideString sTemp = L"";
- for (int i = 0; i < strValue.GetLength(); ++i) {
- FX_WCHAR c = strValue.GetAt(i);
- if (c == L' ' || c == L':') {
- wsArray.push_back(sTemp);
- sTemp = L"";
- continue;
- }
- sTemp += c;
- }
- wsArray.push_back(sTemp);
- if (wsArray.size() != 8)
- return 0;
-
- int nMonth = 1;
- sTemp = wsArray[1];
- if (sTemp.Compare(L"Jan") == 0)
- nMonth = 1;
- else if (sTemp.Compare(L"Feb") == 0)
- nMonth = 2;
- else if (sTemp.Compare(L"Mar") == 0)
- nMonth = 3;
- else if (sTemp.Compare(L"Apr") == 0)
- nMonth = 4;
- else if (sTemp.Compare(L"May") == 0)
- nMonth = 5;
- else if (sTemp.Compare(L"Jun") == 0)
- nMonth = 6;
- else if (sTemp.Compare(L"Jul") == 0)
- nMonth = 7;
- else if (sTemp.Compare(L"Aug") == 0)
- nMonth = 8;
- else if (sTemp.Compare(L"Sep") == 0)
- nMonth = 9;
- else if (sTemp.Compare(L"Oct") == 0)
- nMonth = 10;
- else if (sTemp.Compare(L"Nov") == 0)
- nMonth = 11;
- else if (sTemp.Compare(L"Dec") == 0)
- nMonth = 12;
-
- int nDay = FX_atof(wsArray[2].AsStringC());
- int nHour = FX_atof(wsArray[3].AsStringC());
- int nMin = FX_atof(wsArray[4].AsStringC());
- int nSec = FX_atof(wsArray[5].AsStringC());
- int nYear = FX_atof(wsArray[7].AsStringC());
- double dRet = JS_MakeDate(JS_MakeDay(nYear, nMonth - 1, nDay),
- JS_MakeTime(nHour, nMin, nSec, 0));
- if (JS_PortIsNan(dRet))
- dRet = JS_DateParse(strValue);
-
- return dRet;
-}
-
-// AFDate_KeystrokeEx(cFormat)
-bool CJS_PublicMethods::AFDate_KeystrokeEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = L"AFDate_KeystrokeEx's parameters' size r not correct";
- return false;
- }
-
- CJS_EventContext* pContext = pRuntime->GetCurrentEventContext();
- CJS_EventHandler* pEvent = pContext->GetEventHandler();
- if (pEvent->WillCommit()) {
- if (!pEvent->m_pValue)
- return false;
-
- CFX_WideString strValue = pEvent->Value();
- if (strValue.IsEmpty())
- return true;
-
- CFX_WideString sFormat = params[0].ToCFXWideString(pRuntime);
- bool bWrongFormat = false;
- double dRet = MakeRegularDate(strValue, sFormat, &bWrongFormat);
- if (bWrongFormat || JS_PortIsNan(dRet)) {
- CFX_WideString swMsg;
- swMsg.Format(JSGetStringFromID(IDS_STRING_JSPARSEDATE).c_str(),
- sFormat.c_str());
- AlertIfPossible(pContext, swMsg.c_str());
- pEvent->Rc() = false;
- return true;
- }
- }
- return true;
-}
-
-bool CJS_PublicMethods::AFDate_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- int iIndex = params[0].ToInt(pRuntime);
- const FX_WCHAR* cFormats[] = {L"m/d",
- L"m/d/yy",
- L"mm/dd/yy",
- L"mm/yy",
- L"d-mmm",
- L"d-mmm-yy",
- L"dd-mmm-yy",
- L"yy-mm-dd",
- L"mmm-yy",
- L"mmmm-yy",
- L"mmm d, yyyy",
- L"mmmm d, yyyy",
- L"m/d/yy h:MM tt",
- L"m/d/yy HH:MM"};
-
- if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
- iIndex = 0;
-
- std::vector<CJS_Value> newParams;
- newParams.push_back(CJS_Value(pRuntime, cFormats[iIndex]));
- return AFDate_FormatEx(pRuntime, newParams, vRet, sError);
-}
-
-// AFDate_KeystrokeEx(cFormat)
-bool CJS_PublicMethods::AFDate_Keystroke(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- int iIndex = params[0].ToInt(pRuntime);
- const FX_WCHAR* cFormats[] = {L"m/d",
- L"m/d/yy",
- L"mm/dd/yy",
- L"mm/yy",
- L"d-mmm",
- L"d-mmm-yy",
- L"dd-mmm-yy",
- L"yy-mm-dd",
- L"mmm-yy",
- L"mmmm-yy",
- L"mmm d, yyyy",
- L"mmmm d, yyyy",
- L"m/d/yy h:MM tt",
- L"m/d/yy HH:MM"};
-
- if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
- iIndex = 0;
-
- std::vector<CJS_Value> newParams;
- newParams.push_back(CJS_Value(pRuntime, cFormats[iIndex]));
- return AFDate_KeystrokeEx(pRuntime, newParams, vRet, sError);
-}
-
-// function AFTime_Format(ptf)
-bool CJS_PublicMethods::AFTime_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- int iIndex = params[0].ToInt(pRuntime);
- const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
- L"h:MM:ss tt"};
-
- if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
- iIndex = 0;
-
- std::vector<CJS_Value> newParams;
- newParams.push_back(CJS_Value(pRuntime, cFormats[iIndex]));
- return AFDate_FormatEx(pRuntime, newParams, vRet, sError);
-}
-
-bool CJS_PublicMethods::AFTime_Keystroke(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- int iIndex = params[0].ToInt(pRuntime);
- const FX_WCHAR* cFormats[] = {L"HH:MM", L"h:MM tt", L"HH:MM:ss",
- L"h:MM:ss tt"};
-
- if (iIndex < 0 || (static_cast<size_t>(iIndex) >= FX_ArraySize(cFormats)))
- iIndex = 0;
-
- std::vector<CJS_Value> newParams;
- newParams.push_back(CJS_Value(pRuntime, cFormats[iIndex]));
- return AFDate_KeystrokeEx(pRuntime, newParams, vRet, sError);
-}
-
-bool CJS_PublicMethods::AFTime_FormatEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return AFDate_FormatEx(pRuntime, params, vRet, sError);
-}
-
-bool CJS_PublicMethods::AFTime_KeystrokeEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return AFDate_KeystrokeEx(pRuntime, params, vRet, sError);
-}
-
-// function AFSpecial_Format(psf)
-bool CJS_PublicMethods::AFSpecial_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
- if (!pEvent->m_pValue)
- return false;
-
- CFX_WideString wsSource = pEvent->Value();
- CFX_WideString wsFormat;
- switch (params[0].ToInt(pRuntime)) {
- case 0:
- wsFormat = L"99999";
- break;
- case 1:
- wsFormat = L"99999-9999";
- break;
- case 2:
- if (util::printx(L"9999999999", wsSource).GetLength() >= 10)
- wsFormat = L"(999) 999-9999";
- else
- wsFormat = L"999-9999";
- break;
- case 3:
- wsFormat = L"999-99-9999";
- break;
- }
-
- pEvent->Value() = util::printx(wsFormat, wsSource);
- return true;
-}
-
-// function AFSpecial_KeystrokeEx(mask)
-bool CJS_PublicMethods::AFSpecial_KeystrokeEx(
- CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() < 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CJS_EventContext* pContext = pRuntime->GetCurrentEventContext();
- CJS_EventHandler* pEvent = pContext->GetEventHandler();
- if (!pEvent->m_pValue)
- return false;
-
- CFX_WideString& valEvent = pEvent->Value();
- CFX_WideString wstrMask = params[0].ToCFXWideString(pRuntime);
- if (wstrMask.IsEmpty())
- return true;
-
- if (pEvent->WillCommit()) {
- if (valEvent.IsEmpty())
- return true;
-
- FX_STRSIZE iIndexMask = 0;
- for (; iIndexMask < valEvent.GetLength(); ++iIndexMask) {
- if (!maskSatisfied(valEvent[iIndexMask], wstrMask[iIndexMask]))
- break;
- }
-
- if (iIndexMask != wstrMask.GetLength() ||
- (iIndexMask != valEvent.GetLength() && wstrMask.GetLength() != 0)) {
- AlertIfPossible(
- pContext, JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE).c_str());
- pEvent->Rc() = false;
- }
- return true;
- }
-
- CFX_WideString& wideChange = pEvent->Change();
- if (wideChange.IsEmpty())
- return true;
-
- CFX_WideString wChange = wideChange;
- FX_STRSIZE iIndexMask = pEvent->SelStart();
- FX_STRSIZE combined_len = valEvent.GetLength() + wChange.GetLength() +
- pEvent->SelStart() - pEvent->SelEnd();
- if (combined_len > wstrMask.GetLength()) {
- AlertIfPossible(pContext,
- JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG).c_str());
- pEvent->Rc() = false;
- return true;
- }
-
- if (iIndexMask >= wstrMask.GetLength() && !wChange.IsEmpty()) {
- AlertIfPossible(pContext,
- JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG).c_str());
- pEvent->Rc() = false;
- return true;
- }
-
- for (FX_STRSIZE i = 0; i < wChange.GetLength(); ++i) {
- if (iIndexMask >= wstrMask.GetLength()) {
- AlertIfPossible(pContext,
- JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG).c_str());
- pEvent->Rc() = false;
- return true;
- }
- FX_WCHAR wMask = wstrMask[iIndexMask];
- if (!isReservedMaskChar(wMask))
- wChange.SetAt(i, wMask);
-
- if (!maskSatisfied(wChange[i], wMask)) {
- pEvent->Rc() = false;
- return true;
- }
- iIndexMask++;
- }
- wideChange = wChange;
- return true;
-}
-
-// function AFSpecial_Keystroke(psf)
-bool CJS_PublicMethods::AFSpecial_Keystroke(
- CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
- if (!pEvent->m_pValue)
- return false;
-
- const char* cFormat = "";
- switch (params[0].ToInt(pRuntime)) {
- case 0:
- cFormat = "99999";
- break;
- case 1:
- cFormat = "999999999";
- break;
- case 2:
- if (pEvent->Value().GetLength() + pEvent->Change().GetLength() > 7)
- cFormat = "9999999999";
- else
- cFormat = "9999999";
- break;
- case 3:
- cFormat = "999999999";
- break;
- }
-
- std::vector<CJS_Value> params2;
- params2.push_back(CJS_Value(pRuntime, cFormat));
- return AFSpecial_KeystrokeEx(pRuntime, params2, vRet, sError);
-}
-
-bool CJS_PublicMethods::AFMergeChange(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CJS_EventHandler* pEventHandler =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- CFX_WideString swValue;
- if (pEventHandler->m_pValue)
- swValue = pEventHandler->Value();
-
- if (pEventHandler->WillCommit()) {
- vRet = CJS_Value(pRuntime, swValue.c_str());
- return true;
- }
-
- CFX_WideString prefix, postfix;
-
- if (pEventHandler->SelStart() >= 0)
- prefix = swValue.Mid(0, pEventHandler->SelStart());
- else
- prefix = L"";
-
- if (pEventHandler->SelEnd() >= 0 &&
- pEventHandler->SelEnd() <= swValue.GetLength())
- postfix = swValue.Mid(pEventHandler->SelEnd(),
- swValue.GetLength() - pEventHandler->SelEnd());
- else
- postfix = L"";
-
- vRet =
- CJS_Value(pRuntime, (prefix + pEventHandler->Change() + postfix).c_str());
- return true;
-}
-
-bool CJS_PublicMethods::AFParseDateEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 2) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CFX_WideString sValue = params[0].ToCFXWideString(pRuntime);
- CFX_WideString sFormat = params[1].ToCFXWideString(pRuntime);
- double dDate = MakeRegularDate(sValue, sFormat, nullptr);
- if (JS_PortIsNan(dDate)) {
- CFX_WideString swMsg;
- swMsg.Format(JSGetStringFromID(IDS_STRING_JSPARSEDATE).c_str(),
- sFormat.c_str());
- AlertIfPossible(pRuntime->GetCurrentEventContext(), swMsg.c_str());
- return false;
- }
-
- vRet = CJS_Value(pRuntime, dDate);
- return true;
-}
-
-bool CJS_PublicMethods::AFSimple(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 3) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- vRet = CJS_Value(pRuntime, static_cast<double>(AF_Simple(
- params[0].ToCFXWideString(pRuntime).c_str(),
- params[1].ToDouble(pRuntime),
- params[2].ToDouble(pRuntime))));
-
- return true;
-}
-
-bool CJS_PublicMethods::AFMakeNumber(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CFX_WideString ws = params[0].ToCFXWideString(pRuntime);
- ws.Replace(L",", L".");
- vRet = CJS_Value(pRuntime, ws.c_str());
- vRet.MaybeCoerceToNumber(pRuntime);
- if (vRet.GetType() != CJS_Value::VT_number)
- vRet = CJS_Value(pRuntime, 0);
- return true;
-}
-
-bool CJS_PublicMethods::AFSimple_Calculate(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 2) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CJS_Value params1 = params[1];
- if (!params1.IsArrayObject() && params1.GetType() != CJS_Value::VT_string) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CPDFSDK_InterForm* pReaderInterForm =
- pRuntime->GetFormFillEnv()->GetInterForm();
- CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
-
- CFX_WideString sFunction = params[0].ToCFXWideString(pRuntime);
- double dValue = wcscmp(sFunction.c_str(), L"PRD") == 0 ? 1.0 : 0.0;
-
- CJS_Array FieldNameArray = AF_MakeArrayFromList(pRuntime, params1);
- int nFieldsCount = 0;
-
- for (int i = 0, isz = FieldNameArray.GetLength(pRuntime); i < isz; i++) {
- CJS_Value jsValue(pRuntime);
- FieldNameArray.GetElement(pRuntime, i, jsValue);
- CFX_WideString wsFieldName = jsValue.ToCFXWideString(pRuntime);
-
- for (int j = 0, jsz = pInterForm->CountFields(wsFieldName); j < jsz; j++) {
- if (CPDF_FormField* pFormField = pInterForm->GetField(j, wsFieldName)) {
- double dTemp = 0.0;
- switch (pFormField->GetFieldType()) {
- case FIELDTYPE_TEXTFIELD:
- case FIELDTYPE_COMBOBOX: {
- CFX_WideString trimmed = pFormField->GetValue();
- trimmed.TrimRight();
- trimmed.TrimLeft();
- dTemp = FX_atof(trimmed.AsStringC());
- } break;
- case FIELDTYPE_PUSHBUTTON: {
- dTemp = 0.0;
- } break;
- case FIELDTYPE_CHECKBOX:
- case FIELDTYPE_RADIOBUTTON: {
- dTemp = 0.0;
- for (int c = 0, csz = pFormField->CountControls(); c < csz; c++) {
- if (CPDF_FormControl* pFormCtrl = pFormField->GetControl(c)) {
- if (pFormCtrl->IsChecked()) {
- CFX_WideString trimmed = pFormCtrl->GetExportValue();
- trimmed.TrimRight();
- trimmed.TrimLeft();
- dTemp = FX_atof(trimmed.AsStringC());
- break;
- }
- }
- }
- } break;
- case FIELDTYPE_LISTBOX: {
- if (pFormField->CountSelectedItems() <= 1) {
- CFX_WideString trimmed = pFormField->GetValue();
- trimmed.TrimRight();
- trimmed.TrimLeft();
- dTemp = FX_atof(trimmed.AsStringC());
- }
- } break;
- default:
- break;
- }
-
- if (i == 0 && j == 0 && (wcscmp(sFunction.c_str(), L"MIN") == 0 ||
- wcscmp(sFunction.c_str(), L"MAX") == 0))
- dValue = dTemp;
-
- dValue = AF_Simple(sFunction.c_str(), dValue, dTemp);
-
- nFieldsCount++;
- }
- }
- }
-
- if (wcscmp(sFunction.c_str(), L"AVG") == 0 && nFieldsCount > 0)
- dValue /= nFieldsCount;
-
- dValue = (double)floor(dValue * FXSYS_pow((double)10, (double)6) + 0.49) /
- FXSYS_pow((double)10, (double)6);
-
- CJS_Value jsValue(pRuntime, dValue);
- CJS_EventContext* pContext = pRuntime->GetCurrentEventContext();
- if (pContext->GetEventHandler()->m_pValue)
- pContext->GetEventHandler()->Value() = jsValue.ToCFXWideString(pRuntime);
-
- return true;
-}
-
-/* This function validates the current event to ensure that its value is
-** within the specified range. */
-
-bool CJS_PublicMethods::AFRange_Validate(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 4) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- CJS_EventContext* pContext = pRuntime->GetCurrentEventContext();
- CJS_EventHandler* pEvent = pContext->GetEventHandler();
- if (!pEvent->m_pValue)
- return false;
-
- if (pEvent->Value().IsEmpty())
- return true;
-
- double dEentValue =
- atof(CFX_ByteString::FromUnicode(pEvent->Value()).c_str());
- bool bGreaterThan = params[0].ToBool(pRuntime);
- double dGreaterThan = params[1].ToDouble(pRuntime);
- bool bLessThan = params[2].ToBool(pRuntime);
- double dLessThan = params[3].ToDouble(pRuntime);
- CFX_WideString swMsg;
-
- if (bGreaterThan && bLessThan) {
- if (dEentValue < dGreaterThan || dEentValue > dLessThan)
- swMsg.Format(JSGetStringFromID(IDS_STRING_JSRANGE1).c_str(),
- params[1].ToCFXWideString(pRuntime).c_str(),
- params[3].ToCFXWideString(pRuntime).c_str());
- } else if (bGreaterThan) {
- if (dEentValue < dGreaterThan)
- swMsg.Format(JSGetStringFromID(IDS_STRING_JSRANGE2).c_str(),
- params[1].ToCFXWideString(pRuntime).c_str());
- } else if (bLessThan) {
- if (dEentValue > dLessThan)
- swMsg.Format(JSGetStringFromID(IDS_STRING_JSRANGE3).c_str(),
- params[3].ToCFXWideString(pRuntime).c_str());
- }
-
- if (!swMsg.IsEmpty()) {
- AlertIfPossible(pContext, swMsg.c_str());
- pEvent->Rc() = false;
- }
- return true;
-}
-
-bool CJS_PublicMethods::AFExtractNums(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CFX_WideString str = params[0].ToCFXWideString(pRuntime);
- if (str.GetAt(0) == L'.' || str.GetAt(0) == L',')
- str = L"0" + str;
-
- CFX_WideString sPart;
- CJS_Array nums;
- int nIndex = 0;
- for (int i = 0, sz = str.GetLength(); i < sz; i++) {
- FX_WCHAR wc = str.GetAt(i);
- if (FXSYS_iswdigit(wc)) {
- sPart += wc;
- } else {
- if (sPart.GetLength() > 0) {
- nums.SetElement(pRuntime, nIndex, CJS_Value(pRuntime, sPart.c_str()));
- sPart = L"";
- nIndex++;
- }
- }
- }
-
- if (sPart.GetLength() > 0) {
- nums.SetElement(pRuntime, nIndex, CJS_Value(pRuntime, sPart.c_str()));
- }
-
- if (nums.GetLength(pRuntime) > 0)
- vRet = CJS_Value(pRuntime, nums);
- else
- vRet.SetNull(pRuntime);
-
- return true;
-}
diff --git a/fpdfsdk/javascript/PublicMethods.h b/fpdfsdk/javascript/PublicMethods.h
deleted file mode 100644
index 060c743..0000000
--- a/fpdfsdk/javascript/PublicMethods.h
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_PUBLICMETHODS_H_
-#define FPDFSDK_JAVASCRIPT_PUBLICMETHODS_H_
-
-#include <string>
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class CJS_PublicMethods : public CJS_Object {
- public:
- explicit CJS_PublicMethods(v8::Local<v8::Object> pObject)
- : CJS_Object(pObject) {}
- ~CJS_PublicMethods() override {}
-
- static bool AFNumber_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFNumber_Keystroke(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFPercent_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFPercent_Keystroke(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFDate_FormatEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFDate_KeystrokeEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFDate_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFDate_Keystroke(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFTime_FormatEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError); //
- static bool AFTime_KeystrokeEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFTime_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFTime_Keystroke(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFSpecial_Format(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFSpecial_Keystroke(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFSpecial_KeystrokeEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError); //
- static bool AFSimple(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFMakeNumber(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFSimple_Calculate(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFRange_Validate(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFMergeChange(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFParseDateEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- static bool AFExtractNums(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
-
- JS_STATIC_GLOBAL_FUN(AFNumber_Format);
- JS_STATIC_GLOBAL_FUN(AFNumber_Keystroke);
- JS_STATIC_GLOBAL_FUN(AFPercent_Format);
- JS_STATIC_GLOBAL_FUN(AFPercent_Keystroke);
- JS_STATIC_GLOBAL_FUN(AFDate_FormatEx);
- JS_STATIC_GLOBAL_FUN(AFDate_KeystrokeEx);
- JS_STATIC_GLOBAL_FUN(AFDate_Format);
- JS_STATIC_GLOBAL_FUN(AFDate_Keystroke);
- JS_STATIC_GLOBAL_FUN(AFTime_FormatEx);
- JS_STATIC_GLOBAL_FUN(AFTime_KeystrokeEx);
- JS_STATIC_GLOBAL_FUN(AFTime_Format);
- JS_STATIC_GLOBAL_FUN(AFTime_Keystroke);
- JS_STATIC_GLOBAL_FUN(AFSpecial_Format);
- JS_STATIC_GLOBAL_FUN(AFSpecial_Keystroke);
- JS_STATIC_GLOBAL_FUN(AFSpecial_KeystrokeEx);
- JS_STATIC_GLOBAL_FUN(AFSimple);
- JS_STATIC_GLOBAL_FUN(AFMakeNumber);
- JS_STATIC_GLOBAL_FUN(AFSimple_Calculate);
- JS_STATIC_GLOBAL_FUN(AFRange_Validate);
- JS_STATIC_GLOBAL_FUN(AFMergeChange);
- JS_STATIC_GLOBAL_FUN(AFParseDateEx);
- JS_STATIC_GLOBAL_FUN(AFExtractNums);
-
- JS_STATIC_DECLARE_GLOBAL_FUN();
-
- static int ParseStringInteger(const CFX_WideString& string,
- int nStart,
- int& nSkip,
- int nMaxStep);
- static CFX_WideString ParseStringString(const CFX_WideString& string,
- int nStart,
- int& nSkip);
- static double MakeRegularDate(const CFX_WideString& value,
- const CFX_WideString& format,
- bool* bWrongFormat);
- static CFX_WideString MakeFormatDate(double dDate,
- const CFX_WideString& format);
- static double ParseNormalDate(const CFX_WideString& value,
- bool* bWrongFormat);
- static double MakeInterDate(const CFX_WideString& value);
-
- static bool IsNumber(const CFX_WideString& str);
-
- static bool maskSatisfied(wchar_t c_Change, wchar_t c_Mask);
- static bool isReservedMaskChar(wchar_t ch);
-
- static double AF_Simple(const FX_WCHAR* sFuction,
- double dValue1,
- double dValue2);
- static CJS_Array AF_MakeArrayFromList(CJS_Runtime* pRuntime, CJS_Value val);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_PUBLICMETHODS_H_
diff --git a/fpdfsdk/javascript/app.cpp b/fpdfsdk/javascript/app.cpp
deleted file mode 100644
index 3a8bf08..0000000
--- a/fpdfsdk/javascript/app.cpp
+++ /dev/null
@@ -1,790 +0,0 @@
-// Copyright 2014 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/javascript/app.h"
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/cpdfsdk_interform.h"
-#include "fpdfsdk/javascript/Document.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fpdfsdk/javascript/resource.h"
-#include "third_party/base/stl_util.h"
-
-class GlobalTimer {
- public:
- GlobalTimer(app* pObj,
- CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CJS_Runtime* pRuntime,
- int nType,
- const CFX_WideString& script,
- uint32_t dwElapse,
- uint32_t dwTimeOut);
- ~GlobalTimer();
-
- static void Trigger(int nTimerID);
- static void Cancel(int nTimerID);
-
- bool IsOneShot() const { return m_nType == 1; }
- uint32_t GetTimeOut() const { return m_dwTimeOut; }
- int GetTimerID() const { return m_nTimerID; }
- CJS_Runtime* GetRuntime() const { return m_pRuntime.Get(); }
- CFX_WideString GetJScript() const { return m_swJScript; }
-
- private:
- using TimerMap = std::map<uint32_t, GlobalTimer*>;
- static TimerMap* GetGlobalTimerMap();
-
- uint32_t m_nTimerID;
- app* const m_pEmbedObj;
- bool m_bProcessing;
-
- // data
- const int m_nType; // 0:Interval; 1:TimeOut
- const uint32_t m_dwTimeOut;
- const CFX_WideString m_swJScript;
- CJS_Runtime::ObservedPtr m_pRuntime;
- CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
-};
-
-GlobalTimer::GlobalTimer(app* pObj,
- CPDFSDK_FormFillEnvironment* pFormFillEnv,
- CJS_Runtime* pRuntime,
- int nType,
- const CFX_WideString& script,
- uint32_t dwElapse,
- uint32_t dwTimeOut)
- : m_nTimerID(0),
- m_pEmbedObj(pObj),
- m_bProcessing(false),
- m_nType(nType),
- m_dwTimeOut(dwTimeOut),
- m_swJScript(script),
- m_pRuntime(pRuntime),
- m_pFormFillEnv(pFormFillEnv) {
- CFX_SystemHandler* pHandler = m_pFormFillEnv->GetSysHandler();
- m_nTimerID = pHandler->SetTimer(dwElapse, Trigger);
- if (m_nTimerID)
- (*GetGlobalTimerMap())[m_nTimerID] = this;
-}
-
-GlobalTimer::~GlobalTimer() {
- if (!m_nTimerID)
- return;
-
- if (GetRuntime())
- m_pFormFillEnv->GetSysHandler()->KillTimer(m_nTimerID);
-
- GetGlobalTimerMap()->erase(m_nTimerID);
-}
-
-// static
-void GlobalTimer::Trigger(int nTimerID) {
- auto it = GetGlobalTimerMap()->find(nTimerID);
- if (it == GetGlobalTimerMap()->end())
- return;
-
- GlobalTimer* pTimer = it->second;
- if (pTimer->m_bProcessing)
- return;
-
- pTimer->m_bProcessing = true;
- if (pTimer->m_pEmbedObj)
- pTimer->m_pEmbedObj->TimerProc(pTimer);
-
- // Timer proc may have destroyed timer, find it again.
- it = GetGlobalTimerMap()->find(nTimerID);
- if (it == GetGlobalTimerMap()->end())
- return;
-
- pTimer = it->second;
- pTimer->m_bProcessing = false;
- if (pTimer->IsOneShot())
- pTimer->m_pEmbedObj->CancelProc(pTimer);
-}
-
-// static
-void GlobalTimer::Cancel(int nTimerID) {
- auto it = GetGlobalTimerMap()->find(nTimerID);
- if (it == GetGlobalTimerMap()->end())
- return;
-
- GlobalTimer* pTimer = it->second;
- pTimer->m_pEmbedObj->CancelProc(pTimer);
-}
-
-// static
-GlobalTimer::TimerMap* GlobalTimer::GetGlobalTimerMap() {
- // Leak the timer array at shutdown.
- static auto* s_TimerMap = new TimerMap;
- return s_TimerMap;
-}
-
-JSConstSpec CJS_TimerObj::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_TimerObj::PropertySpecs[] = {{0, 0, 0}};
-
-JSMethodSpec CJS_TimerObj::MethodSpecs[] = {{0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_TimerObj, TimerObj)
-
-TimerObj::TimerObj(CJS_Object* pJSObject)
- : CJS_EmbedObj(pJSObject), m_nTimerID(0) {}
-
-TimerObj::~TimerObj() {}
-
-void TimerObj::SetTimer(GlobalTimer* pTimer) {
- m_nTimerID = pTimer->GetTimerID();
-}
-
-#define JS_STR_VIEWERTYPE L"pdfium"
-#define JS_STR_VIEWERVARIATION L"Full"
-#define JS_STR_PLATFORM L"WIN"
-#define JS_STR_LANGUAGE L"ENU"
-#define JS_NUM_VIEWERVERSION 8
-#ifdef PDF_ENABLE_XFA
-#define JS_NUM_VIEWERVERSION_XFA 11
-#endif // PDF_ENABLE_XFA
-#define JS_NUM_FORMSVERSION 7
-
-JSConstSpec CJS_App::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_App::PropertySpecs[] = {
- {"activeDocs", get_activeDocs_static, set_activeDocs_static},
- {"calculate", get_calculate_static, set_calculate_static},
- {"formsVersion", get_formsVersion_static, set_formsVersion_static},
- {"fs", get_fs_static, set_fs_static},
- {"fullscreen", get_fullscreen_static, set_fullscreen_static},
- {"language", get_language_static, set_language_static},
- {"media", get_media_static, set_media_static},
- {"platform", get_platform_static, set_platform_static},
- {"runtimeHighlight", get_runtimeHighlight_static,
- set_runtimeHighlight_static},
- {"viewerType", get_viewerType_static, set_viewerType_static},
- {"viewerVariation", get_viewerVariation_static, set_viewerVariation_static},
- {"viewerVersion", get_viewerVersion_static, set_viewerVersion_static},
- {0, 0, 0}};
-
-JSMethodSpec CJS_App::MethodSpecs[] = {{"alert", alert_static},
- {"beep", beep_static},
- {"browseForDoc", browseForDoc_static},
- {"clearInterval", clearInterval_static},
- {"clearTimeOut", clearTimeOut_static},
- {"execDialog", execDialog_static},
- {"execMenuItem", execMenuItem_static},
- {"findComponent", findComponent_static},
- {"goBack", goBack_static},
- {"goForward", goForward_static},
- {"launchURL", launchURL_static},
- {"mailMsg", mailMsg_static},
- {"newFDF", newFDF_static},
- {"newDoc", newDoc_static},
- {"openDoc", openDoc_static},
- {"openFDF", openFDF_static},
- {"popUpMenuEx", popUpMenuEx_static},
- {"popUpMenu", popUpMenu_static},
- {"response", response_static},
- {"setInterval", setInterval_static},
- {"setTimeOut", setTimeOut_static},
- {0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_App, app)
-
-app::app(CJS_Object* pJSObject)
- : CJS_EmbedObj(pJSObject), m_bCalculate(true), m_bRuntimeHighLight(false) {}
-
-app::~app() {
-}
-
-bool app::activeDocs(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_Document* pJSDocument = nullptr;
- v8::Local<v8::Object> pObj = pRuntime->GetThisObj();
- if (CFXJS_Engine::GetObjDefnID(pObj) == CJS_Document::g_nObjDefnID)
- pJSDocument = static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pObj));
-
- CJS_Array aDocs;
- aDocs.SetElement(pRuntime, 0, CJS_Value(pRuntime, pJSDocument));
- if (aDocs.GetLength(pRuntime) > 0)
- vp << aDocs;
- else
- vp.GetJSValue()->SetNull(pRuntime);
-
- return true;
-}
-
-bool app::calculate(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- bool bVP;
- vp >> bVP;
- m_bCalculate = (bool)bVP;
- pRuntime->GetFormFillEnv()->GetInterForm()->EnableCalculate(
- (bool)m_bCalculate);
- } else {
- vp << (bool)m_bCalculate;
- }
- return true;
-}
-
-bool app::formsVersion(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsGetting()) {
- vp << JS_NUM_FORMSVERSION;
- return true;
- }
-
- return false;
-}
-
-bool app::viewerType(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsGetting()) {
- vp << JS_STR_VIEWERTYPE;
- return true;
- }
-
- return false;
-}
-
-bool app::viewerVariation(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsGetting()) {
- vp << JS_STR_VIEWERVARIATION;
- return true;
- }
-
- return false;
-}
-
-bool app::viewerVersion(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-#ifdef PDF_ENABLE_XFA
- CPDFXFA_Context* pXFAContext = pRuntime->GetFormFillEnv()->GetXFAContext();
- if (pXFAContext->GetDocType() == 1 || pXFAContext->GetDocType() == 2) {
- vp << JS_NUM_VIEWERVERSION_XFA;
- return true;
- }
-#endif // PDF_ENABLE_XFA
- vp << JS_NUM_VIEWERVERSION;
- return true;
-}
-
-bool app::platform(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-#ifdef PDF_ENABLE_XFA
- CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
- if (!pFormFillEnv)
- return false;
- CFX_WideString platfrom = pFormFillEnv->GetPlatform();
- if (!platfrom.IsEmpty()) {
- vp << platfrom;
- return true;
- }
-#endif
- vp << JS_STR_PLATFORM;
- return true;
-}
-
-bool app::language(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-#ifdef PDF_ENABLE_XFA
- CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
- if (!pFormFillEnv)
- return false;
- CFX_WideString language = pFormFillEnv->GetLanguage();
- if (!language.IsEmpty()) {
- vp << language;
- return true;
- }
-#endif
- vp << JS_STR_LANGUAGE;
- return true;
-}
-
-// creates a new fdf object that contains no data
-// comment: need reader support
-// note:
-// CFDF_Document * CPDFSDK_FormFillEnvironment::NewFDF();
-bool app::newFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-// opens a specified pdf document and returns its document object
-// comment:need reader support
-// note: as defined in js reference, the proto of this function's fourth
-// parmeters, how old an fdf document while do not show it.
-// CFDF_Document * CPDFSDK_FormFillEnvironment::OpenFDF(string strPath,bool
-// bUserConv);
-
-bool app::openFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool app::alert(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- std::vector<CJS_Value> newParams = JS_ExpandKeywordParams(
- pRuntime, params, 4, L"cMsg", L"nIcon", L"nType", L"cTitle");
-
- if (newParams[0].GetType() == CJS_Value::VT_unknown) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CPDFSDK_FormFillEnvironment* pFormFillEnv = pRuntime->GetFormFillEnv();
- if (!pFormFillEnv) {
- vRet = CJS_Value(pRuntime, 0);
- return true;
- }
-
- CFX_WideString swMsg;
- if (newParams[0].GetType() == CJS_Value::VT_object) {
- CJS_Array carray;
- if (newParams[0].ConvertToArray(pRuntime, carray)) {
- swMsg = L"[";
- CJS_Value element(pRuntime);
- for (int i = 0; i < carray.GetLength(pRuntime); ++i) {
- if (i)
- swMsg += L", ";
- carray.GetElement(pRuntime, i, element);
- swMsg += element.ToCFXWideString(pRuntime);
- }
- swMsg += L"]";
- } else {
- swMsg = newParams[0].ToCFXWideString(pRuntime);
- }
- } else {
- swMsg = newParams[0].ToCFXWideString(pRuntime);
- }
-
- int iIcon = 0;
- if (newParams[1].GetType() != CJS_Value::VT_unknown)
- iIcon = newParams[1].ToInt(pRuntime);
-
- int iType = 0;
- if (newParams[2].GetType() != CJS_Value::VT_unknown)
- iType = newParams[2].ToInt(pRuntime);
-
- CFX_WideString swTitle;
- if (newParams[3].GetType() != CJS_Value::VT_unknown)
- swTitle = newParams[3].ToCFXWideString(pRuntime);
- else
- swTitle = JSGetStringFromID(IDS_STRING_JSALERT);
-
- pRuntime->BeginBlock();
- pFormFillEnv->KillFocusAnnot(0);
-
- vRet = CJS_Value(pRuntime, pFormFillEnv->JS_appAlert(
- swMsg.c_str(), swTitle.c_str(), iType, iIcon));
- pRuntime->EndBlock();
- return true;
-}
-
-bool app::beep(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() == 1) {
- pRuntime->GetFormFillEnv()->JS_appBeep(params[0].ToInt(pRuntime));
- return true;
- }
-
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
-}
-
-bool app::findComponent(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool app::popUpMenuEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool app::fs(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError) {
- return false;
-}
-
-bool app::setInterval(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() > 2 || params.size() == 0) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CFX_WideString script =
- params.size() > 0 ? params[0].ToCFXWideString(pRuntime) : L"";
- if (script.IsEmpty()) {
- sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE);
- return true;
- }
-
- uint32_t dwInterval = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000;
-
- GlobalTimer* timerRef = new GlobalTimer(this, pRuntime->GetFormFillEnv(),
- pRuntime, 0, script, dwInterval, 0);
- m_Timers.insert(std::unique_ptr<GlobalTimer>(timerRef));
-
- v8::Local<v8::Object> pRetObj =
- pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID);
- if (pRetObj.IsEmpty())
- return false;
-
- CJS_TimerObj* pJS_TimerObj =
- static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj));
- TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject());
- pTimerObj->SetTimer(timerRef);
-
- vRet = CJS_Value(pRuntime, pRetObj);
- return true;
-}
-
-bool app::setTimeOut(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() > 2 || params.size() == 0) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- CFX_WideString script = params[0].ToCFXWideString(pRuntime);
- if (script.IsEmpty()) {
- sError = JSGetStringFromID(IDS_STRING_JSAFNUMBER_KEYSTROKE);
- return true;
- }
-
- uint32_t dwTimeOut = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000;
- GlobalTimer* timerRef =
- new GlobalTimer(this, pRuntime->GetFormFillEnv(), pRuntime, 1, script,
- dwTimeOut, dwTimeOut);
- m_Timers.insert(std::unique_ptr<GlobalTimer>(timerRef));
-
- v8::Local<v8::Object> pRetObj =
- pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID);
- if (pRetObj.IsEmpty())
- return false;
-
- CJS_TimerObj* pJS_TimerObj =
- static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj));
- TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject());
- pTimerObj->SetTimer(timerRef);
- vRet = CJS_Value(pRuntime, pRetObj);
- return true;
-}
-
-bool app::clearTimeOut(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- app::ClearTimerCommon(pRuntime, params[0]);
- return true;
-}
-
-bool app::clearInterval(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- app::ClearTimerCommon(pRuntime, params[0]);
- return true;
-}
-
-void app::ClearTimerCommon(CJS_Runtime* pRuntime, const CJS_Value& param) {
- if (param.GetType() != CJS_Value::VT_object)
- return;
-
- v8::Local<v8::Object> pObj = param.ToV8Object(pRuntime);
- if (CFXJS_Engine::GetObjDefnID(pObj) != CJS_TimerObj::g_nObjDefnID)
- return;
-
- CJS_Object* pJSObj = param.ToCJSObject(pRuntime);
- if (!pJSObj)
- return;
-
- TimerObj* pTimerObj = static_cast<TimerObj*>(pJSObj->GetEmbedObject());
- if (!pTimerObj)
- return;
-
- GlobalTimer::Cancel(pTimerObj->GetTimerID());
-}
-
-bool app::execMenuItem(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-void app::TimerProc(GlobalTimer* pTimer) {
- CJS_Runtime* pRuntime = pTimer->GetRuntime();
- if (pRuntime && (!pTimer->IsOneShot() || pTimer->GetTimeOut() > 0))
- RunJsScript(pRuntime, pTimer->GetJScript());
-}
-
-void app::CancelProc(GlobalTimer* pTimer) {
- m_Timers.erase(pdfium::FakeUniquePtr<GlobalTimer>(pTimer));
-}
-
-void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) {
- if (!pRuntime->IsBlocking()) {
- IJS_EventContext* pContext = pRuntime->NewEventContext();
- pContext->OnExternal_Exec();
- CFX_WideString wtInfo;
- pContext->RunScript(wsScript, &wtInfo);
- pRuntime->ReleaseEventContext(pContext);
- }
-}
-
-bool app::goBack(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Not supported.
- return true;
-}
-
-bool app::goForward(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Not supported.
- return true;
-}
-
-bool app::mailMsg(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- std::vector<CJS_Value> newParams =
- JS_ExpandKeywordParams(pRuntime, params, 6, L"bUI", L"cTo", L"cCc",
- L"cBcc", L"cSubject", L"cMsg");
-
- if (newParams[0].GetType() == CJS_Value::VT_unknown) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- bool bUI = newParams[0].ToBool(pRuntime);
-
- CFX_WideString cTo;
- if (newParams[1].GetType() != CJS_Value::VT_unknown) {
- cTo = newParams[1].ToCFXWideString(pRuntime);
- } else {
- if (!bUI) {
- // cTo parameter required when UI not invoked.
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- }
-
- CFX_WideString cCc;
- if (newParams[2].GetType() != CJS_Value::VT_unknown)
- cCc = newParams[2].ToCFXWideString(pRuntime);
-
- CFX_WideString cBcc;
- if (newParams[3].GetType() != CJS_Value::VT_unknown)
- cBcc = newParams[3].ToCFXWideString(pRuntime);
-
- CFX_WideString cSubject;
- if (newParams[4].GetType() != CJS_Value::VT_unknown)
- cSubject = newParams[4].ToCFXWideString(pRuntime);
-
- CFX_WideString cMsg;
- if (newParams[5].GetType() != CJS_Value::VT_unknown)
- cMsg = newParams[5].ToCFXWideString(pRuntime);
-
- pRuntime->BeginBlock();
- pRuntime->GetFormFillEnv()->JS_docmailForm(nullptr, 0, bUI, cTo.c_str(),
- cSubject.c_str(), cCc.c_str(),
- cBcc.c_str(), cMsg.c_str());
- pRuntime->EndBlock();
- return true;
-}
-
-bool app::launchURL(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool app::runtimeHighlight(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- vp >> m_bRuntimeHighLight;
- } else {
- vp << m_bRuntimeHighLight;
- }
- return true;
-}
-
-bool app::fullscreen(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return false;
-}
-
-bool app::popUpMenu(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool app::browseForDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-CFX_WideString app::SysPathToPDFPath(const CFX_WideString& sOldPath) {
- CFX_WideString sRet = L"/";
-
- for (int i = 0, sz = sOldPath.GetLength(); i < sz; i++) {
- wchar_t c = sOldPath.GetAt(i);
- if (c == L':') {
- } else {
- if (c == L'\\') {
- sRet += L"/";
- } else {
- sRet += c;
- }
- }
- }
-
- return sRet;
-}
-
-bool app::newDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool app::openDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return false;
-}
-
-bool app::response(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- std::vector<CJS_Value> newParams =
- JS_ExpandKeywordParams(pRuntime, params, 5, L"cQuestion", L"cTitle",
- L"cDefault", L"bPassword", L"cLabel");
-
- if (newParams[0].GetType() == CJS_Value::VT_unknown) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
- CFX_WideString swQuestion = newParams[0].ToCFXWideString(pRuntime);
-
- CFX_WideString swTitle = L"PDF";
- if (newParams[1].GetType() != CJS_Value::VT_unknown)
- swTitle = newParams[1].ToCFXWideString(pRuntime);
-
- CFX_WideString swDefault;
- if (newParams[2].GetType() != CJS_Value::VT_unknown)
- swDefault = newParams[2].ToCFXWideString(pRuntime);
-
- bool bPassword = false;
- if (newParams[3].GetType() != CJS_Value::VT_unknown)
- bPassword = newParams[3].ToBool(pRuntime);
-
- CFX_WideString swLabel;
- if (newParams[4].GetType() != CJS_Value::VT_unknown)
- swLabel = newParams[4].ToCFXWideString(pRuntime);
-
- const int MAX_INPUT_BYTES = 2048;
- std::unique_ptr<char[]> pBuff(new char[MAX_INPUT_BYTES + 2]);
- memset(pBuff.get(), 0, MAX_INPUT_BYTES + 2);
-
- int nLengthBytes = pRuntime->GetFormFillEnv()->JS_appResponse(
- swQuestion.c_str(), swTitle.c_str(), swDefault.c_str(), swLabel.c_str(),
- bPassword, pBuff.get(), MAX_INPUT_BYTES);
-
- if (nLengthBytes < 0 || nLengthBytes > MAX_INPUT_BYTES) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAM_TOOLONG);
- return false;
- }
-
- vRet = CJS_Value(pRuntime, CFX_WideString::FromUTF16LE(
- reinterpret_cast<uint16_t*>(pBuff.get()),
- nLengthBytes / sizeof(uint16_t))
- .c_str());
-
- return true;
-}
-
-bool app::media(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return false;
-}
-
-bool app::execDialog(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
diff --git a/fpdfsdk/javascript/app.h b/fpdfsdk/javascript/app.h
deleted file mode 100644
index 9e11b82..0000000
--- a/fpdfsdk/javascript/app.h
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_APP_H_
-#define FPDFSDK_JAVASCRIPT_APP_H_
-
-#include <memory>
-#include <unordered_set>
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class CJS_Runtime;
-class GlobalTimer;
-
-class TimerObj : public CJS_EmbedObj {
- public:
- explicit TimerObj(CJS_Object* pJSObject);
- ~TimerObj() override;
-
- void SetTimer(GlobalTimer* pTimer);
- int GetTimerID() const { return m_nTimerID; }
-
- private:
- int m_nTimerID; // Weak reference to GlobalTimer through global map.
-};
-
-class CJS_TimerObj : public CJS_Object {
- public:
- explicit CJS_TimerObj(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_TimerObj() override {}
-
- DECLARE_JS_CLASS();
-};
-
-class app : public CJS_EmbedObj {
- public:
- explicit app(CJS_Object* pJSObject);
- ~app() override;
-
- bool activeDocs(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool calculate(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool formsVersion(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool fs(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool fullscreen(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool language(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool media(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool platform(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool runtimeHighlight(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool viewerType(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool viewerVariation(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool viewerVersion(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
-
- bool alert(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool beep(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool browseForDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool clearInterval(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool clearTimeOut(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool execDialog(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool execMenuItem(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool findComponent(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool goBack(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool goForward(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool launchURL(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool mailMsg(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool newFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool newDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool openDoc(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool openFDF(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool popUpMenuEx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool popUpMenu(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool response(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool setInterval(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool setTimeOut(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
-
- void TimerProc(GlobalTimer* pTimer);
- void CancelProc(GlobalTimer* pTimer);
-
- static CFX_WideString SysPathToPDFPath(const CFX_WideString& sOldPath);
-
- private:
- // CJS_EmbedObj
- void RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript);
-
- void ClearTimerCommon(CJS_Runtime* pRuntime, const CJS_Value& param);
-
- bool m_bCalculate;
- bool m_bRuntimeHighLight;
- std::unordered_set<std::unique_ptr<GlobalTimer>> m_Timers;
-};
-
-class CJS_App : public CJS_Object {
- public:
- explicit CJS_App(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_App() override {}
-
- DECLARE_JS_CLASS();
-
- JS_STATIC_PROP(activeDocs, app);
- JS_STATIC_PROP(calculate, app);
- JS_STATIC_PROP(formsVersion, app);
- JS_STATIC_PROP(fs, app);
- JS_STATIC_PROP(fullscreen, app);
- JS_STATIC_PROP(language, app);
- JS_STATIC_PROP(media, app);
- JS_STATIC_PROP(platform, app);
- JS_STATIC_PROP(runtimeHighlight, app);
- JS_STATIC_PROP(viewerType, app);
- JS_STATIC_PROP(viewerVariation, app);
- JS_STATIC_PROP(viewerVersion, app);
-
- JS_STATIC_METHOD(alert, app);
- JS_STATIC_METHOD(beep, app);
- JS_STATIC_METHOD(browseForDoc, app);
- JS_STATIC_METHOD(clearInterval, app);
- JS_STATIC_METHOD(clearTimeOut, app);
- JS_STATIC_METHOD(execDialog, app);
- JS_STATIC_METHOD(execMenuItem, app);
- JS_STATIC_METHOD(findComponent, app);
- JS_STATIC_METHOD(goBack, app);
- JS_STATIC_METHOD(goForward, app);
- JS_STATIC_METHOD(launchURL, app);
- JS_STATIC_METHOD(mailMsg, app);
- JS_STATIC_METHOD(newFDF, app);
- JS_STATIC_METHOD(newDoc, app);
- JS_STATIC_METHOD(openDoc, app);
- JS_STATIC_METHOD(openFDF, app);
- JS_STATIC_METHOD(popUpMenuEx, app);
- JS_STATIC_METHOD(popUpMenu, app);
- JS_STATIC_METHOD(response, app);
- JS_STATIC_METHOD(setInterval, app);
- JS_STATIC_METHOD(setTimeOut, app);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_APP_H_
diff --git a/fpdfsdk/javascript/cjs_event_context.cpp b/fpdfsdk/javascript/cjs_event_context.cpp
deleted file mode 100644
index abfb6da..0000000
--- a/fpdfsdk/javascript/cjs_event_context.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-// 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/javascript/cjs_event_context.h"
-
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fpdfsdk/javascript/resource.h"
-
-CJS_EventContext::CJS_EventContext(CJS_Runtime* pRuntime)
- : m_pRuntime(pRuntime),
- m_pEventHandler(new CJS_EventHandler(this)),
- m_bBusy(false) {
- ASSERT(pRuntime);
-}
-
-CJS_EventContext::~CJS_EventContext() {}
-
-CPDFSDK_FormFillEnvironment* CJS_EventContext::GetFormFillEnv() {
- return m_pRuntime->GetFormFillEnv();
-}
-
-bool CJS_EventContext::RunScript(const CFX_WideString& script,
- CFX_WideString* info) {
- v8::Isolate::Scope isolate_scope(m_pRuntime->GetIsolate());
- v8::HandleScope handle_scope(m_pRuntime->GetIsolate());
- v8::Local<v8::Context> context = m_pRuntime->NewLocalContext();
- v8::Context::Scope context_scope(context);
-
- if (m_bBusy) {
- *info = JSGetStringFromID(IDS_STRING_JSBUSY);
- return false;
- }
-
- CFX_AutoRestorer<bool> restorer(&m_bBusy);
- m_bBusy = true;
-
- ASSERT(m_pEventHandler->IsValid());
- CJS_Runtime::FieldEvent event(m_pEventHandler->TargetName(),
- m_pEventHandler->EventType());
- if (!m_pRuntime->AddEventToSet(event)) {
- *info = JSGetStringFromID(IDS_STRING_JSEVENT);
- return false;
- }
-
- CFX_WideString sErrorMessage;
- int nRet = 0;
- if (script.GetLength() > 0)
- nRet = m_pRuntime->ExecuteScript(script.c_str(), &sErrorMessage);
-
- if (nRet < 0)
- *info += sErrorMessage;
- else
- *info = JSGetStringFromID(IDS_STRING_RUN);
-
- m_pRuntime->RemoveEventFromSet(event);
- m_pEventHandler->Destroy();
- return nRet >= 0;
-}
-
-void CJS_EventContext::OnApp_Init() {
- m_pEventHandler->OnApp_Init();
-}
-
-void CJS_EventContext::OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName) {
- m_pEventHandler->OnDoc_Open(pFormFillEnv, strTargetName);
-}
-
-void CJS_EventContext::OnDoc_WillPrint(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnDoc_WillPrint(pFormFillEnv);
-}
-
-void CJS_EventContext::OnDoc_DidPrint(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnDoc_DidPrint(pFormFillEnv);
-}
-
-void CJS_EventContext::OnDoc_WillSave(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnDoc_WillSave(pFormFillEnv);
-}
-
-void CJS_EventContext::OnDoc_DidSave(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnDoc_DidSave(pFormFillEnv);
-}
-
-void CJS_EventContext::OnDoc_WillClose(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnDoc_WillClose(pFormFillEnv);
-}
-
-void CJS_EventContext::OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnPage_Open(pFormFillEnv);
-}
-
-void CJS_EventContext::OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnPage_Close(pFormFillEnv);
-}
-
-void CJS_EventContext::OnPage_InView(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnPage_InView(pFormFillEnv);
-}
-
-void CJS_EventContext::OnPage_OutView(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnPage_OutView(pFormFillEnv);
-}
-
-void CJS_EventContext::OnField_MouseDown(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) {
- m_pEventHandler->OnField_MouseDown(bModifier, bShift, pTarget);
-}
-
-void CJS_EventContext::OnField_MouseEnter(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) {
- m_pEventHandler->OnField_MouseEnter(bModifier, bShift, pTarget);
-}
-
-void CJS_EventContext::OnField_MouseExit(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) {
- m_pEventHandler->OnField_MouseExit(bModifier, bShift, pTarget);
-}
-
-void CJS_EventContext::OnField_MouseUp(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) {
- m_pEventHandler->OnField_MouseUp(bModifier, bShift, pTarget);
-}
-
-void CJS_EventContext::OnField_Focus(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) {
- m_pEventHandler->OnField_Focus(bModifier, bShift, pTarget, Value);
-}
-
-void CJS_EventContext::OnField_Blur(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) {
- m_pEventHandler->OnField_Blur(bModifier, bShift, pTarget, Value);
-}
-
-void CJS_EventContext::OnField_Calculate(CPDF_FormField* pSource,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) {
- m_pEventHandler->OnField_Calculate(pSource, pTarget, Value, bRc);
-}
-
-void CJS_EventContext::OnField_Format(CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit) {
- m_pEventHandler->OnField_Format(pTarget, Value, bWillCommit);
-}
-
-void CJS_EventContext::OnField_Keystroke(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool bKeyDown,
- bool bModifier,
- int& nSelEnd,
- int& nSelStart,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit,
- bool bFieldFull,
- bool& bRc) {
- m_pEventHandler->OnField_Keystroke(
- strChange, strChangeEx, bKeyDown, bModifier, nSelEnd, nSelStart, bShift,
- pTarget, Value, bWillCommit, bFieldFull, bRc);
-}
-
-void CJS_EventContext::OnField_Validate(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool bKeyDown,
- bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) {
- m_pEventHandler->OnField_Validate(strChange, strChangeEx, bKeyDown, bModifier,
- bShift, pTarget, Value, bRc);
-}
-
-void CJS_EventContext::OnScreen_Focus(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_Focus(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_Blur(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_Blur(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_Open(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_Open(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_Close(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_Close(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_MouseDown(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_MouseDown(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_MouseUp(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_MouseUp(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_MouseEnter(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_MouseEnter(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_MouseExit(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_MouseExit(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_InView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_InView(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnScreen_OutView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) {
- m_pEventHandler->OnScreen_OutView(bModifier, bShift, pScreen);
-}
-
-void CJS_EventContext::OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) {
- m_pEventHandler->OnBookmark_MouseUp(pBookMark);
-}
-
-void CJS_EventContext::OnLink_MouseUp(
- CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnLink_MouseUp(pFormFillEnv);
-}
-
-void CJS_EventContext::OnConsole_Exec() {
- m_pEventHandler->OnConsole_Exec();
-}
-
-void CJS_EventContext::OnExternal_Exec() {
- m_pEventHandler->OnExternal_Exec();
-}
-
-void CJS_EventContext::OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pEventHandler->OnBatchExec(pFormFillEnv);
-}
-
-void CJS_EventContext::OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName) {
- m_pEventHandler->OnMenu_Exec(pFormFillEnv, strTargetName);
-}
diff --git a/fpdfsdk/javascript/cjs_event_context.h b/fpdfsdk/javascript/cjs_event_context.h
deleted file mode 100644
index 7bfe528..0000000
--- a/fpdfsdk/javascript/cjs_event_context.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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_JAVASCRIPT_CJS_EVENT_CONTEXT_H_
-#define FPDFSDK_JAVASCRIPT_CJS_EVENT_CONTEXT_H_
-
-#include <memory>
-
-#include "core/fxcrt/fx_string.h"
-#include "core/fxcrt/fx_system.h"
-#include "fpdfsdk/javascript/ijs_event_context.h"
-
-class CJS_EventHandler;
-class CJS_Runtime;
-class CPDFSDK_FormFillEnvironment;
-
-class CJS_EventContext : public IJS_EventContext {
- public:
- explicit CJS_EventContext(CJS_Runtime* pRuntime);
- ~CJS_EventContext() override;
-
- // IJS_EventContext
- bool RunScript(const CFX_WideString& script, CFX_WideString* info) override;
- void OnApp_Init() override;
- void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName) override;
- void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnDoc_DidSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnDoc_WillClose(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnPage_InView(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnPage_OutView(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnField_MouseDown(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) override;
- void OnField_MouseEnter(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) override;
- void OnField_MouseExit(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) override;
- void OnField_MouseUp(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) override;
- void OnField_Focus(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) override;
- void OnField_Blur(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) override;
- void OnField_Calculate(CPDF_FormField* pSource,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) override;
- void OnField_Format(CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit) override;
- void OnField_Keystroke(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool bKeyDown,
- bool bModifier,
- int& nSelEnd,
- int& nSelStart,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit,
- bool bFieldFull,
- bool& bRc) override;
- void OnField_Validate(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool bKeyDown,
- bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) override;
- void OnScreen_Focus(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_Blur(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_Open(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_Close(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_MouseDown(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_MouseUp(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_MouseEnter(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_MouseExit(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_InView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnScreen_OutView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) override;
- void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) override;
- void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName) override;
- void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) override;
- void OnConsole_Exec() override;
- void OnExternal_Exec() override;
-
- CJS_Runtime* GetJSRuntime() const { return m_pRuntime; }
- CJS_EventHandler* GetEventHandler() const { return m_pEventHandler.get(); }
-
- CPDFSDK_FormFillEnvironment* GetFormFillEnv();
-
- private:
- CJS_Runtime* const m_pRuntime;
- std::unique_ptr<CJS_EventHandler> m_pEventHandler;
- bool m_bBusy;
-};
-
-#endif // FPDFSDK_JAVASCRIPT_CJS_EVENT_CONTEXT_H_
diff --git a/fpdfsdk/javascript/cjs_runtime.cpp b/fpdfsdk/javascript/cjs_runtime.cpp
deleted file mode 100644
index 1ece0b6..0000000
--- a/fpdfsdk/javascript/cjs_runtime.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright 2014 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/javascript/cjs_runtime.h"
-
-#include <algorithm>
-
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/javascript/Annot.h"
-#include "fpdfsdk/javascript/Consts.h"
-#include "fpdfsdk/javascript/Document.h"
-#include "fpdfsdk/javascript/Field.h"
-#include "fpdfsdk/javascript/Icon.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_GlobalData.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/PublicMethods.h"
-#include "fpdfsdk/javascript/app.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/color.h"
-#include "fpdfsdk/javascript/console.h"
-#include "fpdfsdk/javascript/event.h"
-#include "fpdfsdk/javascript/global.h"
-#include "fpdfsdk/javascript/report.h"
-#include "fpdfsdk/javascript/util.h"
-#include "public/fpdf_formfill.h"
-#include "third_party/base/stl_util.h"
-
-#ifdef PDF_ENABLE_XFA
-#include "fxjs/cfxjse_value.h"
-#endif // PDF_ENABLE_XFA
-
-// static
-void IJS_Runtime::Initialize(unsigned int slot, void* isolate) {
- FXJS_Initialize(slot, reinterpret_cast<v8::Isolate*>(isolate));
-}
-
-// static
-void IJS_Runtime::Destroy() {
- FXJS_Release();
-}
-
-// static
-IJS_Runtime* IJS_Runtime::Create(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- return new CJS_Runtime(pFormFillEnv);
-}
-
-// static
-CJS_Runtime* CJS_Runtime::CurrentRuntimeFromIsolate(v8::Isolate* pIsolate) {
- return static_cast<CJS_Runtime*>(
- CFXJS_Engine::CurrentEngineFromIsolate(pIsolate));
-}
-
-CJS_Runtime::CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv)
- : m_pFormFillEnv(pFormFillEnv),
- m_bBlocking(false),
- m_isolateManaged(false) {
- v8::Isolate* pIsolate = nullptr;
-
- IPDF_JSPLATFORM* pPlatform = m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform;
- if (pPlatform->version <= 2) {
- unsigned int embedderDataSlot = 0;
- v8::Isolate* pExternalIsolate = nullptr;
- if (pPlatform->version == 2) {
- pExternalIsolate = reinterpret_cast<v8::Isolate*>(pPlatform->m_isolate);
- embedderDataSlot = pPlatform->m_v8EmbedderSlot;
- }
- FXJS_Initialize(embedderDataSlot, pExternalIsolate);
- }
- m_isolateManaged = FXJS_GetIsolate(&pIsolate);
- SetIsolate(pIsolate);
-
-#ifdef PDF_ENABLE_XFA
- v8::Isolate::Scope isolate_scope(pIsolate);
- v8::HandleScope handle_scope(pIsolate);
-#endif
-
- if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0)
- DefineJSObjects();
-
- IJS_EventContext* pContext = NewEventContext();
- InitializeEngine();
- ReleaseEventContext(pContext);
- SetFormFillEnvToDocument();
-}
-
-CJS_Runtime::~CJS_Runtime() {
- NotifyObservedPtrs();
- ReleaseEngine();
- if (m_isolateManaged) {
- GetIsolate()->Dispose();
- SetIsolate(nullptr);
- }
-}
-
-void CJS_Runtime::DefineJSObjects() {
- v8::Isolate::Scope isolate_scope(GetIsolate());
- v8::HandleScope handle_scope(GetIsolate());
- v8::Local<v8::Context> context = v8::Context::New(GetIsolate());
- v8::Context::Scope context_scope(context);
-
- // The call order determines the "ObjDefID" assigned to each class.
- // ObjDefIDs 0 - 2
- CJS_Border::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Display::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Font::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
-
- // ObjDefIDs 3 - 5
- CJS_Highlight::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Position::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_ScaleHow::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
-
- // ObjDefIDs 6 - 8
- CJS_ScaleWhen::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Style::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Zoomtype::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
-
- // ObjDefIDs 9 - 11
- CJS_App::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Color::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Console::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
-
- // ObjDefIDs 12 - 14
- CJS_Document::DefineJSObjects(this, FXJSOBJTYPE_GLOBAL);
- CJS_Event::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Field::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
-
- // ObjDefIDs 15 - 17
- CJS_Global::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
- CJS_Icon::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
- CJS_Util::DefineJSObjects(this, FXJSOBJTYPE_STATIC);
-
- // ObjDefIDs 18 - 20 (these can't fail, return void).
- CJS_PublicMethods::DefineJSObjects(this);
- CJS_GlobalConsts::DefineJSObjects(this);
- CJS_GlobalArrays::DefineJSObjects(this);
-
- // ObjDefIDs 21 - 23.
- CJS_TimerObj::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
- CJS_PrintParamsObj::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
- CJS_Annot::DefineJSObjects(this, FXJSOBJTYPE_DYNAMIC);
-}
-
-IJS_EventContext* CJS_Runtime::NewEventContext() {
- m_EventContextArray.push_back(
- std::unique_ptr<CJS_EventContext>(new CJS_EventContext(this)));
- return m_EventContextArray.back().get();
-}
-
-void CJS_Runtime::ReleaseEventContext(IJS_EventContext* pContext) {
- auto it = std::find(m_EventContextArray.begin(), m_EventContextArray.end(),
- pdfium::FakeUniquePtr<CJS_EventContext>(
- static_cast<CJS_EventContext*>(pContext)));
- if (it != m_EventContextArray.end())
- m_EventContextArray.erase(it);
-}
-
-CJS_EventContext* CJS_Runtime::GetCurrentEventContext() const {
- return m_EventContextArray.empty() ? nullptr
- : m_EventContextArray.back().get();
-}
-
-void CJS_Runtime::SetFormFillEnvToDocument() {
- v8::Isolate::Scope isolate_scope(GetIsolate());
- v8::HandleScope handle_scope(GetIsolate());
- v8::Local<v8::Context> context = NewLocalContext();
- v8::Context::Scope context_scope(context);
-
- v8::Local<v8::Object> pThis = GetThisObj();
- if (pThis.IsEmpty())
- return;
-
- if (CFXJS_Engine::GetObjDefnID(pThis) != CJS_Document::g_nObjDefnID)
- return;
-
- CJS_Document* pJSDocument =
- static_cast<CJS_Document*>(GetObjectPrivate(pThis));
- if (!pJSDocument)
- return;
-
- Document* pDocument = static_cast<Document*>(pJSDocument->GetEmbedObject());
- if (!pDocument)
- return;
-
- pDocument->SetFormFillEnv(m_pFormFillEnv.Get());
-}
-
-CPDFSDK_FormFillEnvironment* CJS_Runtime::GetFormFillEnv() const {
- return m_pFormFillEnv.Get();
-}
-
-int CJS_Runtime::ExecuteScript(const CFX_WideString& script,
- CFX_WideString* info) {
- FXJSErr error = {};
- int nRet = Execute(script, &error);
- if (nRet < 0) {
- info->Format(L"[ Line: %05d { %s } ] : %s", error.linnum - 1, error.srcline,
- error.message);
- }
- return nRet;
-}
-
-bool CJS_Runtime::AddEventToSet(const FieldEvent& event) {
- return m_FieldEventSet.insert(event).second;
-}
-
-void CJS_Runtime::RemoveEventFromSet(const FieldEvent& event) {
- m_FieldEventSet.erase(event);
-}
-
-#ifdef PDF_ENABLE_XFA
-CFX_WideString ChangeObjName(const CFX_WideString& str) {
- CFX_WideString sRet = str;
- sRet.Replace(L"_", L".");
- return sRet;
-}
-bool CJS_Runtime::GetValueByName(const CFX_ByteStringC& utf8Name,
- CFXJSE_Value* pValue) {
- const FX_CHAR* name = utf8Name.c_str();
-
- v8::Isolate::Scope isolate_scope(GetIsolate());
- v8::HandleScope handle_scope(GetIsolate());
- v8::Local<v8::Context> context = NewLocalContext();
- v8::Context::Scope context_scope(context);
-
- v8::Local<v8::Value> propvalue =
- context->Global()->Get(v8::String::NewFromUtf8(
- GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength()));
-
- if (propvalue.IsEmpty()) {
- pValue->SetUndefined();
- return false;
- }
- pValue->ForceSetValue(propvalue);
- return true;
-}
-bool CJS_Runtime::SetValueByName(const CFX_ByteStringC& utf8Name,
- CFXJSE_Value* pValue) {
- if (utf8Name.IsEmpty() || !pValue)
- return false;
- const FX_CHAR* name = utf8Name.c_str();
- v8::Isolate* pIsolate = GetIsolate();
- v8::Isolate::Scope isolate_scope(pIsolate);
- v8::HandleScope handle_scope(pIsolate);
- v8::Local<v8::Context> context = NewLocalContext();
- v8::Context::Scope context_scope(context);
-
- // v8::Local<v8::Context> tmpCotext =
- // v8::Local<v8::Context>::New(GetIsolate(), m_context);
- v8::Local<v8::Value> propvalue =
- v8::Local<v8::Value>::New(GetIsolate(), pValue->DirectGetValue());
- context->Global()->Set(
- v8::String::NewFromUtf8(pIsolate, name, v8::String::kNormalString,
- utf8Name.GetLength()),
- propvalue);
- return true;
-}
-#endif
diff --git a/fpdfsdk/javascript/cjs_runtime.h b/fpdfsdk/javascript/cjs_runtime.h
deleted file mode 100644
index 0bde51f..0000000
--- a/fpdfsdk/javascript/cjs_runtime.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_CJS_RUNTIME_H_
-#define FPDFSDK_JAVASCRIPT_CJS_RUNTIME_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "core/fxcrt/cfx_observable.h"
-#include "core/fxcrt/fx_basic.h"
-#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/ijs_runtime.h"
-#include "fxjs/fxjs_v8.h"
-
-class CJS_EventContext;
-
-class CJS_Runtime : public IJS_Runtime,
- public CFXJS_Engine,
- public CFX_Observable<CJS_Runtime> {
- public:
- using FieldEvent = std::pair<CFX_WideString, JS_EVENT_T>;
-
- static CJS_Runtime* CurrentRuntimeFromIsolate(v8::Isolate* pIsolate);
-
- explicit CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- ~CJS_Runtime() override;
-
- // IJS_Runtime
- IJS_EventContext* NewEventContext() override;
- void ReleaseEventContext(IJS_EventContext* pContext) override;
- CPDFSDK_FormFillEnvironment* GetFormFillEnv() const override;
- int ExecuteScript(const CFX_WideString& script,
- CFX_WideString* info) override;
-
- CJS_EventContext* GetCurrentEventContext() const;
-
- // Returns true if the event isn't already found in the set.
- bool AddEventToSet(const FieldEvent& event);
- void RemoveEventFromSet(const FieldEvent& event);
-
- void BeginBlock() { m_bBlocking = true; }
- void EndBlock() { m_bBlocking = false; }
- bool IsBlocking() const { return m_bBlocking; }
-
-#ifdef PDF_ENABLE_XFA
- bool GetValueByName(const CFX_ByteStringC& utf8Name,
- CFXJSE_Value* pValue) override;
- bool SetValueByName(const CFX_ByteStringC& utf8Name,
- CFXJSE_Value* pValue) override;
-#endif // PDF_ENABLE_XFA
-
- private:
- void DefineJSObjects();
- void SetFormFillEnvToDocument();
-
- std::vector<std::unique_ptr<CJS_EventContext>> m_EventContextArray;
- CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
- bool m_bBlocking;
- bool m_isolateManaged;
- std::set<FieldEvent> m_FieldEventSet;
-};
-
-#endif // FPDFSDK_JAVASCRIPT_CJS_RUNTIME_H_
diff --git a/fpdfsdk/javascript/color.cpp b/fpdfsdk/javascript/color.cpp
deleted file mode 100644
index b5ccbad..0000000
--- a/fpdfsdk/javascript/color.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright 2014 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/javascript/color.h"
-
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-
-JSConstSpec CJS_Color::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Color::PropertySpecs[] = {
- {"black", get_black_static, set_black_static},
- {"blue", get_blue_static, set_blue_static},
- {"cyan", get_cyan_static, set_cyan_static},
- {"dkGray", get_dkGray_static, set_dkGray_static},
- {"gray", get_gray_static, set_gray_static},
- {"green", get_green_static, set_green_static},
- {"ltGray", get_ltGray_static, set_ltGray_static},
- {"magenta", get_magenta_static, set_magenta_static},
- {"red", get_red_static, set_red_static},
- {"transparent", get_transparent_static, set_transparent_static},
- {"white", get_white_static, set_white_static},
- {"yellow", get_yellow_static, set_yellow_static},
- {0, 0, 0}};
-
-JSMethodSpec CJS_Color::MethodSpecs[] = {{"convert", convert_static},
- {"equal", equal_static},
- {0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Color, color)
-
-color::color(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {
- m_crTransparent = CPWL_Color(COLORTYPE_TRANSPARENT);
- m_crBlack = CPWL_Color(COLORTYPE_GRAY, 0);
- m_crWhite = CPWL_Color(COLORTYPE_GRAY, 1);
- m_crRed = CPWL_Color(COLORTYPE_RGB, 1, 0, 0);
- m_crGreen = CPWL_Color(COLORTYPE_RGB, 0, 1, 0);
- m_crBlue = CPWL_Color(COLORTYPE_RGB, 0, 0, 1);
- m_crCyan = CPWL_Color(COLORTYPE_CMYK, 1, 0, 0, 0);
- m_crMagenta = CPWL_Color(COLORTYPE_CMYK, 0, 1, 0, 0);
- m_crYellow = CPWL_Color(COLORTYPE_CMYK, 0, 0, 1, 0);
- m_crDKGray = CPWL_Color(COLORTYPE_GRAY, 0.25);
- m_crGray = CPWL_Color(COLORTYPE_GRAY, 0.5);
- m_crLTGray = CPWL_Color(COLORTYPE_GRAY, 0.75);
-}
-
-color::~color() {}
-
-void color::ConvertPWLColorToArray(CJS_Runtime* pRuntime,
- const CPWL_Color& color,
- CJS_Array* array) {
- switch (color.nColorType) {
- case COLORTYPE_TRANSPARENT:
- array->SetElement(pRuntime, 0, CJS_Value(pRuntime, "T"));
- break;
- case COLORTYPE_GRAY:
- array->SetElement(pRuntime, 0, CJS_Value(pRuntime, "G"));
- array->SetElement(pRuntime, 1, CJS_Value(pRuntime, color.fColor1));
- break;
- case COLORTYPE_RGB:
- array->SetElement(pRuntime, 0, CJS_Value(pRuntime, "RGB"));
- array->SetElement(pRuntime, 1, CJS_Value(pRuntime, color.fColor1));
- array->SetElement(pRuntime, 2, CJS_Value(pRuntime, color.fColor2));
- array->SetElement(pRuntime, 3, CJS_Value(pRuntime, color.fColor3));
- break;
- case COLORTYPE_CMYK:
- array->SetElement(pRuntime, 0, CJS_Value(pRuntime, "CMYK"));
- array->SetElement(pRuntime, 1, CJS_Value(pRuntime, color.fColor1));
- array->SetElement(pRuntime, 2, CJS_Value(pRuntime, color.fColor2));
- array->SetElement(pRuntime, 3, CJS_Value(pRuntime, color.fColor3));
- array->SetElement(pRuntime, 4, CJS_Value(pRuntime, color.fColor4));
- break;
- }
-}
-
-void color::ConvertArrayToPWLColor(CJS_Runtime* pRuntime,
- const CJS_Array& array,
- CPWL_Color* color) {
- int nArrayLen = array.GetLength(pRuntime);
- if (nArrayLen < 1)
- return;
-
- CJS_Value value(pRuntime);
- array.GetElement(pRuntime, 0, value);
- CFX_ByteString sSpace = value.ToCFXByteString(pRuntime);
-
- double d1 = 0;
- double d2 = 0;
- double d3 = 0;
- double d4 = 0;
-
- if (nArrayLen > 1) {
- array.GetElement(pRuntime, 1, value);
- d1 = value.ToDouble(pRuntime);
- }
-
- if (nArrayLen > 2) {
- array.GetElement(pRuntime, 2, value);
- d2 = value.ToDouble(pRuntime);
- }
-
- if (nArrayLen > 3) {
- array.GetElement(pRuntime, 3, value);
- d3 = value.ToDouble(pRuntime);
- }
-
- if (nArrayLen > 4) {
- array.GetElement(pRuntime, 4, value);
- d4 = value.ToDouble(pRuntime);
- }
-
- if (sSpace == "T") {
- *color = CPWL_Color(COLORTYPE_TRANSPARENT);
- } else if (sSpace == "G") {
- *color = CPWL_Color(COLORTYPE_GRAY, (FX_FLOAT)d1);
- } else if (sSpace == "RGB") {
- *color =
- CPWL_Color(COLORTYPE_RGB, (FX_FLOAT)d1, (FX_FLOAT)d2, (FX_FLOAT)d3);
- } else if (sSpace == "CMYK") {
- *color = CPWL_Color(COLORTYPE_CMYK, (FX_FLOAT)d1, (FX_FLOAT)d2,
- (FX_FLOAT)d3, (FX_FLOAT)d4);
- }
-}
-
-bool color::transparent(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crTransparent);
-}
-
-bool color::black(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crBlack);
-}
-
-bool color::white(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crWhite);
-}
-
-bool color::red(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crRed);
-}
-
-bool color::green(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crGreen);
-}
-
-bool color::blue(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crBlue);
-}
-
-bool color::cyan(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crCyan);
-}
-
-bool color::magenta(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crMagenta);
-}
-
-bool color::yellow(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crYellow);
-}
-
-bool color::dkGray(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crDKGray);
-}
-
-bool color::gray(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crGray);
-}
-
-bool color::ltGray(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return PropertyHelper(pRuntime, vp, &m_crLTGray);
-}
-
-bool color::PropertyHelper(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CPWL_Color* var) {
- CJS_Array array;
- if (vp.IsGetting()) {
- ConvertPWLColorToArray(pRuntime, *var, &array);
- vp << array;
- return true;
- }
- if (!vp.GetJSValue()->ConvertToArray(pRuntime, array))
- return false;
-
- ConvertArrayToPWLColor(pRuntime, array, var);
- return true;
-}
-
-bool color::convert(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int iSize = params.size();
- if (iSize < 2)
- return false;
-
- CJS_Array aSource;
- if (!params[0].ConvertToArray(pRuntime, aSource))
- return false;
-
- CPWL_Color crSource;
- ConvertArrayToPWLColor(pRuntime, aSource, &crSource);
-
- CFX_ByteString sDestSpace = params[1].ToCFXByteString(pRuntime);
- int nColorType = COLORTYPE_TRANSPARENT;
-
- if (sDestSpace == "T") {
- nColorType = COLORTYPE_TRANSPARENT;
- } else if (sDestSpace == "G") {
- nColorType = COLORTYPE_GRAY;
- } else if (sDestSpace == "RGB") {
- nColorType = COLORTYPE_RGB;
- } else if (sDestSpace == "CMYK") {
- nColorType = COLORTYPE_CMYK;
- }
-
- CJS_Array aDest;
- CPWL_Color crDest = crSource.ConvertColorType(nColorType);
- ConvertPWLColorToArray(pRuntime, crDest, &aDest);
- vRet = CJS_Value(pRuntime, aDest);
-
- return true;
-}
-
-bool color::equal(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() < 2)
- return false;
-
- CJS_Array array1;
- CJS_Array array2;
- if (!params[0].ConvertToArray(pRuntime, array1))
- return false;
- if (!params[1].ConvertToArray(pRuntime, array2))
- return false;
-
- CPWL_Color color1;
- CPWL_Color color2;
- ConvertArrayToPWLColor(pRuntime, array1, &color1);
- ConvertArrayToPWLColor(pRuntime, array2, &color2);
- color1 = color1.ConvertColorType(color2.nColorType);
- vRet = CJS_Value(pRuntime, color1 == color2);
- return true;
-}
diff --git a/fpdfsdk/javascript/color.h b/fpdfsdk/javascript/color.h
deleted file mode 100644
index 8d6187a..0000000
--- a/fpdfsdk/javascript/color.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_COLOR_H_
-#define FPDFSDK_JAVASCRIPT_COLOR_H_
-
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-class color : public CJS_EmbedObj {
- public:
- explicit color(CJS_Object* pJSObject);
- ~color() override;
-
- bool black(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool blue(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool cyan(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool dkGray(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool gray(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool green(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool ltGray(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool magenta(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool red(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool transparent(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool white(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool yellow(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
-
- bool convert(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool equal(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
-
- static void ConvertPWLColorToArray(CJS_Runtime* pRuntime,
- const CPWL_Color& color,
- CJS_Array* array);
- static void ConvertArrayToPWLColor(CJS_Runtime* pRuntime,
- const CJS_Array& array,
- CPWL_Color* color);
-
- private:
- bool PropertyHelper(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CPWL_Color* val);
-
- CPWL_Color m_crTransparent;
- CPWL_Color m_crBlack;
- CPWL_Color m_crWhite;
- CPWL_Color m_crRed;
- CPWL_Color m_crGreen;
- CPWL_Color m_crBlue;
- CPWL_Color m_crCyan;
- CPWL_Color m_crMagenta;
- CPWL_Color m_crYellow;
- CPWL_Color m_crDKGray;
- CPWL_Color m_crGray;
- CPWL_Color m_crLTGray;
-};
-
-class CJS_Color : public CJS_Object {
- public:
- explicit CJS_Color(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Color() override {}
-
- DECLARE_JS_CLASS();
-
- JS_STATIC_PROP(black, color);
- JS_STATIC_PROP(blue, color);
- JS_STATIC_PROP(cyan, color);
- JS_STATIC_PROP(dkGray, color);
- JS_STATIC_PROP(gray, color);
- JS_STATIC_PROP(green, color);
- JS_STATIC_PROP(ltGray, color);
- JS_STATIC_PROP(magenta, color);
- JS_STATIC_PROP(red, color);
- JS_STATIC_PROP(transparent, color);
- JS_STATIC_PROP(white, color);
- JS_STATIC_PROP(yellow, color);
-
- JS_STATIC_METHOD(convert, color);
- JS_STATIC_METHOD(equal, color);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_COLOR_H_
diff --git a/fpdfsdk/javascript/console.cpp b/fpdfsdk/javascript/console.cpp
deleted file mode 100644
index e9d1308..0000000
--- a/fpdfsdk/javascript/console.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 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/javascript/console.h"
-
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-
-JSConstSpec CJS_Console::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Console::PropertySpecs[] = {{0, 0, 0}};
-
-JSMethodSpec CJS_Console::MethodSpecs[] = {{"clear", clear_static},
- {"hide", hide_static},
- {"println", println_static},
- {"show", show_static},
- {0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Console, console)
-
-console::console(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {}
-
-console::~console() {}
-
-bool console::clear(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool console::hide(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
-
-bool console::println(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() < 1) {
- return false;
- }
- return true;
-}
-
-bool console::show(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- return true;
-}
diff --git a/fpdfsdk/javascript/console.h b/fpdfsdk/javascript/console.h
deleted file mode 100644
index a7e4d8e..0000000
--- a/fpdfsdk/javascript/console.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_CONSOLE_H_
-#define FPDFSDK_JAVASCRIPT_CONSOLE_H_
-
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class console : public CJS_EmbedObj {
- public:
- explicit console(CJS_Object* pJSObject);
- ~console() override;
-
- public:
- bool clear(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool hide(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool println(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool show(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
-};
-
-class CJS_Console : public CJS_Object {
- public:
- explicit CJS_Console(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Console() override {}
-
- DECLARE_JS_CLASS();
-
- JS_STATIC_METHOD(clear, console);
- JS_STATIC_METHOD(hide, console);
- JS_STATIC_METHOD(println, console);
- JS_STATIC_METHOD(show, console);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_CONSOLE_H_
diff --git a/fpdfsdk/javascript/event.cpp b/fpdfsdk/javascript/event.cpp
deleted file mode 100644
index 2b00cbc..0000000
--- a/fpdfsdk/javascript/event.cpp
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2014 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/javascript/event.h"
-
-#include "fpdfsdk/javascript/Field.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-
-JSConstSpec CJS_Event::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Event::PropertySpecs[] = {
- {"change", get_change_static, set_change_static},
- {"changeEx", get_changeEx_static, set_changeEx_static},
- {"commitKey", get_commitKey_static, set_commitKey_static},
- {"fieldFull", get_fieldFull_static, set_fieldFull_static},
- {"keyDown", get_keyDown_static, set_keyDown_static},
- {"modifier", get_modifier_static, set_modifier_static},
- {"name", get_name_static, set_name_static},
- {"rc", get_rc_static, set_rc_static},
- {"richChange", get_richChange_static, set_richChange_static},
- {"richChangeEx", get_richChangeEx_static, set_richChangeEx_static},
- {"richValue", get_richValue_static, set_richValue_static},
- {"selEnd", get_selEnd_static, set_selEnd_static},
- {"selStart", get_selStart_static, set_selStart_static},
- {"shift", get_shift_static, set_shift_static},
- {"source", get_source_static, set_source_static},
- {"target", get_target_static, set_target_static},
- {"targetName", get_targetName_static, set_targetName_static},
- {"type", get_type_static, set_type_static},
- {"value", get_value_static, set_value_static},
- {"willCommit", get_willCommit_static, set_willCommit_static},
- {0, 0, 0}};
-
-JSMethodSpec CJS_Event::MethodSpecs[] = {{0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Event, event)
-
-event::event(CJS_Object* pJsObject) : CJS_EmbedObj(pJsObject) {}
-
-event::~event() {}
-
-bool event::change(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
- CFX_WideString& wChange = pEvent->Change();
- if (vp.IsSetting()) {
- if (vp.GetJSValue()->GetType() == CJS_Value::VT_string)
- vp >> wChange;
- return true;
- }
- vp << wChange;
- return true;
-}
-
-bool event::changeEx(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->ChangeEx();
- return true;
-}
-
-bool event::commitKey(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->CommitKey();
- return true;
-}
-
-bool event::fieldFull(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- if (!vp.IsGetting() &&
- wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0)
- return false;
-
- vp << pEvent->FieldFull();
- return true;
-}
-
-bool event::keyDown(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->KeyDown();
- return true;
-}
-
-bool event::modifier(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->Modifier();
- return true;
-}
-
-bool event::name(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->Name();
- return true;
-}
-
-bool event::rc(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- bool& bRc = pEvent->Rc();
- if (vp.IsSetting())
- vp >> bRc;
- else
- vp << bRc;
-
- return true;
-}
-
-bool event::richChange(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool event::richChangeEx(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool event::richValue(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- return true;
-}
-
-bool event::selEnd(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0)
- return true;
-
- int& iSelEnd = pEvent->SelEnd();
- if (vp.IsSetting())
- vp >> iSelEnd;
- else
- vp << iSelEnd;
-
- return true;
-}
-
-bool event::selStart(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- if (wcscmp((const wchar_t*)pEvent->Name(), L"Keystroke") != 0)
- return true;
-
- int& iSelStart = pEvent->SelStart();
- if (vp.IsSetting())
- vp >> iSelStart;
- else
- vp << iSelStart;
-
- return true;
-}
-
-bool event::shift(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->Shift();
- return true;
-}
-
-bool event::source(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->Source()->GetJSObject();
- return true;
-}
-
-bool event::target(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->Target_Field()->GetJSObject();
- return true;
-}
-
-bool event::targetName(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->TargetName();
- return true;
-}
-
-bool event::type(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->Type();
- return true;
-}
-
-bool event::value(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- if (wcscmp((const wchar_t*)pEvent->Type(), L"Field") != 0)
- return false;
-
- if (!pEvent->m_pValue)
- return false;
-
- CFX_WideString& val = pEvent->Value();
- if (vp.IsSetting())
- vp >> val;
- else
- vp << val;
-
- return true;
-}
-
-bool event::willCommit(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (!vp.IsGetting())
- return false;
-
- CJS_EventHandler* pEvent =
- pRuntime->GetCurrentEventContext()->GetEventHandler();
-
- vp << pEvent->WillCommit();
- return true;
-}
diff --git a/fpdfsdk/javascript/event.h b/fpdfsdk/javascript/event.h
deleted file mode 100644
index 2be8a0a..0000000
--- a/fpdfsdk/javascript/event.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_EVENT_H_
-#define FPDFSDK_JAVASCRIPT_EVENT_H_
-
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class event : public CJS_EmbedObj {
- public:
- explicit event(CJS_Object* pJSObject);
- ~event() override;
-
- public:
- bool change(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool changeEx(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool commitKey(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool fieldFull(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool keyDown(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool modifier(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool name(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool rc(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool richChange(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool richChangeEx(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool richValue(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool selEnd(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool selStart(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool shift(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool source(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool target(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool targetName(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool type(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool value(CJS_Runtime* pRuntime, CJS_PropValue& vp, CFX_WideString& sError);
- bool willCommit(CJS_Runtime* pRuntime,
- CJS_PropValue& vp,
- CFX_WideString& sError);
-};
-
-class CJS_Event : public CJS_Object {
- public:
- explicit CJS_Event(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Event() override {}
-
- DECLARE_JS_CLASS();
- JS_STATIC_PROP(change, event);
- JS_STATIC_PROP(changeEx, event);
- JS_STATIC_PROP(commitKey, event);
- JS_STATIC_PROP(fieldFull, event);
- JS_STATIC_PROP(keyDown, event);
- JS_STATIC_PROP(modifier, event);
- JS_STATIC_PROP(name, event);
- JS_STATIC_PROP(rc, event);
- JS_STATIC_PROP(richChange, event);
- JS_STATIC_PROP(richChangeEx, event);
- JS_STATIC_PROP(richValue, event);
- JS_STATIC_PROP(selEnd, event);
- JS_STATIC_PROP(selStart, event);
- JS_STATIC_PROP(shift, event);
- JS_STATIC_PROP(source, event);
- JS_STATIC_PROP(target, event);
- JS_STATIC_PROP(targetName, event);
- JS_STATIC_PROP(type, event);
- JS_STATIC_PROP(value, event);
- JS_STATIC_PROP(willCommit, event);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_EVENT_H_
diff --git a/fpdfsdk/javascript/global.cpp b/fpdfsdk/javascript/global.cpp
deleted file mode 100644
index a450606..0000000
--- a/fpdfsdk/javascript/global.cpp
+++ /dev/null
@@ -1,440 +0,0 @@
-// Copyright 2014 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/javascript/global.h"
-
-#include <vector>
-
-#include "core/fxcrt/fx_ext.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_GlobalData.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/resource.h"
-
-JSConstSpec CJS_Global::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Global::PropertySpecs[] = {{0, 0, 0}};
-
-JSMethodSpec CJS_Global::MethodSpecs[] = {
- {"setPersistent", setPersistent_static},
- {0, 0}};
-
-IMPLEMENT_SPECIAL_JS_CLASS(CJS_Global, JSGlobalAlternate, global);
-
-void CJS_Global::InitInstance(IJS_Runtime* pIRuntime) {
- CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime);
- JSGlobalAlternate* pGlobal =
- static_cast<JSGlobalAlternate*>(GetEmbedObject());
- pGlobal->Initial(pRuntime->GetFormFillEnv());
-}
-
-JSGlobalData::JSGlobalData()
- : nType(JS_GlobalDataType::NUMBER),
- dData(0),
- bData(false),
- sData(""),
- bPersistent(false),
- bDeleted(false) {}
-
-JSGlobalData::~JSGlobalData() {
- pData.Reset();
-}
-
-JSGlobalAlternate::JSGlobalAlternate(CJS_Object* pJSObject)
- : CJS_EmbedObj(pJSObject), m_pFormFillEnv(nullptr) {}
-
-JSGlobalAlternate::~JSGlobalAlternate() {
- DestroyGlobalPersisitentVariables();
- m_pGlobalData->Release();
-}
-
-void JSGlobalAlternate::Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
- m_pFormFillEnv.Reset(pFormFillEnv);
- m_pGlobalData = CJS_GlobalData::GetRetainedInstance(pFormFillEnv);
- UpdateGlobalPersistentVariables();
-}
-
-bool JSGlobalAlternate::QueryProperty(const FX_WCHAR* propname) {
- return CFX_WideString(propname) != L"setPersistent";
-}
-
-bool JSGlobalAlternate::DelProperty(CJS_Runtime* pRuntime,
- const FX_WCHAR* propname,
- CFX_WideString& sError) {
- auto it = m_mapGlobal.find(CFX_ByteString::FromUnicode(propname));
- if (it == m_mapGlobal.end())
- return false;
-
- it->second->bDeleted = true;
- return true;
-}
-
-bool JSGlobalAlternate::DoProperty(CJS_Runtime* pRuntime,
- const FX_WCHAR* propname,
- CJS_PropValue& vp,
- CFX_WideString& sError) {
- if (vp.IsSetting()) {
- CFX_ByteString sPropName = CFX_ByteString::FromUnicode(propname);
- switch (vp.GetJSValue()->GetType()) {
- case CJS_Value::VT_number: {
- double dData;
- vp >> dData;
- return SetGlobalVariables(sPropName, JS_GlobalDataType::NUMBER, dData,
- false, "", v8::Local<v8::Object>(), false);
- }
- case CJS_Value::VT_boolean: {
- bool bData;
- vp >> bData;
- return SetGlobalVariables(sPropName, JS_GlobalDataType::BOOLEAN, 0,
- bData, "", v8::Local<v8::Object>(), false);
- }
- case CJS_Value::VT_string: {
- CFX_ByteString sData;
- vp >> sData;
- return SetGlobalVariables(sPropName, JS_GlobalDataType::STRING, 0,
- false, sData, v8::Local<v8::Object>(), false);
- }
- case CJS_Value::VT_object: {
- v8::Local<v8::Object> pData;
- vp >> pData;
- return SetGlobalVariables(sPropName, JS_GlobalDataType::OBJECT, 0,
- false, "", pData, false);
- }
- case CJS_Value::VT_null: {
- return SetGlobalVariables(sPropName, JS_GlobalDataType::NULLOBJ, 0,
- false, "", v8::Local<v8::Object>(), false);
- }
- case CJS_Value::VT_undefined: {
- DelProperty(pRuntime, propname, sError);
- return true;
- }
- default:
- break;
- }
- } else {
- auto it = m_mapGlobal.find(CFX_ByteString::FromUnicode(propname));
- if (it == m_mapGlobal.end()) {
- vp.GetJSValue()->SetNull(pRuntime);
- return true;
- }
- JSGlobalData* pData = it->second;
- if (pData->bDeleted) {
- vp.GetJSValue()->SetNull(pRuntime);
- return true;
- }
- switch (pData->nType) {
- case JS_GlobalDataType::NUMBER:
- vp << pData->dData;
- return true;
- case JS_GlobalDataType::BOOLEAN:
- vp << pData->bData;
- return true;
- case JS_GlobalDataType::STRING:
- vp << pData->sData;
- return true;
- case JS_GlobalDataType::OBJECT: {
- v8::Local<v8::Object> obj = v8::Local<v8::Object>::New(
- vp.GetJSRuntime()->GetIsolate(), pData->pData);
- vp << obj;
- return true;
- }
- case JS_GlobalDataType::NULLOBJ:
- vp.GetJSValue()->SetNull(pRuntime);
- return true;
- default:
- break;
- }
- }
- return false;
-}
-
-bool JSGlobalAlternate::setPersistent(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() != 2) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- auto it = m_mapGlobal.find(params[0].ToCFXByteString(pRuntime));
- if (it != m_mapGlobal.end()) {
- JSGlobalData* pData = it->second;
- if (!pData->bDeleted) {
- pData->bPersistent = params[1].ToBool(pRuntime);
- return true;
- }
- }
-
- sError = JSGetStringFromID(IDS_STRING_JSNOGLOBAL);
- return false;
-}
-
-void JSGlobalAlternate::UpdateGlobalPersistentVariables() {
- CJS_Runtime* pRuntime =
- static_cast<CJS_Runtime*>(CFXJS_Engine::CurrentEngineFromIsolate(
- m_pJSObject->ToV8Object()->GetIsolate()));
-
- for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
- CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);
- switch (pData->data.nType) {
- case JS_GlobalDataType::NUMBER:
- SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NUMBER,
- pData->data.dData, false, "",
- v8::Local<v8::Object>(), pData->bPersistent == 1);
- pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
- pData->data.sKey.UTF8Decode(),
- pRuntime->NewNumber(pData->data.dData));
- break;
- case JS_GlobalDataType::BOOLEAN:
- SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::BOOLEAN, 0,
- pData->data.bData == 1, "", v8::Local<v8::Object>(),
- pData->bPersistent == 1);
- pRuntime->PutObjectProperty(
- m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(),
- pRuntime->NewBoolean(pData->data.bData == 1));
- break;
- case JS_GlobalDataType::STRING:
- SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::STRING, 0,
- false, pData->data.sData, v8::Local<v8::Object>(),
- pData->bPersistent == 1);
- pRuntime->PutObjectProperty(
- m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(),
- pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringC()));
- break;
- case JS_GlobalDataType::OBJECT: {
- v8::Local<v8::Object> pObj = pRuntime->NewFxDynamicObj(-1);
- PutObjectProperty(pObj, &pData->data);
- SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::OBJECT, 0,
- false, "", pObj, pData->bPersistent == 1);
- pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
- pData->data.sKey.UTF8Decode(), pObj);
- } break;
- case JS_GlobalDataType::NULLOBJ:
- SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NULLOBJ, 0,
- false, "", v8::Local<v8::Object>(),
- pData->bPersistent == 1);
- pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
- pData->data.sKey.UTF8Decode(),
- pRuntime->NewNull());
- break;
- }
- }
-}
-
-void JSGlobalAlternate::CommitGlobalPersisitentVariables(
- CJS_Runtime* pRuntime) {
- for (auto it = m_mapGlobal.begin(); it != m_mapGlobal.end(); ++it) {
- CFX_ByteString name = it->first;
- JSGlobalData* pData = it->second;
- if (pData->bDeleted) {
- m_pGlobalData->DeleteGlobalVariable(name);
- } else {
- switch (pData->nType) {
- case JS_GlobalDataType::NUMBER:
- m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
- m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
- break;
- case JS_GlobalDataType::BOOLEAN:
- m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
- m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
- break;
- case JS_GlobalDataType::STRING:
- m_pGlobalData->SetGlobalVariableString(name, pData->sData);
- m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
- break;
- case JS_GlobalDataType::OBJECT: {
- CJS_GlobalVariableArray array;
- v8::Local<v8::Object> obj = v8::Local<v8::Object>::New(
- GetJSObject()->GetIsolate(), pData->pData);
- ObjectToArray(pRuntime, obj, array);
- m_pGlobalData->SetGlobalVariableObject(name, array);
- m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
- } break;
- case JS_GlobalDataType::NULLOBJ:
- m_pGlobalData->SetGlobalVariableNull(name);
- m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
- break;
- }
- }
- }
-}
-
-void JSGlobalAlternate::ObjectToArray(CJS_Runtime* pRuntime,
- v8::Local<v8::Object> pObj,
- CJS_GlobalVariableArray& array) {
- std::vector<CFX_WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
- for (const auto& ws : pKeyList) {
- CFX_ByteString sKey = ws.UTF8Encode();
- v8::Local<v8::Value> v = pRuntime->GetObjectProperty(pObj, ws);
- switch (CJS_Value::GetValueType(v)) {
- case CJS_Value::VT_number: {
- CJS_KeyValue* pObjElement = new CJS_KeyValue;
- pObjElement->nType = JS_GlobalDataType::NUMBER;
- pObjElement->sKey = sKey;
- pObjElement->dData = pRuntime->ToDouble(v);
- array.Add(pObjElement);
- } break;
- case CJS_Value::VT_boolean: {
- CJS_KeyValue* pObjElement = new CJS_KeyValue;
- pObjElement->nType = JS_GlobalDataType::BOOLEAN;
- pObjElement->sKey = sKey;
- pObjElement->dData = pRuntime->ToBoolean(v);
- array.Add(pObjElement);
- } break;
- case CJS_Value::VT_string: {
- CFX_ByteString sValue =
- CJS_Value(pRuntime, v).ToCFXByteString(pRuntime);
- CJS_KeyValue* pObjElement = new CJS_KeyValue;
- pObjElement->nType = JS_GlobalDataType::STRING;
- pObjElement->sKey = sKey;
- pObjElement->sData = sValue;
- array.Add(pObjElement);
- } break;
- case CJS_Value::VT_object: {
- CJS_KeyValue* pObjElement = new CJS_KeyValue;
- pObjElement->nType = JS_GlobalDataType::OBJECT;
- pObjElement->sKey = sKey;
- ObjectToArray(pRuntime, pRuntime->ToObject(v), pObjElement->objData);
- array.Add(pObjElement);
- } break;
- case CJS_Value::VT_null: {
- CJS_KeyValue* pObjElement = new CJS_KeyValue;
- pObjElement->nType = JS_GlobalDataType::NULLOBJ;
- pObjElement->sKey = sKey;
- array.Add(pObjElement);
- } break;
- default:
- break;
- }
- }
-}
-
-void JSGlobalAlternate::PutObjectProperty(v8::Local<v8::Object> pObj,
- CJS_KeyValue* pData) {
- CJS_Runtime* pRuntime = CJS_Runtime::CurrentRuntimeFromIsolate(
- m_pJSObject->ToV8Object()->GetIsolate());
-
- for (int i = 0, sz = pData->objData.Count(); i < sz; i++) {
- CJS_KeyValue* pObjData = pData->objData.GetAt(i);
- switch (pObjData->nType) {
- case JS_GlobalDataType::NUMBER:
- pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
- pRuntime->NewNumber(pObjData->dData));
- break;
- case JS_GlobalDataType::BOOLEAN:
- pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
- pRuntime->NewBoolean(pObjData->bData == 1));
- break;
- case JS_GlobalDataType::STRING:
- pRuntime->PutObjectProperty(
- pObj, pObjData->sKey.UTF8Decode(),
- pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringC()));
- break;
- case JS_GlobalDataType::OBJECT: {
- v8::Local<v8::Object> pNewObj = pRuntime->NewFxDynamicObj(-1);
- PutObjectProperty(pNewObj, pObjData);
- pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(), pNewObj);
- } break;
- case JS_GlobalDataType::NULLOBJ:
- pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
- pRuntime->NewNull());
- break;
- }
- }
-}
-
-void JSGlobalAlternate::DestroyGlobalPersisitentVariables() {
- for (const auto& pair : m_mapGlobal) {
- delete pair.second;
- }
- m_mapGlobal.clear();
-}
-
-bool JSGlobalAlternate::SetGlobalVariables(const CFX_ByteString& propname,
- JS_GlobalDataType nType,
- double dData,
- bool bData,
- const CFX_ByteString& sData,
- v8::Local<v8::Object> pData,
- bool bDefaultPersistent) {
- if (propname.IsEmpty())
- return false;
-
- auto it = m_mapGlobal.find(propname);
- if (it != m_mapGlobal.end()) {
- JSGlobalData* pTemp = it->second;
- if (pTemp->bDeleted || pTemp->nType != nType) {
- pTemp->dData = 0;
- pTemp->bData = 0;
- pTemp->sData = "";
- pTemp->nType = nType;
- }
-
- pTemp->bDeleted = false;
- switch (nType) {
- case JS_GlobalDataType::NUMBER: {
- pTemp->dData = dData;
- } break;
- case JS_GlobalDataType::BOOLEAN: {
- pTemp->bData = bData;
- } break;
- case JS_GlobalDataType::STRING: {
- pTemp->sData = sData;
- } break;
- case JS_GlobalDataType::OBJECT: {
- pTemp->pData.Reset(pData->GetIsolate(), pData);
- } break;
- case JS_GlobalDataType::NULLOBJ:
- break;
- default:
- return false;
- }
- return true;
- }
-
- JSGlobalData* pNewData = nullptr;
-
- switch (nType) {
- case JS_GlobalDataType::NUMBER: {
- pNewData = new JSGlobalData;
- pNewData->nType = JS_GlobalDataType::NUMBER;
- pNewData->dData = dData;
- pNewData->bPersistent = bDefaultPersistent;
- } break;
- case JS_GlobalDataType::BOOLEAN: {
- pNewData = new JSGlobalData;
- pNewData->nType = JS_GlobalDataType::BOOLEAN;
- pNewData->bData = bData;
- pNewData->bPersistent = bDefaultPersistent;
- } break;
- case JS_GlobalDataType::STRING: {
- pNewData = new JSGlobalData;
- pNewData->nType = JS_GlobalDataType::STRING;
- pNewData->sData = sData;
- pNewData->bPersistent = bDefaultPersistent;
- } break;
- case JS_GlobalDataType::OBJECT: {
- pNewData = new JSGlobalData;
- pNewData->nType = JS_GlobalDataType::OBJECT;
- pNewData->pData.Reset(pData->GetIsolate(), pData);
- pNewData->bPersistent = bDefaultPersistent;
- } break;
- case JS_GlobalDataType::NULLOBJ: {
- pNewData = new JSGlobalData;
- pNewData->nType = JS_GlobalDataType::NULLOBJ;
- pNewData->bPersistent = bDefaultPersistent;
- } break;
- default:
- return false;
- }
-
- m_mapGlobal[propname] = pNewData;
- return true;
-}
diff --git a/fpdfsdk/javascript/global.h b/fpdfsdk/javascript/global.h
deleted file mode 100644
index e313929..0000000
--- a/fpdfsdk/javascript/global.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_GLOBAL_H_
-#define FPDFSDK_JAVASCRIPT_GLOBAL_H_
-
-#include <map>
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_KeyValue.h"
-
-class CJS_GlobalData;
-class CJS_GlobalVariableArray;
-class CJS_KeyValue;
-
-struct JSGlobalData {
- JSGlobalData();
- ~JSGlobalData();
-
- JS_GlobalDataType nType;
- double dData;
- bool bData;
- CFX_ByteString sData;
- v8::Global<v8::Object> pData;
- bool bPersistent;
- bool bDeleted;
-};
-
-class JSGlobalAlternate : public CJS_EmbedObj {
- public:
- explicit JSGlobalAlternate(CJS_Object* pJSObject);
- ~JSGlobalAlternate() override;
-
- bool setPersistent(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool QueryProperty(const FX_WCHAR* propname);
- bool DoProperty(CJS_Runtime* pRuntime,
- const FX_WCHAR* propname,
- CJS_PropValue& vp,
- CFX_WideString& sError);
- bool DelProperty(CJS_Runtime* pRuntime,
- const FX_WCHAR* propname,
- CFX_WideString& sError);
- void Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv);
-
- private:
- void UpdateGlobalPersistentVariables();
- void CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime);
- void DestroyGlobalPersisitentVariables();
- bool SetGlobalVariables(const CFX_ByteString& propname,
- JS_GlobalDataType nType,
- double dData,
- bool bData,
- const CFX_ByteString& sData,
- v8::Local<v8::Object> pData,
- bool bDefaultPersistent);
- void ObjectToArray(CJS_Runtime* pRuntime,
- v8::Local<v8::Object> pObj,
- CJS_GlobalVariableArray& array);
- void PutObjectProperty(v8::Local<v8::Object> obj, CJS_KeyValue* pData);
-
- std::map<CFX_ByteString, JSGlobalData*> m_mapGlobal;
- CFX_WideString m_sFilePath;
- CJS_GlobalData* m_pGlobalData;
- CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
-};
-
-class CJS_Global : public CJS_Object {
- public:
- explicit CJS_Global(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Global() override {}
-
- // CJS_Object
- void InitInstance(IJS_Runtime* pIRuntime) override;
-
- DECLARE_SPECIAL_JS_CLASS();
- JS_SPECIAL_STATIC_METHOD(setPersistent, JSGlobalAlternate, global);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_GLOBAL_H_
diff --git a/fpdfsdk/javascript/ijs_event_context.h b/fpdfsdk/javascript/ijs_event_context.h
deleted file mode 100644
index 8428072..0000000
--- a/fpdfsdk/javascript/ijs_event_context.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2016 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_JAVASCRIPT_IJS_EVENT_CONTEXT_H_
-#define FPDFSDK_JAVASCRIPT_IJS_EVENT_CONTEXT_H_
-
-#include "core/fxcrt/fx_string.h"
-#include "core/fxcrt/fx_system.h"
-
-class CPDF_Bookmark;
-class CPDF_FormField;
-class CPDFSDK_Annot;
-class CPDFSDK_FormFillEnvironment;
-
-// Records the details of an event and triggers JS execution for it. There
-// can be more than one of these at any given time, as JS callbacks to C++
-// may trigger new events on top of one another.
-class IJS_EventContext {
- public:
- virtual bool RunScript(const CFX_WideString& script,
- CFX_WideString* info) = 0;
-
- virtual void OnApp_Init() = 0;
-
- virtual void OnDoc_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString& strTargetName) = 0;
- virtual void OnDoc_WillPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
- virtual void OnDoc_DidPrint(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
- virtual void OnDoc_WillSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
- virtual void OnDoc_DidSave(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
- virtual void OnDoc_WillClose(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
-
- virtual void OnPage_Open(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
- virtual void OnPage_Close(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
- virtual void OnPage_InView(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
- virtual void OnPage_OutView(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
-
- virtual void OnField_MouseDown(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) = 0;
- virtual void OnField_MouseEnter(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) = 0;
- virtual void OnField_MouseExit(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) = 0;
- virtual void OnField_MouseUp(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget) = 0;
- virtual void OnField_Focus(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) = 0;
- virtual void OnField_Blur(bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- const CFX_WideString& Value) = 0;
-
- virtual void OnField_Calculate(CPDF_FormField* pSource,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) = 0;
- virtual void OnField_Format(CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit) = 0;
- virtual void OnField_Keystroke(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool KeyDown,
- bool bModifier,
- int& nSelEnd,
- int& nSelStart,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool bWillCommit,
- bool bFieldFull,
- bool& bRc) = 0;
- virtual void OnField_Validate(CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- bool bKeyDown,
- bool bModifier,
- bool bShift,
- CPDF_FormField* pTarget,
- CFX_WideString& Value,
- bool& bRc) = 0;
-
- virtual void OnScreen_Focus(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_Blur(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_Open(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_Close(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_MouseDown(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_MouseUp(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_MouseEnter(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_MouseExit(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_InView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
- virtual void OnScreen_OutView(bool bModifier,
- bool bShift,
- CPDFSDK_Annot* pScreen) = 0;
-
- virtual void OnBookmark_MouseUp(CPDF_Bookmark* pBookMark) = 0;
- virtual void OnLink_MouseUp(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
-
- virtual void OnMenu_Exec(CPDFSDK_FormFillEnvironment* pFormFillEnv,
- const CFX_WideString&) = 0;
- virtual void OnBatchExec(CPDFSDK_FormFillEnvironment* pFormFillEnv) = 0;
- virtual void OnConsole_Exec() = 0;
- virtual void OnExternal_Exec() = 0;
-
- protected:
- virtual ~IJS_EventContext() {}
-};
-
-#endif // FPDFSDK_JAVASCRIPT_IJS_EVENT_CONTEXT_H_
diff --git a/fpdfsdk/javascript/ijs_runtime.h b/fpdfsdk/javascript/ijs_runtime.h
deleted file mode 100644
index babc418..0000000
--- a/fpdfsdk/javascript/ijs_runtime.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2016 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_JAVASCRIPT_IJS_RUNTIME_H_
-#define FPDFSDK_JAVASCRIPT_IJS_RUNTIME_H_
-
-#include "core/fxcrt/fx_string.h"
-#include "core/fxcrt/fx_system.h"
-
-#ifdef PDF_ENABLE_XFA
-#include "fxjs/fxjse.h"
-#endif // PDF_ENABLE_XFA
-
-class CPDFSDK_FormFillEnvironment;
-class IJS_EventContext;
-
-// Owns the FJXS objects needed to actually execute JS.
-class IJS_Runtime {
- public:
- static void Initialize(unsigned int slot, void* isolate);
- static void Destroy();
- static IJS_Runtime* Create(CPDFSDK_FormFillEnvironment* pFormFillEnv);
- virtual ~IJS_Runtime() {}
-
- virtual IJS_EventContext* NewEventContext() = 0;
- virtual void ReleaseEventContext(IJS_EventContext* pContext) = 0;
- virtual CPDFSDK_FormFillEnvironment* GetFormFillEnv() const = 0;
- virtual int ExecuteScript(const CFX_WideString& script,
- CFX_WideString* info) = 0;
-
-#ifdef PDF_ENABLE_XFA
- virtual bool GetValueByName(const CFX_ByteStringC& utf8Name,
- CFXJSE_Value* pValue) = 0;
- virtual bool SetValueByName(const CFX_ByteStringC& utf8Name,
- CFXJSE_Value* pValue) = 0;
-#endif // PDF_ENABLE_XFA
-
- protected:
- IJS_Runtime() {}
-};
-
-#endif // FPDFSDK_JAVASCRIPT_IJS_RUNTIME_H_
diff --git a/fpdfsdk/javascript/public_methods_embeddertest.cpp b/fpdfsdk/javascript/public_methods_embeddertest.cpp
deleted file mode 100644
index 2479366..0000000
--- a/fpdfsdk/javascript/public_methods_embeddertest.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2015 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.
-
-#include <cmath>
-
-#include "core/fxcrt/fx_string.h"
-#include "fpdfsdk/javascript/PublicMethods.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/js_embedder_test.h"
-
-namespace {
-
-double RoundDownDate(double date) {
- return date - fmod(date, 86400000);
-}
-
-} // namespace
-
-class PublicMethodsEmbedderTest : public JSEmbedderTest {};
-
-TEST_F(PublicMethodsEmbedderTest, MakeRegularDate) {
- v8::Isolate::Scope isolate_scope(isolate());
- v8::HandleScope handle_scope(isolate());
- v8::Context::Scope context_scope(GetV8Context());
- bool bWrongFormat;
- double date;
-
- // 1968
- bWrongFormat = false;
- date = CJS_PublicMethods::MakeRegularDate(L"06/25/1968", L"mm/dd/yyyy",
- &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(-47865600000, date);
- EXPECT_FALSE(bWrongFormat);
-
- // 1968
- bWrongFormat = false;
- date = CJS_PublicMethods::MakeRegularDate(L"25061968", L"ddmmyyyy",
- &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(-47865600000, date);
- EXPECT_FALSE(bWrongFormat);
-
- // 1968
- bWrongFormat = false;
- date = CJS_PublicMethods::MakeRegularDate(L"19680625", L"yyyymmdd",
- &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(-47865600000, date);
- EXPECT_FALSE(bWrongFormat);
-
- // 1985
- bWrongFormat = false;
- date = CJS_PublicMethods::MakeRegularDate(L"31121985", L"ddmmyyyy",
- &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(504835200000.0, date);
- EXPECT_FALSE(bWrongFormat);
-
- // 2085, the other '85.
- bWrongFormat = false;
- date =
- CJS_PublicMethods::MakeRegularDate(L"311285", L"ddmmyy", &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(3660595200000.0, date);
- EXPECT_FALSE(bWrongFormat);
-
- // 1995
- bWrongFormat = false;
- date = CJS_PublicMethods::MakeRegularDate(L"01021995", L"ddmmyyyy",
- &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(791596800000.0, date);
- EXPECT_FALSE(bWrongFormat);
-
- // 2095, the other '95.
- bWrongFormat = false;
- date =
- CJS_PublicMethods::MakeRegularDate(L"010295", L"ddmmyy", &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(3947356800000.0, date);
- EXPECT_FALSE(bWrongFormat);
-
- // 2005
- bWrongFormat = false;
- date = CJS_PublicMethods::MakeRegularDate(L"01022005", L"ddmmyyyy",
- &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(1107216000000.0, date);
- EXPECT_FALSE(bWrongFormat);
-
- // 2005
- bWrongFormat = false;
- date =
- CJS_PublicMethods::MakeRegularDate(L"010205", L"ddmmyy", &bWrongFormat);
- date = RoundDownDate(date);
- EXPECT_DOUBLE_EQ(1107216000000.0, date);
- EXPECT_FALSE(bWrongFormat);
-}
-
-TEST_F(PublicMethodsEmbedderTest, MakeFormatDate) {
- v8::Isolate::Scope isolate_scope(isolate());
- v8::HandleScope handle_scope(isolate());
- v8::Context::Scope context_scope(GetV8Context());
- CFX_WideString formatted_date;
-
- // 1968-06-25
- formatted_date = CJS_PublicMethods::MakeFormatDate(-47952000000, L"ddmmyy");
- EXPECT_STREQ(L"250668", formatted_date.c_str());
- formatted_date = CJS_PublicMethods::MakeFormatDate(-47952000000, L"yy/mm/dd");
- EXPECT_STREQ(L"68/06/25", formatted_date.c_str());
-
- // 1969-12-31
- formatted_date = CJS_PublicMethods::MakeFormatDate(-0.0001, L"ddmmyy");
- EXPECT_STREQ(L"311269", formatted_date.c_str());
- formatted_date = CJS_PublicMethods::MakeFormatDate(-0.0001, L"yy!mmdd");
- EXPECT_STREQ(L"69!1231", formatted_date.c_str());
-
- // 1970-01-01
- formatted_date = CJS_PublicMethods::MakeFormatDate(0, L"ddmmyy");
- EXPECT_STREQ(L"010170", formatted_date.c_str());
- formatted_date = CJS_PublicMethods::MakeFormatDate(0, L"mm-yyyy-dd");
- EXPECT_STREQ(L"01-1970-01", formatted_date.c_str());
-
- // 1985-12-31
- formatted_date = CJS_PublicMethods::MakeFormatDate(504835200000.0, L"ddmmyy");
- EXPECT_STREQ(L"311285", formatted_date.c_str());
- formatted_date = CJS_PublicMethods::MakeFormatDate(504835200000.0, L"yymmdd");
- EXPECT_STREQ(L"851231", formatted_date.c_str());
-
- // 1995-02-01
- formatted_date = CJS_PublicMethods::MakeFormatDate(791596800000.0, L"ddmmyy");
- EXPECT_STREQ(L"010295", formatted_date.c_str());
- formatted_date =
- CJS_PublicMethods::MakeFormatDate(791596800000.0, L"yyyymmdd");
- EXPECT_STREQ(L"19950201", formatted_date.c_str());
-
- // 2005-02-01
- formatted_date =
- CJS_PublicMethods::MakeFormatDate(1107216000000.0, L"ddmmyy");
- EXPECT_STREQ(L"010205", formatted_date.c_str());
- formatted_date =
- CJS_PublicMethods::MakeFormatDate(1107216000000.0, L"yyyyddmm");
- EXPECT_STREQ(L"20050102", formatted_date.c_str());
-
- // 2085-12-31
- formatted_date =
- CJS_PublicMethods::MakeFormatDate(3660595200000.0, L"ddmmyy");
- EXPECT_STREQ(L"311285", formatted_date.c_str());
- formatted_date =
- CJS_PublicMethods::MakeFormatDate(3660595200000.0, L"yyyydd");
- EXPECT_STREQ(L"208531", formatted_date.c_str());
-
- // 2095-02-01
- formatted_date =
- CJS_PublicMethods::MakeFormatDate(3947356800000.0, L"ddmmyy");
- EXPECT_STREQ(L"010295", formatted_date.c_str());
- formatted_date =
- CJS_PublicMethods::MakeFormatDate(3947356800000.0, L"mmddyyyy");
- EXPECT_STREQ(L"02012095", formatted_date.c_str());
-}
diff --git a/fpdfsdk/javascript/public_methods_unittest.cpp b/fpdfsdk/javascript/public_methods_unittest.cpp
deleted file mode 100644
index ace0920..0000000
--- a/fpdfsdk/javascript/public_methods_unittest.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2016 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.
-
-#include "fpdfsdk/javascript/PublicMethods.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/test_support.h"
-
-TEST(CJS_PublicMethods, IsNumber) {
- // TODO(weili): Check whether results from case 0, 1, 10, 15 are intended.
- struct {
- const wchar_t* input;
- bool expected;
- } test_data[] = {
- // Empty string.
- {L"", true},
- // Only whitespaces.
- {L" ", true},
- // Content with invalid characters.
- {L"xyz00", false},
- {L"1%", false},
- // Hex string.
- {L"0x234", false},
- // Signed numbers.
- {L"+123", true},
- {L"-98765", true},
- // Numbers with whitespaces.
- {L" 345 ", true},
- // Float numbers.
- {L"-1e5", false},
- {L"-2e", false},
- {L"e-5", true},
- {L"0.023", true},
- {L".356089", true},
- {L"1e-9", true},
- {L"-1.23e+23", true},
- // Numbers with commas.
- {L"1,000,000", false},
- {L"560,024", true},
- // Regular numbers.
- {L"0", true},
- {L"0123", true},
- {L"9876123", true},
- };
- for (size_t i = 0; i < FX_ArraySize(test_data); ++i) {
- EXPECT_EQ(test_data[i].expected,
- CJS_PublicMethods::IsNumber(test_data[i].input))
- << "for case " << i;
- }
-}
diff --git a/fpdfsdk/javascript/report.cpp b/fpdfsdk/javascript/report.cpp
deleted file mode 100644
index c9c986d..0000000
--- a/fpdfsdk/javascript/report.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 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/javascript/report.h"
-
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-
-JSConstSpec CJS_Report::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Report::PropertySpecs[] = {{0, 0, 0}};
-
-JSMethodSpec CJS_Report::MethodSpecs[] = {{"save", save_static},
- {"writeText", writeText_static},
- {0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Report, Report)
-
-Report::Report(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {}
-
-Report::~Report() {}
-
-bool Report::writeText(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
-
-bool Report::save(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- // Unsafe, not supported.
- return true;
-}
diff --git a/fpdfsdk/javascript/report.h b/fpdfsdk/javascript/report.h
deleted file mode 100644
index c66db80..0000000
--- a/fpdfsdk/javascript/report.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_REPORT_H_
-#define FPDFSDK_JAVASCRIPT_REPORT_H_
-
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class Report : public CJS_EmbedObj {
- public:
- explicit Report(CJS_Object* pJSObject);
- ~Report() override;
-
- public:
- bool save(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool writeText(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
-};
-
-class CJS_Report : public CJS_Object {
- public:
- explicit CJS_Report(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Report() override {}
-
- DECLARE_JS_CLASS();
-
- JS_STATIC_METHOD(save, Report)
- JS_STATIC_METHOD(writeText, Report);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_REPORT_H_
diff --git a/fpdfsdk/javascript/resource.cpp b/fpdfsdk/javascript/resource.cpp
deleted file mode 100644
index 6113c54..0000000
--- a/fpdfsdk/javascript/resource.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 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/javascript/resource.h"
-
-CFX_WideString JSGetStringFromID(uint32_t id) {
- switch (id) {
- case IDS_STRING_JSALERT:
- return L"Alert";
- case IDS_STRING_JSPARAMERROR:
- return L"Incorrect number of parameters passed to function.";
- case IDS_STRING_JSAFNUMBER_KEYSTROKE:
- return L"The input value is invalid.";
- case IDS_STRING_JSPARAM_TOOLONG:
- return L"The input value is too long.";
- case IDS_STRING_JSPARSEDATE:
- return L"The input value can't be parsed as a valid date/time (%s).";
- case IDS_STRING_JSRANGE1:
- return L"The input value must be greater than or equal to %s"
- L" and less than or equal to %s.";
- case IDS_STRING_JSRANGE2:
- return L"The input value must be greater than or equal to %s.";
- case IDS_STRING_JSRANGE3:
- return L"The input value must be less than or equal to %s.";
- case IDS_STRING_JSNOTSUPPORT:
- return L"Operation not supported.";
- case IDS_STRING_JSBUSY:
- return L"System is busy.";
- case IDS_STRING_JSEVENT:
- return L"Duplicate formfield event found.";
- case IDS_STRING_RUN:
- return L"Script ran successfully.";
- case IDS_STRING_JSPRINT1:
- return L"The second parameter can't be converted to a Date.";
- case IDS_STRING_JSPRINT2:
- return L"The second parameter is an invalid Date!";
- case IDS_STRING_JSNOGLOBAL:
- return L"Global value not found.";
- case IDS_STRING_JSREADONLY:
- return L"Cannot assign to readonly property.";
- case IDS_STRING_JSTYPEERROR:
- return L"Incorrect parameter type.";
- case IDS_STRING_JSVALUEERROR:
- return L"Incorrect parameter value.";
- case IDS_STRING_JSNOPERMISSION:
- return L"Permission denied.";
- case IDS_STRING_JSBADOBJECT:
- return L"Object no longer exists.";
- default:
- return L"";
- }
-}
-
-CFX_WideString JSFormatErrorString(const char* class_name,
- const char* property_name,
- const CFX_WideString& details) {
- CFX_WideString result = CFX_WideString::FromLocal(class_name);
- if (property_name) {
- result += L".";
- result += CFX_WideString::FromLocal(property_name);
- }
- result += L": ";
- result += details;
- return result;
-}
diff --git a/fpdfsdk/javascript/resource.h b/fpdfsdk/javascript/resource.h
deleted file mode 100644
index af7788f..0000000
--- a/fpdfsdk/javascript/resource.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_RESOURCE_H_
-#define FPDFSDK_JAVASCRIPT_RESOURCE_H_
-
-#include "core/fxcrt/fx_string.h"
-
-class CJS_EventContext;
-
-#define IDS_STRING_JSALERT 25613
-#define IDS_STRING_JSPARAMERROR 25614
-#define IDS_STRING_JSAFNUMBER_KEYSTROKE 25615
-#define IDS_STRING_JSPARAM_TOOLONG 25617
-#define IDS_STRING_JSPARSEDATE 25618
-#define IDS_STRING_JSRANGE1 25619
-#define IDS_STRING_JSRANGE2 25620
-#define IDS_STRING_JSRANGE3 25621
-#define IDS_STRING_JSNOTSUPPORT 25627
-#define IDS_STRING_JSBUSY 25628
-#define IDS_STRING_JSEVENT 25629
-#define IDS_STRING_RUN 25630
-#define IDS_STRING_JSPRINT1 25632
-#define IDS_STRING_JSPRINT2 25633
-#define IDS_STRING_JSNOGLOBAL 25635
-#define IDS_STRING_JSREADONLY 25636
-#define IDS_STRING_JSTYPEERROR 25637
-#define IDS_STRING_JSVALUEERROR 25638
-#define IDS_STRING_JSNOPERMISSION 25639
-#define IDS_STRING_JSBADOBJECT 25640
-
-CFX_WideString JSGetStringFromID(uint32_t id);
-CFX_WideString JSFormatErrorString(const char* class_name,
- const char* property_name,
- const CFX_WideString& details);
-
-#endif // FPDFSDK_JAVASCRIPT_RESOURCE_H_
diff --git a/fpdfsdk/javascript/util.cpp b/fpdfsdk/javascript/util.cpp
deleted file mode 100644
index 3221cfb..0000000
--- a/fpdfsdk/javascript/util.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-// Copyright 2014 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/javascript/util.h"
-
-#include <time.h>
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "core/fxcrt/fx_ext.h"
-#include "fpdfsdk/javascript/JS_Define.h"
-#include "fpdfsdk/javascript/JS_EventHandler.h"
-#include "fpdfsdk/javascript/JS_Object.h"
-#include "fpdfsdk/javascript/JS_Value.h"
-#include "fpdfsdk/javascript/PublicMethods.h"
-#include "fpdfsdk/javascript/cjs_event_context.h"
-#include "fpdfsdk/javascript/cjs_runtime.h"
-#include "fpdfsdk/javascript/resource.h"
-
-#if _FX_OS_ == _FX_ANDROID_
-#include <ctype.h>
-#endif
-
-JSConstSpec CJS_Util::ConstSpecs[] = {{0, JSConstSpec::Number, 0, 0}};
-
-JSPropertySpec CJS_Util::PropertySpecs[] = {{0, 0, 0}};
-
-JSMethodSpec CJS_Util::MethodSpecs[] = {
- {"printd", printd_static}, {"printf", printf_static},
- {"printx", printx_static}, {"scand", scand_static},
- {"byteToChar", byteToChar_static}, {0, 0}};
-
-IMPLEMENT_JS_CLASS(CJS_Util, util)
-
-#define UTIL_INT 0
-#define UTIL_DOUBLE 1
-#define UTIL_STRING 2
-
-namespace {
-
-// Map PDF-style directives to equivalent wcsftime directives. Not
-// all have direct equivalents, though.
-struct TbConvert {
- const FX_WCHAR* lpszJSMark;
- const FX_WCHAR* lpszCppMark;
-};
-
-// Map PDF-style directives lacking direct wcsftime directives to
-// the value with which they will be replaced.
-struct TbConvertAdditional {
- const FX_WCHAR* lpszJSMark;
- int iValue;
-};
-
-const TbConvert TbConvertTable[] = {
- {L"mmmm", L"%B"}, {L"mmm", L"%b"}, {L"mm", L"%m"}, {L"dddd", L"%A"},
- {L"ddd", L"%a"}, {L"dd", L"%d"}, {L"yyyy", L"%Y"}, {L"yy", L"%y"},
- {L"HH", L"%H"}, {L"hh", L"%I"}, {L"MM", L"%M"}, {L"ss", L"%S"},
- {L"TT", L"%p"},
-#if defined(_WIN32)
- {L"tt", L"%p"}, {L"h", L"%#I"},
-#else
- {L"tt", L"%P"}, {L"h", L"%l"},
-#endif
-};
-
-int ParseDataType(std::wstring* sFormat) {
- bool bPercent = false;
- for (size_t i = 0; i < sFormat->length(); ++i) {
- wchar_t c = (*sFormat)[i];
- if (c == L'%') {
- bPercent = true;
- continue;
- }
-
- if (bPercent) {
- if (c == L'c' || c == L'C' || c == L'd' || c == L'i' || c == L'o' ||
- c == L'u' || c == L'x' || c == L'X') {
- return UTIL_INT;
- }
- if (c == L'e' || c == L'E' || c == L'f' || c == L'g' || c == L'G') {
- return UTIL_DOUBLE;
- }
- if (c == L's' || c == L'S') {
- // Map s to S since we always deal internally
- // with wchar_t strings.
- (*sFormat)[i] = L'S';
- return UTIL_STRING;
- }
- if (c == L'.' || c == L'+' || c == L'-' || c == L'#' || c == L' ' ||
- FXSYS_iswdigit(c)) {
- continue;
- }
- break;
- }
- }
-
- return -1;
-}
-
-} // namespace
-
-util::util(CJS_Object* pJSObject) : CJS_EmbedObj(pJSObject) {}
-
-util::~util() {}
-
-bool util::printf(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int iSize = params.size();
- if (iSize < 1)
- return false;
- std::wstring c_ConvChar(params[0].ToCFXWideString(pRuntime).c_str());
- std::vector<std::wstring> c_strConvers;
- int iOffset = 0;
- int iOffend = 0;
- c_ConvChar.insert(c_ConvChar.begin(), L'S');
- while (iOffset != -1) {
- iOffend = c_ConvChar.find(L"%", iOffset + 1);
- std::wstring strSub;
- if (iOffend == -1)
- strSub = c_ConvChar.substr(iOffset);
- else
- strSub = c_ConvChar.substr(iOffset, iOffend - iOffset);
- c_strConvers.push_back(strSub);
- iOffset = iOffend;
- }
-
- std::wstring c_strResult;
- std::wstring c_strFormat;
- for (int iIndex = 0; iIndex < (int)c_strConvers.size(); iIndex++) {
- c_strFormat = c_strConvers[iIndex];
- if (iIndex == 0) {
- c_strResult = c_strFormat;
- continue;
- }
-
- CFX_WideString strSegment;
- if (iIndex >= iSize) {
- c_strResult += c_strFormat;
- continue;
- }
-
- switch (ParseDataType(&c_strFormat)) {
- case UTIL_INT:
- strSegment.Format(c_strFormat.c_str(), params[iIndex].ToInt(pRuntime));
- break;
- case UTIL_DOUBLE:
- strSegment.Format(c_strFormat.c_str(),
- params[iIndex].ToDouble(pRuntime));
- break;
- case UTIL_STRING:
- strSegment.Format(c_strFormat.c_str(),
- params[iIndex].ToCFXWideString(pRuntime).c_str());
- break;
- default:
- strSegment.Format(L"%S", c_strFormat.c_str());
- break;
- }
- c_strResult += strSegment.GetBuffer(strSegment.GetLength() + 1);
- }
-
- c_strResult.erase(c_strResult.begin());
- vRet = CJS_Value(pRuntime, c_strResult.c_str());
- return true;
-}
-
-bool util::printd(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int iSize = params.size();
- if (iSize < 2)
- return false;
-
- CJS_Value p1 = params[0];
- CJS_Value p2 = params[1];
- CJS_Date jsDate;
- if (!p2.ConvertToDate(pRuntime, jsDate)) {
- sError = JSGetStringFromID(IDS_STRING_JSPRINT1);
- return false;
- }
-
- if (!jsDate.IsValidDate(pRuntime)) {
- sError = JSGetStringFromID(IDS_STRING_JSPRINT2);
- return false;
- }
-
- if (p1.GetType() == CJS_Value::VT_number) {
- CFX_WideString swResult;
- switch (p1.ToInt(pRuntime)) {
- case 0:
- swResult.Format(L"D:%04d%02d%02d%02d%02d%02d", jsDate.GetYear(pRuntime),
- jsDate.GetMonth(pRuntime) + 1, jsDate.GetDay(pRuntime),
- jsDate.GetHours(pRuntime), jsDate.GetMinutes(pRuntime),
- jsDate.GetSeconds(pRuntime));
- break;
- case 1:
- swResult.Format(L"%04d.%02d.%02d %02d:%02d:%02d",
- jsDate.GetYear(pRuntime), jsDate.GetMonth(pRuntime) + 1,
- jsDate.GetDay(pRuntime), jsDate.GetHours(pRuntime),
- jsDate.GetMinutes(pRuntime),
- jsDate.GetSeconds(pRuntime));
- break;
- case 2:
- swResult.Format(L"%04d/%02d/%02d %02d:%02d:%02d",
- jsDate.GetYear(pRuntime), jsDate.GetMonth(pRuntime) + 1,
- jsDate.GetDay(pRuntime), jsDate.GetHours(pRuntime),
- jsDate.GetMinutes(pRuntime),
- jsDate.GetSeconds(pRuntime));
- break;
- default:
- sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
- return false;
- }
-
- vRet = CJS_Value(pRuntime, swResult.c_str());
- return true;
- }
-
- if (p1.GetType() == CJS_Value::VT_string) {
- if (iSize > 2 && params[2].ToBool(pRuntime)) {
- sError = JSGetStringFromID(IDS_STRING_JSNOTSUPPORT);
- return false; // currently, it doesn't support XFAPicture.
- }
-
- // Convert PDF-style format specifiers to wcsftime specifiers. Remove any
- // pre-existing %-directives before inserting our own.
- std::basic_string<wchar_t> cFormat = p1.ToCFXWideString(pRuntime).c_str();
- cFormat.erase(std::remove(cFormat.begin(), cFormat.end(), '%'),
- cFormat.end());
-
- for (size_t i = 0; i < FX_ArraySize(TbConvertTable); ++i) {
- int iStart = 0;
- int iEnd;
- while ((iEnd = cFormat.find(TbConvertTable[i].lpszJSMark, iStart)) !=
- -1) {
- cFormat.replace(iEnd, FXSYS_wcslen(TbConvertTable[i].lpszJSMark),
- TbConvertTable[i].lpszCppMark);
- iStart = iEnd;
- }
- }
-
- int iYear = jsDate.GetYear(pRuntime);
- int iMonth = jsDate.GetMonth(pRuntime);
- int iDay = jsDate.GetDay(pRuntime);
- int iHour = jsDate.GetHours(pRuntime);
- int iMin = jsDate.GetMinutes(pRuntime);
- int iSec = jsDate.GetSeconds(pRuntime);
-
- TbConvertAdditional cTableAd[] = {
- {L"m", iMonth + 1}, {L"d", iDay},
- {L"H", iHour}, {L"h", iHour > 12 ? iHour - 12 : iHour},
- {L"M", iMin}, {L"s", iSec},
- };
-
- for (size_t i = 0; i < FX_ArraySize(cTableAd); ++i) {
- wchar_t tszValue[16];
- CFX_WideString sValue;
- sValue.Format(L"%d", cTableAd[i].iValue);
- memcpy(tszValue, (wchar_t*)sValue.GetBuffer(sValue.GetLength() + 1),
- (sValue.GetLength() + 1) * sizeof(wchar_t));
-
- int iStart = 0;
- int iEnd;
- while ((iEnd = cFormat.find(cTableAd[i].lpszJSMark, iStart)) != -1) {
- if (iEnd > 0) {
- if (cFormat[iEnd - 1] == L'%') {
- iStart = iEnd + 1;
- continue;
- }
- }
- cFormat.replace(iEnd, FXSYS_wcslen(cTableAd[i].lpszJSMark), tszValue);
- iStart = iEnd;
- }
- }
-
- struct tm time = {};
- time.tm_year = iYear - 1900;
- time.tm_mon = iMonth;
- time.tm_mday = iDay;
- time.tm_hour = iHour;
- time.tm_min = iMin;
- time.tm_sec = iSec;
-
- wchar_t buf[64] = {};
- wcsftime(buf, 64, cFormat.c_str(), &time);
- cFormat = buf;
- vRet = CJS_Value(pRuntime, cFormat.c_str());
- return true;
- }
-
- sError = JSGetStringFromID(IDS_STRING_JSTYPEERROR);
- return false;
-}
-
-bool util::printx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() < 2) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- vRet = CJS_Value(pRuntime, printx(params[0].ToCFXWideString(pRuntime),
- params[1].ToCFXWideString(pRuntime))
- .c_str());
-
- return true;
-}
-
-enum CaseMode { kPreserveCase, kUpperCase, kLowerCase };
-
-static FX_WCHAR TranslateCase(FX_WCHAR input, CaseMode eMode) {
- if (eMode == kLowerCase && input >= 'A' && input <= 'Z')
- return input | 0x20;
- if (eMode == kUpperCase && input >= 'a' && input <= 'z')
- return input & ~0x20;
- return input;
-}
-
-CFX_WideString util::printx(const CFX_WideString& wsFormat,
- const CFX_WideString& wsSource) {
- CFX_WideString wsResult;
- FX_STRSIZE iSourceIdx = 0;
- FX_STRSIZE iFormatIdx = 0;
- CaseMode eCaseMode = kPreserveCase;
- bool bEscaped = false;
- while (iFormatIdx < wsFormat.GetLength()) {
- if (bEscaped) {
- bEscaped = false;
- wsResult += wsFormat[iFormatIdx];
- ++iFormatIdx;
- continue;
- }
- switch (wsFormat[iFormatIdx]) {
- case '\\': {
- bEscaped = true;
- ++iFormatIdx;
- } break;
- case '<': {
- eCaseMode = kLowerCase;
- ++iFormatIdx;
- } break;
- case '>': {
- eCaseMode = kUpperCase;
- ++iFormatIdx;
- } break;
- case '=': {
- eCaseMode = kPreserveCase;
- ++iFormatIdx;
- } break;
- case '?': {
- if (iSourceIdx < wsSource.GetLength()) {
- wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
- ++iSourceIdx;
- }
- ++iFormatIdx;
- } break;
- case 'X': {
- if (iSourceIdx < wsSource.GetLength()) {
- if ((wsSource[iSourceIdx] >= '0' && wsSource[iSourceIdx] <= '9') ||
- (wsSource[iSourceIdx] >= 'a' && wsSource[iSourceIdx] <= 'z') ||
- (wsSource[iSourceIdx] >= 'A' && wsSource[iSourceIdx] <= 'Z')) {
- wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
- ++iFormatIdx;
- }
- ++iSourceIdx;
- } else {
- ++iFormatIdx;
- }
- } break;
- case 'A': {
- if (iSourceIdx < wsSource.GetLength()) {
- if ((wsSource[iSourceIdx] >= 'a' && wsSource[iSourceIdx] <= 'z') ||
- (wsSource[iSourceIdx] >= 'A' && wsSource[iSourceIdx] <= 'Z')) {
- wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
- ++iFormatIdx;
- }
- ++iSourceIdx;
- } else {
- ++iFormatIdx;
- }
- } break;
- case '9': {
- if (iSourceIdx < wsSource.GetLength()) {
- if (wsSource[iSourceIdx] >= '0' && wsSource[iSourceIdx] <= '9') {
- wsResult += wsSource[iSourceIdx];
- ++iFormatIdx;
- }
- ++iSourceIdx;
- } else {
- ++iFormatIdx;
- }
- } break;
- case '*': {
- if (iSourceIdx < wsSource.GetLength()) {
- wsResult += TranslateCase(wsSource[iSourceIdx], eCaseMode);
- ++iSourceIdx;
- } else {
- ++iFormatIdx;
- }
- } break;
- default: {
- wsResult += wsFormat[iFormatIdx];
- ++iFormatIdx;
- } break;
- }
- }
- return wsResult;
-}
-
-bool util::scand(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- int iSize = params.size();
- if (iSize < 2)
- return false;
-
- CFX_WideString sFormat = params[0].ToCFXWideString(pRuntime);
- CFX_WideString sDate = params[1].ToCFXWideString(pRuntime);
- double dDate = JS_GetDateTime();
- if (sDate.GetLength() > 0) {
- dDate = CJS_PublicMethods::MakeRegularDate(sDate, sFormat, nullptr);
- }
-
- if (!JS_PortIsNan(dDate)) {
- vRet = CJS_Value(pRuntime, CJS_Date(pRuntime, dDate));
- } else {
- vRet.SetNull(pRuntime);
- }
-
- return true;
-}
-
-bool util::byteToChar(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError) {
- if (params.size() < 1) {
- sError = JSGetStringFromID(IDS_STRING_JSPARAMERROR);
- return false;
- }
-
- int arg = params[0].ToInt(pRuntime);
- if (arg < 0 || arg > 255) {
- sError = JSGetStringFromID(IDS_STRING_JSVALUEERROR);
- return false;
- }
-
- CFX_WideString wStr(static_cast<FX_WCHAR>(arg));
- vRet = CJS_Value(pRuntime, wStr.c_str());
- return true;
-}
diff --git a/fpdfsdk/javascript/util.h b/fpdfsdk/javascript/util.h
deleted file mode 100644
index 98761b6..0000000
--- a/fpdfsdk/javascript/util.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2014 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_JAVASCRIPT_UTIL_H_
-#define FPDFSDK_JAVASCRIPT_UTIL_H_
-
-#include <string>
-#include <vector>
-
-#include "fpdfsdk/javascript/JS_Define.h"
-
-class util : public CJS_EmbedObj {
- public:
- explicit util(CJS_Object* pJSObject);
- ~util() override;
-
- bool printd(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool printf(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool printx(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool scand(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
- bool byteToChar(CJS_Runtime* pRuntime,
- const std::vector<CJS_Value>& params,
- CJS_Value& vRet,
- CFX_WideString& sError);
-
- static CFX_WideString printx(const CFX_WideString& cFormat,
- const CFX_WideString& cSource);
-};
-
-class CJS_Util : public CJS_Object {
- public:
- explicit CJS_Util(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
- ~CJS_Util() override {}
-
- DECLARE_JS_CLASS();
-
- JS_STATIC_METHOD(printd, util);
- JS_STATIC_METHOD(printf, util);
- JS_STATIC_METHOD(printx, util);
- JS_STATIC_METHOD(scand, util);
- JS_STATIC_METHOD(byteToChar, util);
-};
-
-#endif // FPDFSDK_JAVASCRIPT_UTIL_H_
diff --git a/fpdfsdk/pdfsdk_fieldaction.h b/fpdfsdk/pdfsdk_fieldaction.h
index 4ee56ac..aec5dca 100644
--- a/fpdfsdk/pdfsdk_fieldaction.h
+++ b/fpdfsdk/pdfsdk_fieldaction.h
@@ -25,12 +25,12 @@
bool bModifier;
bool bShift;
int nCommitKey;
- CFX_WideString sChange;
- CFX_WideString sChangeEx;
+ WideString sChange;
+ WideString sChangeEx;
bool bKeyDown;
int nSelEnd;
int nSelStart;
- CFX_WideString sValue;
+ WideString sValue;
bool bWillCommit;
bool bFieldFull;
bool bRC;
diff --git a/fpdfsdk/pdfwindow/PWL_Caret.cpp b/fpdfsdk/pdfwindow/PWL_Caret.cpp
deleted file mode 100644
index 3360bbf..0000000
--- a/fpdfsdk/pdfwindow/PWL_Caret.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2014 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/PWL_Caret.h"
-
-#include "core/fxge/cfx_graphstatedata.h"
-#include "core/fxge/cfx_pathdata.h"
-#include "core/fxge/cfx_renderdevice.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-#define PWL_CARET_FLASHINTERVAL 500
-
-PWL_CARET_INFO::PWL_CARET_INFO() : bVisible(false) {}
-
-CPWL_Caret::CPWL_Caret() : m_bFlash(false), m_fWidth(0.4f), m_nDelay(0) {}
-
-CPWL_Caret::~CPWL_Caret() {}
-
-CFX_ByteString CPWL_Caret::GetClassName() const {
- return "CPWL_Caret";
-}
-
-void CPWL_Caret::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- GetCaretApp(sAppStream, CFX_PointF());
-}
-
-void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- if (IsVisible() && m_bFlash) {
- CFX_FloatRect rcRect = GetCaretRect();
- CFX_FloatRect rcClip = GetClipRect();
- CFX_PathData path;
-
- FX_FLOAT fCaretX = rcRect.left + m_fWidth * 0.5f;
- FX_FLOAT fCaretTop = rcRect.top;
- FX_FLOAT fCaretBottom = rcRect.bottom;
- if (!rcClip.IsEmpty()) {
- rcRect.Intersect(rcClip);
- if (rcRect.IsEmpty())
- return;
-
- fCaretTop = rcRect.top;
- fCaretBottom = rcRect.bottom;
- }
-
- path.AppendPoint(CFX_PointF(fCaretX, fCaretBottom), FXPT_TYPE::MoveTo,
- false);
- path.AppendPoint(CFX_PointF(fCaretX, fCaretTop), FXPT_TYPE::LineTo, false);
-
- CFX_GraphStateData gsd;
- gsd.m_LineWidth = m_fWidth;
- pDevice->DrawPath(&path, pUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0),
- FXFILL_ALTERNATE);
- }
-}
-
-void CPWL_Caret::GetCaretApp(CFX_ByteTextBuf& sAppStream,
- const CFX_PointF& ptOffset) {
- if (IsVisible() && m_bFlash) {
- CFX_ByteTextBuf sCaret;
-
- CFX_FloatRect rcRect = GetCaretRect();
- CFX_FloatRect rcClip = GetClipRect();
-
- rcRect = CPWL_Utils::OffsetRect(rcRect, ptOffset.x, ptOffset.y);
- rcClip = CPWL_Utils::OffsetRect(rcClip, ptOffset.x, ptOffset.y);
-
- sCaret << "q\n";
- if (!rcClip.IsEmpty()) {
- sCaret << rcClip.left << " " << rcClip.bottom + 2.5f << " "
- << rcClip.right - rcClip.left << " "
- << rcClip.top - rcClip.bottom - 4.5f << " re W n\n";
- }
- sCaret << m_fWidth << " w\n0 G\n";
- sCaret << rcRect.left + m_fWidth / 2 << " " << rcRect.bottom << " m\n";
- sCaret << rcRect.left + m_fWidth / 2 << " " << rcRect.top << " l S\nQ\n";
-
- sAppStream << sCaret;
- }
-}
-
-CFX_ByteString CPWL_Caret::GetCaretAppearanceStream(
- const CFX_PointF& ptOffset) {
- CFX_ByteTextBuf sCaret;
- GetCaretApp(sCaret, ptOffset);
- return sCaret.MakeString();
-}
-
-void CPWL_Caret::TimerProc() {
- if (m_nDelay > 0) {
- m_nDelay--;
- } else {
- m_bFlash = !m_bFlash;
- InvalidateRect();
- }
-}
-
-CFX_FloatRect CPWL_Caret::GetCaretRect() const {
- return CFX_FloatRect(m_ptFoot.x, m_ptFoot.y, m_ptHead.x + m_fWidth,
- m_ptHead.y);
-}
-
-void CPWL_Caret::SetCaret(bool bVisible,
- const CFX_PointF& ptHead,
- const CFX_PointF& ptFoot) {
- if (bVisible) {
- if (IsVisible()) {
- if (m_ptHead != ptHead || m_ptFoot != ptFoot) {
- m_ptHead = ptHead;
- m_ptFoot = ptFoot;
- m_bFlash = true;
- Move(m_rcInvalid, false, true);
- }
- } else {
- m_ptHead = ptHead;
- m_ptFoot = ptFoot;
- EndTimer();
- BeginTimer(PWL_CARET_FLASHINTERVAL);
- CPWL_Wnd::SetVisible(true);
- m_bFlash = true;
- Move(m_rcInvalid, false, true);
- }
- } else {
- m_ptHead = CFX_PointF();
- m_ptFoot = CFX_PointF();
- m_bFlash = false;
- if (IsVisible()) {
- EndTimer();
- CPWL_Wnd::SetVisible(false);
- }
- }
-}
-
-void CPWL_Caret::InvalidateRect(CFX_FloatRect* pRect) {
- if (pRect) {
- CFX_FloatRect rcRefresh = CPWL_Utils::InflateRect(*pRect, 0.5f);
- rcRefresh.top += 1;
- rcRefresh.bottom -= 1;
- CPWL_Wnd::InvalidateRect(&rcRefresh);
- } else {
- CPWL_Wnd::InvalidateRect(pRect);
- }
-}
diff --git a/fpdfsdk/pdfwindow/PWL_Caret.h b/fpdfsdk/pdfwindow/PWL_Caret.h
deleted file mode 100644
index 60ebbdc..0000000
--- a/fpdfsdk/pdfwindow/PWL_Caret.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 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_PWL_CARET_H_
-#define FPDFSDK_PDFWINDOW_PWL_CARET_H_
-
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-struct PWL_CARET_INFO {
- public:
- PWL_CARET_INFO();
-
- bool bVisible;
- CFX_PointF ptHead;
- CFX_PointF ptFoot;
-};
-
-class CPWL_Caret : public CPWL_Wnd {
- public:
- CPWL_Caret();
- ~CPWL_Caret() override;
-
- // CPWL_Wnd
- CFX_ByteString GetClassName() const override;
- void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override;
- void DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
- void InvalidateRect(CFX_FloatRect* pRect = nullptr) override;
- void SetVisible(bool bVisible) override {}
- void TimerProc() override;
-
- void SetCaret(bool bVisible,
- const CFX_PointF& ptHead,
- const CFX_PointF& ptFoot);
- CFX_ByteString GetCaretAppearanceStream(const CFX_PointF& ptOffset);
- void SetInvalidRect(CFX_FloatRect rc) { m_rcInvalid = rc; }
-
- private:
- void GetCaretApp(CFX_ByteTextBuf& sAppStream, const CFX_PointF& ptOffset);
- CFX_FloatRect GetCaretRect() const;
-
- bool m_bFlash;
- CFX_PointF m_ptHead;
- CFX_PointF m_ptFoot;
- FX_FLOAT m_fWidth;
- int32_t m_nDelay;
- CFX_FloatRect m_rcInvalid;
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_CARET_H_
diff --git a/fpdfsdk/pdfwindow/PWL_ComboBox.cpp b/fpdfsdk/pdfwindow/PWL_ComboBox.cpp
deleted file mode 100644
index bc6909a..0000000
--- a/fpdfsdk/pdfwindow/PWL_ComboBox.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-// Copyright 2014 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/PWL_ComboBox.h"
-
-#include "core/fxge/cfx_pathdata.h"
-#include "core/fxge/cfx_renderdevice.h"
-#include "fpdfsdk/fxedit/fxet_list.h"
-#include "fpdfsdk/pdfwindow/PWL_Edit.h"
-#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h"
-#include "fpdfsdk/pdfwindow/PWL_ListBox.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-#include "public/fpdf_fwlevent.h"
-
-#define PWLCB_DEFAULTFONTSIZE 12.0f
-
-bool CPWL_CBListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonUp(point, nFlag);
-
- if (!m_bMouseDown)
- return true;
-
- ReleaseCapture();
- m_bMouseDown = false;
-
- if (!ClientHitTest(point))
- return true;
- if (CPWL_Wnd* pParent = GetParentWindow())
- pParent->OnNotify(this, PNM_LBUTTONUP, 0, PWL_MAKEDWORD(point.x, point.y));
-
- bool bExit = false;
- OnNotifySelChanged(false, bExit, nFlag);
-
- return !bExit;
-}
-
-bool CPWL_CBListBox::OnKeyDownWithExit(uint16_t nChar,
- bool& bExit,
- uint32_t nFlag) {
- switch (nChar) {
- case FWL_VKEY_Up:
- case FWL_VKEY_Down:
- case FWL_VKEY_Home:
- case FWL_VKEY_Left:
- case FWL_VKEY_End:
- case FWL_VKEY_Right:
- break;
- default:
- return false;
- }
-
- switch (nChar) {
- case FWL_VKEY_Up:
- m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Down:
- m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Home:
- m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Left:
- m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_End:
- m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Right:
- m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Delete:
- break;
- }
-
- OnNotifySelChanged(true, bExit, nFlag);
-
- return true;
-}
-
-bool CPWL_CBListBox::OnCharWithExit(uint16_t nChar,
- bool& bExit,
- uint32_t nFlag) {
- if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)))
- return false;
- if (CPWL_ComboBox* pComboBox = (CPWL_ComboBox*)GetParentWindow())
- pComboBox->SetSelectText();
-
- OnNotifySelChanged(true, bExit, nFlag);
-
- return true;
-}
-
-void CPWL_CBButton::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- CPWL_Wnd::GetThisAppearanceStream(sAppStream);
-
- CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect();
-
- if (IsVisible() && !rectWnd.IsEmpty()) {
- CFX_ByteTextBuf sButton;
-
- CFX_PointF ptCenter = GetCenterPoint();
-
- CFX_PointF pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN,
- ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
- CFX_PointF pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN,
- ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
- CFX_PointF pt3(ptCenter.x,
- ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
-
- if (IsFloatBigger(rectWnd.right - rectWnd.left,
- PWL_CBBUTTON_TRIANGLE_HALFLEN * 2) &&
- IsFloatBigger(rectWnd.top - rectWnd.bottom,
- PWL_CBBUTTON_TRIANGLE_HALFLEN)) {
- sButton << "0 g\n";
- sButton << pt1.x << " " << pt1.y << " m\n";
- sButton << pt2.x << " " << pt2.y << " l\n";
- sButton << pt3.x << " " << pt3.y << " l\n";
- sButton << pt1.x << " " << pt1.y << " l f\n";
-
- sAppStream << "q\n" << sButton << "Q\n";
- }
- }
-}
-
-void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
-
- CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect();
-
- if (IsVisible() && !rectWnd.IsEmpty()) {
- CFX_PointF ptCenter = GetCenterPoint();
-
- CFX_PointF pt1(ptCenter.x - PWL_CBBUTTON_TRIANGLE_HALFLEN,
- ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
- CFX_PointF pt2(ptCenter.x + PWL_CBBUTTON_TRIANGLE_HALFLEN,
- ptCenter.y + PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
- CFX_PointF pt3(ptCenter.x,
- ptCenter.y - PWL_CBBUTTON_TRIANGLE_HALFLEN * 0.5f);
-
- if (IsFloatBigger(rectWnd.right - rectWnd.left,
- PWL_CBBUTTON_TRIANGLE_HALFLEN * 2) &&
- IsFloatBigger(rectWnd.top - rectWnd.bottom,
- PWL_CBBUTTON_TRIANGLE_HALFLEN)) {
- CFX_PathData path;
- path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
- path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
- path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
- path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
-
- pDevice->DrawPath(&path, pUser2Device, nullptr,
- PWL_DEFAULT_BLACKCOLOR.ToFXColor(GetTransparency()), 0,
- FXFILL_ALTERNATE);
- }
- }
-}
-
-bool CPWL_CBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonDown(point, nFlag);
-
- SetCapture();
-
- if (CPWL_Wnd* pParent = GetParentWindow()) {
- pParent->OnNotify(this, PNM_LBUTTONDOWN, 0,
- PWL_MAKEDWORD(point.x, point.y));
- }
-
- return true;
-}
-
-bool CPWL_CBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonUp(point, nFlag);
-
- ReleaseCapture();
-
- return true;
-}
-
-CPWL_ComboBox::CPWL_ComboBox()
- : m_pEdit(nullptr),
- m_pButton(nullptr),
- m_pList(nullptr),
- m_bPopup(false),
- m_nPopupWhere(0),
- m_nSelectItem(-1),
- m_pFillerNotify(nullptr) {}
-
-CFX_ByteString CPWL_ComboBox::GetClassName() const {
- return "CPWL_ComboBox";
-}
-
-void CPWL_ComboBox::OnCreate(PWL_CREATEPARAM& cp) {
- cp.dwFlags &= ~PWS_HSCROLL;
- cp.dwFlags &= ~PWS_VSCROLL;
-}
-
-void CPWL_ComboBox::SetFocus() {
- if (m_pEdit)
- m_pEdit->SetFocus();
-}
-
-void CPWL_ComboBox::KillFocus() {
- SetPopup(false);
- CPWL_Wnd::KillFocus();
-}
-
-CFX_WideString CPWL_ComboBox::GetText() const {
- if (m_pEdit) {
- return m_pEdit->GetText();
- }
- return CFX_WideString();
-}
-
-void CPWL_ComboBox::SetText(const CFX_WideString& text) {
- if (m_pEdit)
- m_pEdit->SetText(text);
-}
-
-void CPWL_ComboBox::AddString(const CFX_WideString& str) {
- if (m_pList)
- m_pList->AddString(str);
-}
-
-int32_t CPWL_ComboBox::GetSelect() const {
- return m_nSelectItem;
-}
-
-void CPWL_ComboBox::SetSelect(int32_t nItemIndex) {
- if (m_pList)
- m_pList->Select(nItemIndex);
-
- m_pEdit->SetText(m_pList->GetText());
- m_nSelectItem = nItemIndex;
-}
-
-void CPWL_ComboBox::SetEditSel(int32_t nStartChar, int32_t nEndChar) {
- if (m_pEdit)
- m_pEdit->SetSel(nStartChar, nEndChar);
-}
-
-void CPWL_ComboBox::GetEditSel(int32_t& nStartChar, int32_t& nEndChar) const {
- nStartChar = -1;
- nEndChar = -1;
-
- if (m_pEdit)
- m_pEdit->GetSel(nStartChar, nEndChar);
-}
-
-void CPWL_ComboBox::Clear() {
- if (m_pEdit)
- m_pEdit->Clear();
-}
-
-void CPWL_ComboBox::CreateChildWnd(const PWL_CREATEPARAM& cp) {
- CreateEdit(cp);
- CreateButton(cp);
- CreateListBox(cp);
-}
-
-void CPWL_ComboBox::CreateEdit(const PWL_CREATEPARAM& cp) {
- if (!m_pEdit) {
- m_pEdit = new CPWL_CBEdit;
- m_pEdit->AttachFFLData(m_pFormFiller);
-
- PWL_CREATEPARAM ecp = cp;
- ecp.pParentWnd = this;
- ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER |
- PES_AUTOSCROLL | PES_UNDO;
-
- if (HasFlag(PWS_AUTOFONTSIZE))
- ecp.dwFlags |= PWS_AUTOFONTSIZE;
-
- if (!HasFlag(PCBS_ALLOWCUSTOMTEXT))
- ecp.dwFlags |= PWS_READONLY;
-
- ecp.rcRectWnd = CFX_FloatRect(0, 0, 0, 0);
- ecp.dwBorderWidth = 0;
- ecp.nBorderStyle = BorderStyle::SOLID;
-
- m_pEdit->Create(ecp);
- }
-}
-
-void CPWL_ComboBox::CreateButton(const PWL_CREATEPARAM& cp) {
- if (!m_pButton) {
- m_pButton = new CPWL_CBButton;
-
- PWL_CREATEPARAM bcp = cp;
- bcp.pParentWnd = this;
- bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND;
- bcp.sBackgroundColor = PWL_SCROLLBAR_BKCOLOR;
- bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
- bcp.dwBorderWidth = 2;
- bcp.nBorderStyle = BorderStyle::BEVELED;
- bcp.eCursorType = FXCT_ARROW;
-
- m_pButton->Create(bcp);
- }
-}
-
-void CPWL_ComboBox::CreateListBox(const PWL_CREATEPARAM& cp) {
- if (!m_pList) {
- m_pList = new CPWL_CBListBox;
- m_pList->AttachFFLData(m_pFormFiller);
- PWL_CREATEPARAM lcp = cp;
- lcp.pParentWnd = this;
- lcp.dwFlags =
- PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL;
- lcp.nBorderStyle = BorderStyle::SOLID;
- lcp.dwBorderWidth = 1;
- lcp.eCursorType = FXCT_ARROW;
- lcp.rcRectWnd = CFX_FloatRect(0, 0, 0, 0);
-
- if (cp.dwFlags & PWS_AUTOFONTSIZE)
- lcp.fFontSize = PWLCB_DEFAULTFONTSIZE;
- else
- lcp.fFontSize = cp.fFontSize;
-
- if (cp.sBorderColor.nColorType == COLORTYPE_TRANSPARENT)
- lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
-
- if (cp.sBackgroundColor.nColorType == COLORTYPE_TRANSPARENT)
- lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
-
- m_pList->Create(lcp);
- }
-}
-
-void CPWL_ComboBox::RePosChildWnd() {
- CFX_FloatRect rcClient = GetClientRect();
-
- if (m_bPopup) {
- CFX_FloatRect rclient = GetClientRect();
- CFX_FloatRect rcButton = rclient;
- CFX_FloatRect rcEdit = rcClient;
- CFX_FloatRect rcList = CPWL_Wnd::GetWindowRect();
-
- FX_FLOAT fOldWindowHeight = m_rcOldWindow.Height();
- FX_FLOAT fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2;
-
- switch (m_nPopupWhere) {
- case 0:
- rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;
-
- if (rcButton.left < rclient.left)
- rcButton.left = rclient.left;
-
- rcButton.bottom = rcButton.top - fOldClientHeight;
-
- rcEdit.right = rcButton.left - 1.0f;
-
- if (rcEdit.left < rclient.left)
- rcEdit.left = rclient.left;
-
- if (rcEdit.right < rcEdit.left)
- rcEdit.right = rcEdit.left;
-
- rcEdit.bottom = rcEdit.top - fOldClientHeight;
-
- rcList.top -= fOldWindowHeight;
-
- break;
- case 1:
- rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;
-
- if (rcButton.left < rclient.left)
- rcButton.left = rclient.left;
-
- rcButton.top = rcButton.bottom + fOldClientHeight;
-
- rcEdit.right = rcButton.left - 1.0f;
-
- if (rcEdit.left < rclient.left)
- rcEdit.left = rclient.left;
-
- if (rcEdit.right < rcEdit.left)
- rcEdit.right = rcEdit.left;
-
- rcEdit.top = rcEdit.bottom + fOldClientHeight;
-
- rcList.bottom += fOldWindowHeight;
-
- break;
- }
-
- if (m_pButton)
- m_pButton->Move(rcButton, true, false);
-
- if (m_pEdit)
- m_pEdit->Move(rcEdit, true, false);
-
- if (m_pList) {
- m_pList->SetVisible(true);
- m_pList->Move(rcList, true, false);
- m_pList->ScrollToListItem(m_nSelectItem);
- }
- } else {
- CFX_FloatRect rcButton = rcClient;
-
- rcButton.left = rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH;
-
- if (rcButton.left < rcClient.left)
- rcButton.left = rcClient.left;
-
- if (m_pButton)
- m_pButton->Move(rcButton, true, false);
-
- CFX_FloatRect rcEdit = rcClient;
- rcEdit.right = rcButton.left - 1.0f;
-
- if (rcEdit.left < rcClient.left)
- rcEdit.left = rcClient.left;
-
- if (rcEdit.right < rcEdit.left)
- rcEdit.right = rcEdit.left;
-
- if (m_pEdit)
- m_pEdit->Move(rcEdit, true, false);
-
- if (m_pList)
- m_pList->SetVisible(false);
- }
-}
-
-void CPWL_ComboBox::SelectAll() {
- if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT))
- m_pEdit->SelectAll();
-}
-
-CFX_FloatRect CPWL_ComboBox::GetFocusRect() const {
- return CFX_FloatRect();
-}
-
-void CPWL_ComboBox::SetPopup(bool bPopup) {
- if (!m_pList)
- return;
- if (bPopup == m_bPopup)
- return;
- FX_FLOAT fListHeight = m_pList->GetContentRect().Height();
- if (!IsFloatBigger(fListHeight, 0.0f))
- return;
-
- if (bPopup) {
- if (m_pFillerNotify) {
-#ifdef PDF_ENABLE_XFA
- bool bExit = false;
- m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, 0);
- if (bExit)
- return;
-#endif // PDF_ENABLE_XFA
- int32_t nWhere = 0;
- FX_FLOAT fPopupRet = 0.0f;
- FX_FLOAT fPopupMin = 0.0f;
- if (m_pList->GetCount() > 3)
- fPopupMin =
- m_pList->GetFirstHeight() * 3 + m_pList->GetBorderWidth() * 2;
- FX_FLOAT fPopupMax = fListHeight + m_pList->GetBorderWidth() * 2;
- m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin, fPopupMax,
- nWhere, fPopupRet);
-
- if (IsFloatBigger(fPopupRet, 0.0f)) {
- m_bPopup = bPopup;
-
- CFX_FloatRect rcWindow = CPWL_Wnd::GetWindowRect();
- m_rcOldWindow = rcWindow;
- switch (nWhere) {
- default:
- case 0:
- rcWindow.bottom -= fPopupRet;
- break;
- case 1:
- rcWindow.top += fPopupRet;
- break;
- }
-
- m_nPopupWhere = nWhere;
- Move(rcWindow, true, true);
-#ifdef PDF_ENABLE_XFA
- bExit = false;
- m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, 0);
- if (bExit)
- return;
-#endif // PDF_ENABLE_XFA
- }
- }
- } else {
- m_bPopup = bPopup;
- Move(m_rcOldWindow, true, true);
- }
-}
-
-bool CPWL_ComboBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
- if (!m_pList)
- return false;
- if (!m_pEdit)
- return false;
-
- m_nSelectItem = -1;
-
- switch (nChar) {
- case FWL_VKEY_Up:
- if (m_pList->GetCurSel() > 0) {
- bool bExit = false;
-#ifdef PDF_ENABLE_XFA
- if (m_pFillerNotify) {
- m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
- if (bExit)
- return false;
- bExit = false;
- m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
- if (bExit)
- return false;
- }
-#endif // PDF_ENABLE_XFA
- if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) {
- if (bExit)
- return false;
- SetSelectText();
- }
- }
- return true;
- case FWL_VKEY_Down:
- if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
- bool bExit = false;
-#ifdef PDF_ENABLE_XFA
- if (m_pFillerNotify) {
- m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
- if (bExit)
- return false;
- bExit = false;
- m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
- if (bExit)
- return false;
- }
-#endif // PDF_ENABLE_XFA
- if (m_pList->OnKeyDownWithExit(nChar, bExit, nFlag)) {
- if (bExit)
- return false;
- SetSelectText();
- }
- }
- return true;
- }
-
- if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
- return m_pEdit->OnKeyDown(nChar, nFlag);
-
- return false;
-}
-
-bool CPWL_ComboBox::OnChar(uint16_t nChar, uint32_t nFlag) {
- if (!m_pList)
- return false;
-
- if (!m_pEdit)
- return false;
-
- m_nSelectItem = -1;
- if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
- return m_pEdit->OnChar(nChar, nFlag);
-
- bool bExit = false;
-#ifdef PDF_ENABLE_XFA
- if (m_pFillerNotify) {
- m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), bExit, nFlag);
- if (bExit)
- return false;
-
- m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), bExit, nFlag);
- if (bExit)
- return false;
- }
-#endif // PDF_ENABLE_XFA
- return m_pList->OnCharWithExit(nChar, bExit, nFlag) ? bExit : false;
-}
-
-void CPWL_ComboBox::OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam,
- intptr_t lParam) {
- switch (msg) {
- case PNM_LBUTTONDOWN:
- if (pWnd == m_pButton) {
- SetPopup(!m_bPopup);
- return;
- }
- break;
- case PNM_LBUTTONUP:
- if (m_pEdit && m_pList) {
- if (pWnd == m_pList) {
- SetSelectText();
- SelectAll();
- m_pEdit->SetFocus();
- SetPopup(false);
- return;
- }
- }
- }
-
- CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
-}
-
-bool CPWL_ComboBox::IsPopup() const {
- return m_bPopup;
-}
-
-void CPWL_ComboBox::SetSelectText() {
- m_pEdit->SelectAll();
- m_pEdit->ReplaceSel(m_pList->GetText());
- m_pEdit->SelectAll();
- m_nSelectItem = m_pList->GetCurSel();
-}
-
-void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify) {
- m_pFillerNotify = pNotify;
-
- if (m_pEdit)
- m_pEdit->SetFillerNotify(pNotify);
-
- if (m_pList)
- m_pList->SetFillerNotify(pNotify);
-}
diff --git a/fpdfsdk/pdfwindow/PWL_ComboBox.h b/fpdfsdk/pdfwindow/PWL_ComboBox.h
deleted file mode 100644
index e1a8df7..0000000
--- a/fpdfsdk/pdfwindow/PWL_ComboBox.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2014 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_PWL_COMBOBOX_H_
-#define FPDFSDK_PDFWINDOW_PWL_COMBOBOX_H_
-
-#include "fpdfsdk/pdfwindow/PWL_Edit.h"
-#include "fpdfsdk/pdfwindow/PWL_ListBox.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-class CPWL_CBEdit : public CPWL_Edit {
- public:
- CPWL_CBEdit() {}
- ~CPWL_CBEdit() override {}
-};
-
-class CPWL_CBListBox : public CPWL_ListBox {
- public:
- CPWL_CBListBox() {}
- ~CPWL_CBListBox() override {}
-
- // CPWL_ListBox
- bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
-
- bool OnKeyDownWithExit(uint16_t nChar, bool& bExit, uint32_t nFlag);
- bool OnCharWithExit(uint16_t nChar, bool& bExit, uint32_t nFlag);
-};
-
-#define PWL_COMBOBOX_BUTTON_WIDTH 13
-
-class CPWL_CBButton : public CPWL_Wnd {
- public:
- CPWL_CBButton() {}
- ~CPWL_CBButton() override {}
-
- // CPWL_Wnd
- void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override;
- void DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
- bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
-};
-
-class CPWL_ComboBox : public CPWL_Wnd {
- public:
- CPWL_ComboBox();
- ~CPWL_ComboBox() override {}
-
- CPWL_Edit* GetEdit() const { return m_pEdit; }
-
- // CPWL_Wnd:
- CFX_ByteString GetClassName() const override;
- void OnCreate(PWL_CREATEPARAM& cp) override;
- bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override;
- bool OnChar(uint16_t nChar, uint32_t nFlag) override;
- void OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam = 0,
- intptr_t lParam = 0) override;
- void CreateChildWnd(const PWL_CREATEPARAM& cp) override;
- void RePosChildWnd() override;
- CFX_FloatRect GetFocusRect() const override;
- void SetFocus() override;
- void KillFocus() override;
-
- void SetFillerNotify(IPWL_Filler_Notify* pNotify);
-
- CFX_WideString GetText() const;
- void SetText(const CFX_WideString& text);
- void AddString(const CFX_WideString& str);
- int32_t GetSelect() const;
- void SetSelect(int32_t nItemIndex);
-
- void SetEditSel(int32_t nStartChar, int32_t nEndChar);
- void GetEditSel(int32_t& nStartChar, int32_t& nEndChar) const;
- void Clear();
- void SelectAll();
- bool IsPopup() const;
-
- void SetSelectText();
-
- void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; }
-
- private:
- void CreateEdit(const PWL_CREATEPARAM& cp);
- void CreateButton(const PWL_CREATEPARAM& cp);
- void CreateListBox(const PWL_CREATEPARAM& cp);
- void SetPopup(bool bPopup);
-
- CPWL_CBEdit* m_pEdit;
- CPWL_CBButton* m_pButton;
- CPWL_CBListBox* m_pList;
- bool m_bPopup;
- CFX_FloatRect m_rcOldWindow;
- int32_t m_nPopupWhere;
- int32_t m_nSelectItem;
- IPWL_Filler_Notify* m_pFillerNotify;
- CFFL_FormFiller* m_pFormFiller; // Not owned.
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_COMBOBOX_H_
diff --git a/fpdfsdk/pdfwindow/PWL_Edit.cpp b/fpdfsdk/pdfwindow/PWL_Edit.cpp
deleted file mode 100644
index b77aad9..0000000
--- a/fpdfsdk/pdfwindow/PWL_Edit.cpp
+++ /dev/null
@@ -1,878 +0,0 @@
-// Copyright 2014 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/PWL_Edit.h"
-
-#include <memory>
-#include <vector>
-
-#include "core/fpdfapi/font/cpdf_font.h"
-#include "core/fpdfdoc/cpvt_word.h"
-#include "core/fxcrt/fx_safe_types.h"
-#include "core/fxcrt/fx_xml.h"
-#include "core/fxge/cfx_graphstatedata.h"
-#include "core/fxge/cfx_pathdata.h"
-#include "core/fxge/cfx_renderdevice.h"
-#include "core/fxge/fx_font.h"
-#include "fpdfsdk/fxedit/fxet_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_Caret.h"
-#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h"
-#include "fpdfsdk/pdfwindow/PWL_FontMap.h"
-#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-#include "public/fpdf_fwlevent.h"
-#include "third_party/base/stl_util.h"
-
-CPWL_Edit::CPWL_Edit()
- : m_pFillerNotify(nullptr), m_bFocus(false), m_pFormFiller(nullptr) {}
-
-CPWL_Edit::~CPWL_Edit() {
- ASSERT(m_bFocus == false);
-}
-
-CFX_ByteString CPWL_Edit::GetClassName() const {
- return PWL_CLASSNAME_EDIT;
-}
-
-void CPWL_Edit::OnDestroy() {}
-
-void CPWL_Edit::SetText(const CFX_WideString& csText) {
- CFX_WideString swText = csText;
- if (!HasFlag(PES_RICH)) {
- m_pEdit->SetText(swText);
- return;
- }
-
- CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText);
- std::unique_ptr<CXML_Element> pXML(
- CXML_Element::Parse(sValue.c_str(), sValue.GetLength()));
- if (!pXML) {
- m_pEdit->SetText(swText);
- return;
- }
-
- int32_t nCount = pXML->CountChildren();
- bool bFirst = true;
-
- swText.clear();
-
- for (int32_t i = 0; i < nCount; i++) {
- CXML_Element* pSubElement = pXML->GetElement(i);
- if (!pSubElement)
- continue;
-
- CFX_ByteString tag = pSubElement->GetTagName();
- if (tag.EqualNoCase("p")) {
- int nChild = pSubElement->CountChildren();
- CFX_WideString swSection;
- for (int32_t j = 0; j < nChild; j++)
- swSection += pSubElement->GetContent(j);
-
- if (bFirst)
- bFirst = false;
- else
- swText += FWL_VKEY_Return;
- swText += swSection;
- }
- }
-
- m_pEdit->SetText(swText);
-}
-
-void CPWL_Edit::RePosChildWnd() {
- if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
- CFX_FloatRect rcWindow = m_rcOldWindow;
- CFX_FloatRect rcVScroll =
- CFX_FloatRect(rcWindow.right, rcWindow.bottom,
- rcWindow.right + PWL_SCROLLBAR_WIDTH, rcWindow.top);
- pVSB->Move(rcVScroll, true, false);
- }
-
- if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW))
- m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(
- GetClientRect(), 1.0f)); // +1 for caret beside border
-
- CPWL_EditCtrl::RePosChildWnd();
-}
-
-CFX_FloatRect CPWL_Edit::GetClientRect() const {
- CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(
- GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
-
- if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
- if (pVSB->IsVisible()) {
- rcClient.right -= PWL_SCROLLBAR_WIDTH;
- }
- }
-
- return rcClient;
-}
-
-void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, bool bPaint) {
- m_pEdit->SetAlignmentV((int32_t)nFormat, bPaint);
-}
-
-bool CPWL_Edit::CanSelectAll() const {
- return GetSelectWordRange() != m_pEdit->GetWholeWordRange();
-}
-
-bool CPWL_Edit::CanClear() const {
- return !IsReadOnly() && m_pEdit->IsSelected();
-}
-
-bool CPWL_Edit::CanCopy() const {
- return !HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) &&
- m_pEdit->IsSelected();
-}
-
-bool CPWL_Edit::CanCut() const {
- return CanCopy() && !IsReadOnly();
-}
-void CPWL_Edit::CutText() {
- if (!CanCut())
- return;
- m_pEdit->Clear();
-}
-
-void CPWL_Edit::OnCreated() {
- CPWL_EditCtrl::OnCreated();
-
- if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
- pScroll->RemoveFlag(PWS_AUTOTRANSPARENT);
- pScroll->SetTransparency(255);
- }
-
- SetParamByFlag();
-
- m_rcOldWindow = GetWindowRect();
-
- m_pEdit->SetOprNotify(this);
- m_pEdit->EnableOprNotify(true);
-}
-
-void CPWL_Edit::SetParamByFlag() {
- if (HasFlag(PES_RIGHT)) {
- m_pEdit->SetAlignmentH(2, false);
- } else if (HasFlag(PES_MIDDLE)) {
- m_pEdit->SetAlignmentH(1, false);
- } else {
- m_pEdit->SetAlignmentH(0, false);
- }
-
- if (HasFlag(PES_BOTTOM)) {
- m_pEdit->SetAlignmentV(2, false);
- } else if (HasFlag(PES_CENTER)) {
- m_pEdit->SetAlignmentV(1, false);
- } else {
- m_pEdit->SetAlignmentV(0, false);
- }
-
- if (HasFlag(PES_PASSWORD)) {
- m_pEdit->SetPasswordChar('*', false);
- }
-
- m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), false);
- m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), false);
- m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), false);
- m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), false);
- m_pEdit->EnableUndo(HasFlag(PES_UNDO));
-
- if (HasFlag(PES_TEXTOVERFLOW)) {
- SetClipRect(CFX_FloatRect(0.0f, 0.0f, 0.0f, 0.0f));
- m_pEdit->SetTextOverflow(true, false);
- } else {
- if (m_pEditCaret) {
- m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(
- GetClientRect(), 1.0f)); // +1 for caret beside border
- }
- }
-}
-
-void CPWL_Edit::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- CPWL_Wnd::GetThisAppearanceStream(sAppStream);
-
- CFX_FloatRect rcClient = GetClientRect();
- CFX_ByteTextBuf sLine;
-
- int32_t nCharArray = m_pEdit->GetCharArray();
-
- if (nCharArray > 0) {
- switch (GetBorderStyle()) {
- case BorderStyle::SOLID: {
- sLine << "q\n"
- << GetBorderWidth() << " w\n"
- << CPWL_Utils::GetColorAppStream(GetBorderColor(), false)
- .AsStringC()
- << " 2 J 0 j\n";
-
- for (int32_t i = 1; i < nCharArray; i++) {
- sLine << rcClient.left +
- ((rcClient.right - rcClient.left) / nCharArray) * i
- << " " << rcClient.bottom << " m\n"
- << rcClient.left +
- ((rcClient.right - rcClient.left) / nCharArray) * i
- << " " << rcClient.top << " l S\n";
- }
-
- sLine << "Q\n";
- break;
- }
- case BorderStyle::DASH: {
- sLine << "q\n"
- << GetBorderWidth() << " w\n"
- << CPWL_Utils::GetColorAppStream(GetBorderColor(), false)
- .AsStringC()
- << " 2 J 0 j\n"
- << "[" << GetBorderDash().nDash << " " << GetBorderDash().nGap
- << "] " << GetBorderDash().nPhase << " d\n";
-
- for (int32_t i = 1; i < nCharArray; i++) {
- sLine << rcClient.left +
- ((rcClient.right - rcClient.left) / nCharArray) * i
- << " " << rcClient.bottom << " m\n"
- << rcClient.left +
- ((rcClient.right - rcClient.left) / nCharArray) * i
- << " " << rcClient.top << " l S\n";
- }
-
- sLine << "Q\n";
- break;
- }
- default:
- break;
- }
- }
-
- sAppStream << sLine;
-
- CFX_ByteTextBuf sText;
- CFX_PointF ptOffset;
- CPVT_WordRange wrWhole = m_pEdit->GetWholeWordRange();
- CPVT_WordRange wrSelect = GetSelectWordRange();
- CPVT_WordRange wrVisible =
- HasFlag(PES_TEXTOVERFLOW) ? wrWhole : m_pEdit->GetVisibleWordRange();
-
- CPVT_WordRange wrSelBefore(wrWhole.BeginPos, wrSelect.BeginPos);
- CPVT_WordRange wrSelAfter(wrSelect.EndPos, wrWhole.EndPos);
- CPVT_WordRange wrTemp =
- CPWL_Utils::OverlapWordRange(GetSelectWordRange(), wrVisible);
- CFX_ByteString sEditSel =
- CPWL_Utils::GetEditSelAppStream(m_pEdit.get(), ptOffset, &wrTemp);
-
- if (sEditSel.GetLength() > 0)
- sText << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELBACKCOLOR).AsStringC()
- << sEditSel.AsStringC();
-
- wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelBefore);
- CFX_ByteString sEditBefore = CPWL_Utils::GetEditAppStream(
- m_pEdit.get(), ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
- m_pEdit->GetPasswordChar());
-
- if (sEditBefore.GetLength() > 0)
- sText << "BT\n"
- << CPWL_Utils::GetColorAppStream(GetTextColor()).AsStringC()
- << sEditBefore.AsStringC() << "ET\n";
-
- wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelect);
- CFX_ByteString sEditMid = CPWL_Utils::GetEditAppStream(
- m_pEdit.get(), ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
- m_pEdit->GetPasswordChar());
-
- if (sEditMid.GetLength() > 0)
- sText << "BT\n"
- << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY, 1))
- .AsStringC()
- << sEditMid.AsStringC() << "ET\n";
-
- wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelAfter);
- CFX_ByteString sEditAfter = CPWL_Utils::GetEditAppStream(
- m_pEdit.get(), ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
- m_pEdit->GetPasswordChar());
-
- if (sEditAfter.GetLength() > 0)
- sText << "BT\n"
- << CPWL_Utils::GetColorAppStream(GetTextColor()).AsStringC()
- << sEditAfter.AsStringC() << "ET\n";
-
- if (sText.GetLength() > 0) {
- CFX_FloatRect rect = GetClientRect();
- sAppStream << "q\n/Tx BMC\n";
-
- if (!HasFlag(PES_TEXTOVERFLOW))
- sAppStream << rect.left << " " << rect.bottom << " "
- << rect.right - rect.left << " " << rect.top - rect.bottom
- << " re W n\n";
-
- sAppStream << sText;
-
- sAppStream << "EMC\nQ\n";
- }
-}
-
-void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
-
- CFX_FloatRect rcClient = GetClientRect();
- CFX_ByteTextBuf sLine;
-
- int32_t nCharArray = m_pEdit->GetCharArray();
- FX_SAFE_INT32 nCharArraySafe = nCharArray;
- nCharArraySafe -= 1;
- nCharArraySafe *= 2;
-
- if (nCharArray > 0 && nCharArraySafe.IsValid()) {
- switch (GetBorderStyle()) {
- case BorderStyle::SOLID: {
- CFX_GraphStateData gsd;
- gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();
-
- CFX_PathData path;
-
- for (int32_t i = 0; i < nCharArray - 1; i++) {
- path.AppendPoint(
- CFX_PointF(
- rcClient.left +
- ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
- rcClient.bottom),
- FXPT_TYPE::MoveTo, false);
- path.AppendPoint(
- CFX_PointF(
- rcClient.left +
- ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
- rcClient.top),
- FXPT_TYPE::LineTo, false);
- }
- if (!path.GetPoints().empty()) {
- pDevice->DrawPath(&path, pUser2Device, &gsd, 0,
- GetBorderColor().ToFXColor(255), FXFILL_ALTERNATE);
- }
- break;
- }
- case BorderStyle::DASH: {
- CFX_GraphStateData gsd;
- gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();
-
- gsd.SetDashCount(2);
- gsd.m_DashArray[0] = (FX_FLOAT)GetBorderDash().nDash;
- gsd.m_DashArray[1] = (FX_FLOAT)GetBorderDash().nGap;
- gsd.m_DashPhase = (FX_FLOAT)GetBorderDash().nPhase;
-
- CFX_PathData path;
- for (int32_t i = 0; i < nCharArray - 1; i++) {
- path.AppendPoint(
- CFX_PointF(
- rcClient.left +
- ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
- rcClient.bottom),
- FXPT_TYPE::MoveTo, false);
- path.AppendPoint(
- CFX_PointF(
- rcClient.left +
- ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
- rcClient.top),
- FXPT_TYPE::LineTo, false);
- }
- if (!path.GetPoints().empty()) {
- pDevice->DrawPath(&path, pUser2Device, &gsd, 0,
- GetBorderColor().ToFXColor(255), FXFILL_ALTERNATE);
- }
- break;
- }
- default:
- break;
- }
- }
-
- CFX_FloatRect rcClip;
- CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange();
- CPVT_WordRange* pRange = nullptr;
- if (!HasFlag(PES_TEXTOVERFLOW)) {
- rcClip = GetClientRect();
- pRange = &wrRange;
- }
-
- CFX_SystemHandler* pSysHandler = GetSystemHandler();
- CFX_Edit::DrawEdit(pDevice, pUser2Device, m_pEdit.get(),
- GetTextColor().ToFXColor(GetTransparency()), rcClip,
- CFX_PointF(), pRange, pSysHandler, m_pFormFiller);
-}
-
-bool CPWL_Edit::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonDown(point, nFlag);
-
- if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) {
- if (m_bMouseDown)
- InvalidateRect();
-
- m_bMouseDown = true;
- SetCapture();
-
- m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- }
-
- return true;
-}
-
-bool CPWL_Edit::OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonDblClk(point, nFlag);
-
- if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) {
- m_pEdit->SelectAll();
- }
-
- return true;
-}
-
-bool CPWL_Edit::OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) {
- if (m_bMouseDown)
- return false;
-
- CPWL_Wnd::OnRButtonUp(point, nFlag);
-
- if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point))
- return true;
-
- CFX_SystemHandler* pSH = GetSystemHandler();
- if (!pSH)
- return false;
-
- SetFocus();
-
- return false;
-}
-
-void CPWL_Edit::OnSetFocus() {
- SetEditCaret(true);
- if (!IsReadOnly()) {
- if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
- pFocusHandler->OnSetFocus(this);
- }
- m_bFocus = true;
-}
-
-void CPWL_Edit::OnKillFocus() {
- ShowVScrollBar(false);
- m_pEdit->SelectNone();
- SetCaret(false, CFX_PointF(), CFX_PointF());
- SetCharSet(FXFONT_ANSI_CHARSET);
- m_bFocus = false;
-}
-
-void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace) {
- m_pEdit->SetCharSpace(fCharSpace);
-}
-
-CFX_ByteString CPWL_Edit::GetSelectAppearanceStream(
- const CFX_PointF& ptOffset) const {
- CPVT_WordRange wr = GetSelectWordRange();
- return CPWL_Utils::GetEditSelAppStream(m_pEdit.get(), ptOffset, &wr);
-}
-
-CPVT_WordRange CPWL_Edit::GetSelectWordRange() const {
- if (m_pEdit->IsSelected()) {
- int32_t nStart = -1;
- int32_t nEnd = -1;
-
- m_pEdit->GetSel(nStart, nEnd);
-
- CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart);
- CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd);
-
- return CPVT_WordRange(wpStart, wpEnd);
- }
-
- return CPVT_WordRange();
-}
-
-CFX_ByteString CPWL_Edit::GetTextAppearanceStream(
- const CFX_PointF& ptOffset) const {
- CFX_ByteTextBuf sRet;
- CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(m_pEdit.get(), ptOffset);
- if (sEdit.GetLength() > 0) {
- sRet << "BT\n"
- << CPWL_Utils::GetColorAppStream(GetTextColor()).AsStringC()
- << sEdit.AsStringC() << "ET\n";
- }
- return sRet.MakeString();
-}
-
-CFX_ByteString CPWL_Edit::GetCaretAppearanceStream(
- const CFX_PointF& ptOffset) const {
- if (m_pEditCaret)
- return m_pEditCaret->GetCaretAppearanceStream(ptOffset);
-
- return CFX_ByteString();
-}
-
-CFX_PointF CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord) {
- CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator();
- CPVT_WordPlace wpOld = pIterator->GetAt();
- pIterator->SetAt(wpWord);
-
- CFX_PointF pt;
- CPVT_Word word;
- if (pIterator->GetWord(word)) {
- pt = CFX_PointF(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent);
- }
- pIterator->SetAt(wpOld);
- return pt;
-}
-
-bool CPWL_Edit::IsTextFull() const {
- return m_pEdit->IsTextFull();
-}
-
-FX_FLOAT CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont,
- const CFX_FloatRect& rcPlate,
- int32_t nCharArray) {
- if (pFont && !pFont->IsStandardFont()) {
- FX_RECT rcBBox;
- pFont->GetFontBBox(rcBBox);
-
- CFX_FloatRect rcCell = rcPlate;
- FX_FLOAT xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width();
- FX_FLOAT ydiv = -rcCell.Height() * 1000.0f / rcBBox.Height();
-
- return xdiv < ydiv ? xdiv : ydiv;
- }
-
- return 0.0f;
-}
-
-void CPWL_Edit::SetCharArray(int32_t nCharArray) {
- if (HasFlag(PES_CHARARRAY) && nCharArray > 0) {
- m_pEdit->SetCharArray(nCharArray);
- m_pEdit->SetTextOverflow(true, true);
-
- if (HasFlag(PWS_AUTOFONTSIZE)) {
- if (IPVT_FontMap* pFontMap = GetFontMap()) {
- FX_FLOAT fFontSize = GetCharArrayAutoFontSize(
- pFontMap->GetPDFFont(0), GetClientRect(), nCharArray);
- if (fFontSize > 0.0f) {
- m_pEdit->SetAutoFontSize(false, true);
- m_pEdit->SetFontSize(fFontSize);
- }
- }
- }
- }
-}
-
-void CPWL_Edit::SetLimitChar(int32_t nLimitChar) {
- m_pEdit->SetLimitChar(nLimitChar);
-}
-
-void CPWL_Edit::ReplaceSel(const CFX_WideString& wsText) {
- m_pEdit->Clear();
- m_pEdit->InsertText(wsText, FXFONT_DEFAULT_CHARSET);
-}
-
-CFX_FloatRect CPWL_Edit::GetFocusRect() const {
- return CFX_FloatRect();
-}
-
-void CPWL_Edit::ShowVScrollBar(bool bShow) {
- if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
- if (bShow) {
- if (!pScroll->IsVisible()) {
- pScroll->SetVisible(true);
- CFX_FloatRect rcWindow = GetWindowRect();
- m_rcOldWindow = rcWindow;
- rcWindow.right += PWL_SCROLLBAR_WIDTH;
- Move(rcWindow, true, true);
- }
- } else {
- if (pScroll->IsVisible()) {
- pScroll->SetVisible(false);
- Move(m_rcOldWindow, true, true);
- }
- }
- }
-}
-
-bool CPWL_Edit::IsVScrollBarVisible() const {
- if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
- return pScroll->IsVisible();
- }
-
- return false;
-}
-
-bool CPWL_Edit::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
- if (m_bMouseDown)
- return true;
-
- if (nChar == FWL_VKEY_Delete) {
- if (m_pFillerNotify) {
- bool bRC = true;
- bool bExit = false;
- CFX_WideString strChange;
- CFX_WideString strChangeEx;
-
- int nSelStart = 0;
- int nSelEnd = 0;
- GetSel(nSelStart, nSelEnd);
-
- if (nSelStart == nSelEnd)
- nSelEnd = nSelStart + 1;
- m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), strChange,
- strChangeEx, nSelStart, nSelEnd, true,
- bRC, bExit, nFlag);
- if (!bRC)
- return false;
- if (bExit)
- return false;
- }
- }
-
- bool bRet = CPWL_EditCtrl::OnKeyDown(nChar, nFlag);
-
- // In case of implementation swallow the OnKeyDown event.
- if (IsProceedtoOnChar(nChar, nFlag))
- return true;
-
- return bRet;
-}
-
-/**
-*In case of implementation swallow the OnKeyDown event.
-*If the event is swallowed, implementation may do other unexpected things, which
-*is not the control means to do.
-*/
-bool CPWL_Edit::IsProceedtoOnChar(uint16_t nKeyCode, uint32_t nFlag) {
- bool bCtrl = IsCTRLpressed(nFlag);
- bool bAlt = IsALTpressed(nFlag);
- if (bCtrl && !bAlt) {
- // hot keys for edit control.
- switch (nKeyCode) {
- case 'C':
- case 'V':
- case 'X':
- case 'A':
- case 'Z':
- return true;
- default:
- break;
- }
- }
- // control characters.
- switch (nKeyCode) {
- case FWL_VKEY_Escape:
- case FWL_VKEY_Back:
- case FWL_VKEY_Return:
- case FWL_VKEY_Space:
- return true;
- default:
- return false;
- }
-}
-
-bool CPWL_Edit::OnChar(uint16_t nChar, uint32_t nFlag) {
- if (m_bMouseDown)
- return true;
-
- bool bRC = true;
- bool bExit = false;
-
- if (!IsCTRLpressed(nFlag)) {
- if (m_pFillerNotify) {
- CFX_WideString swChange;
-
- int nSelStart = 0;
- int nSelEnd = 0;
- GetSel(nSelStart, nSelEnd);
-
- switch (nChar) {
- case FWL_VKEY_Back:
- if (nSelStart == nSelEnd)
- nSelStart = nSelEnd - 1;
- break;
- case FWL_VKEY_Return:
- break;
- default:
- swChange += nChar;
- break;
- }
-
- CFX_WideString strChangeEx;
- m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), swChange,
- strChangeEx, nSelStart, nSelEnd, true,
- bRC, bExit, nFlag);
- }
- }
-
- if (!bRC)
- return true;
- if (bExit)
- return false;
-
- if (IPVT_FontMap* pFontMap = GetFontMap()) {
- int32_t nOldCharSet = GetCharSet();
- int32_t nNewCharSet =
- pFontMap->CharSetFromUnicode(nChar, FXFONT_DEFAULT_CHARSET);
- if (nOldCharSet != nNewCharSet) {
- SetCharSet(nNewCharSet);
- }
- }
-
- return CPWL_EditCtrl::OnChar(nChar, nFlag);
-}
-
-bool CPWL_Edit::OnMouseWheel(short zDelta,
- const CFX_PointF& point,
- uint32_t nFlag) {
- if (HasFlag(PES_MULTILINE)) {
- CFX_PointF ptScroll = GetScrollPos();
-
- if (zDelta > 0) {
- ptScroll.y += GetFontSize();
- } else {
- ptScroll.y -= GetFontSize();
- }
- SetScrollPos(ptScroll);
-
- return true;
- }
-
- return false;
-}
-
-void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace) {
- if (HasFlag(PES_SPELLCHECK)) {
- m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
- GetLatinWordsRange(place)));
- }
-}
-
-void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace) {
- if (HasFlag(PES_SPELLCHECK)) {
- m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
- GetLatinWordsRange(place)));
- }
-}
-
-void CPWL_Edit::OnDelete(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace) {
- if (HasFlag(PES_SPELLCHECK)) {
- m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
- GetLatinWordsRange(place)));
- }
-}
-
-void CPWL_Edit::OnClear(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace) {
- if (HasFlag(PES_SPELLCHECK)) {
- m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
- GetLatinWordsRange(place)));
- }
-}
-
-void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace) {
- if (HasFlag(PES_SPELLCHECK)) {
- m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
- GetLatinWordsRange(place)));
- }
-}
-
-void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace) {
- if (HasFlag(PES_SPELLCHECK)) {
- m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
- GetLatinWordsRange(place)));
- }
-}
-
-CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1,
- const CPVT_WordRange& wr2) {
- CPVT_WordRange wrRet;
-
- if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0) {
- wrRet.BeginPos = wr1.BeginPos;
- } else {
- wrRet.BeginPos = wr2.BeginPos;
- }
-
- if (wr1.EndPos.WordCmp(wr2.EndPos) < 0) {
- wrRet.EndPos = wr2.EndPos;
- } else {
- wrRet.EndPos = wr1.EndPos;
- }
-
- return wrRet;
-}
-
-CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CFX_PointF& point) const {
- return GetSameWordsRange(m_pEdit->SearchWordPlace(point), true, false);
-}
-
-CPVT_WordRange CPWL_Edit::GetLatinWordsRange(
- const CPVT_WordPlace& place) const {
- return GetSameWordsRange(place, true, false);
-}
-
-CPVT_WordRange CPWL_Edit::GetArabicWordsRange(
- const CPVT_WordPlace& place) const {
- return GetSameWordsRange(place, false, true);
-}
-
-#define PWL_ISARABICWORD(word) \
- ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
-
-CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace& place,
- bool bLatin,
- bool bArabic) const {
- CPVT_WordRange range;
-
- CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator();
- CPVT_Word wordinfo;
- CPVT_WordPlace wpStart(place), wpEnd(place);
- pIterator->SetAt(place);
-
- if (bLatin) {
- while (pIterator->NextWord()) {
- if (!pIterator->GetWord(wordinfo) ||
- !FX_EDIT_ISLATINWORD(wordinfo.Word)) {
- break;
- }
-
- wpEnd = pIterator->GetAt();
- }
- } else if (bArabic) {
- while (pIterator->NextWord()) {
- if (!pIterator->GetWord(wordinfo) || !PWL_ISARABICWORD(wordinfo.Word))
- break;
-
- wpEnd = pIterator->GetAt();
- }
- }
-
- pIterator->SetAt(place);
-
- if (bLatin) {
- do {
- if (!pIterator->GetWord(wordinfo) ||
- !FX_EDIT_ISLATINWORD(wordinfo.Word)) {
- break;
- }
-
- wpStart = pIterator->GetAt();
- } while (pIterator->PrevWord());
- } else if (bArabic) {
- do {
- if (!pIterator->GetWord(wordinfo) || !PWL_ISARABICWORD(wordinfo.Word))
- break;
-
- wpStart = pIterator->GetAt();
- } while (pIterator->PrevWord());
- }
-
- range.Set(wpStart, wpEnd);
- return range;
-}
diff --git a/fpdfsdk/pdfwindow/PWL_Edit.h b/fpdfsdk/pdfwindow/PWL_Edit.h
deleted file mode 100644
index b6d0130..0000000
--- a/fpdfsdk/pdfwindow/PWL_Edit.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2014 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_PWL_EDIT_H_
-#define FPDFSDK_PDFWINDOW_PWL_EDIT_H_
-
-#include <vector>
-
-#include "core/fxcrt/fx_basic.h"
-#include "fpdfsdk/fxedit/fx_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-class CPDF_PageObjectHolder;
-class CPDF_TextObject;
-class IFX_Edit_UndoItem;
-
-class IPWL_Filler_Notify {
- public:
- virtual ~IPWL_Filler_Notify() {}
- virtual void QueryWherePopup(
- void* pPrivateData,
- FX_FLOAT fPopupMin,
- FX_FLOAT fPopupMax,
- int32_t& nRet,
- FX_FLOAT& fPopupRet) = 0; // nRet: (0:bottom 1:top)
- virtual void OnBeforeKeyStroke(void* pPrivateData,
- CFX_WideString& strChange,
- const CFX_WideString& strChangeEx,
- int nSelStart,
- int nSelEnd,
- bool bKeyDown,
- bool& bRC,
- bool& bExit,
- uint32_t nFlag) = 0;
-#ifdef PDF_ENABLE_XFA
- virtual void OnPopupPreOpen(void* pPrivateData,
- bool& bExit,
- uint32_t nFlag) = 0;
- virtual void OnPopupPostOpen(void* pPrivateData,
- bool& bExit,
- uint32_t nFlag) = 0;
-#endif // PDF_ENABLE_XFA
-};
-
-class CPWL_Edit : public CPWL_EditCtrl {
- public:
- CPWL_Edit();
- ~CPWL_Edit() override;
-
- // CPWL_EditCtrl
- CFX_ByteString GetClassName() const override;
- void OnDestroy() override;
- void OnCreated() override;
- void RePosChildWnd() override;
- CFX_FloatRect GetClientRect() const override;
- void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override;
- void DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
- bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnMouseWheel(short zDelta,
- const CFX_PointF& point,
- uint32_t nFlag) override;
- bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override;
- bool OnChar(uint16_t nChar, uint32_t nFlag) override;
- CFX_FloatRect GetFocusRect() const override;
- void OnSetFocus() override;
- void OnKillFocus() override;
-
- void SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat = PEAV_TOP,
- bool bPaint = true); // 0:top 1:bottom 2:center
-
- void SetCharArray(int32_t nCharArray);
- void SetLimitChar(int32_t nLimitChar);
-
- void SetCharSpace(FX_FLOAT fCharSpace);
-
- bool CanSelectAll() const;
- bool CanClear() const;
- bool CanCopy() const;
- bool CanCut() const;
-
- void CutText();
-
- void SetText(const CFX_WideString& csText);
- void ReplaceSel(const CFX_WideString& csText);
-
- CFX_ByteString GetTextAppearanceStream(const CFX_PointF& ptOffset) const;
- CFX_ByteString GetCaretAppearanceStream(const CFX_PointF& ptOffset) const;
- CFX_ByteString GetSelectAppearanceStream(const CFX_PointF& ptOffset) const;
-
- bool IsTextFull() const;
-
- static FX_FLOAT GetCharArrayAutoFontSize(CPDF_Font* pFont,
- const CFX_FloatRect& rcPlate,
- int32_t nCharArray);
-
- void SetFillerNotify(IPWL_Filler_Notify* pNotify) {
- m_pFillerNotify = pNotify;
- }
-
- bool IsProceedtoOnChar(uint16_t nKeyCode, uint32_t nFlag);
- void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; }
-
- void OnInsertWord(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace);
- void OnInsertReturn(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace);
- void OnBackSpace(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
- void OnDelete(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
- void OnClear(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
- void OnInsertText(const CPVT_WordPlace& place,
- const CPVT_WordPlace& oldplace);
-
- private:
- CPVT_WordRange GetSelectWordRange() const;
- virtual void ShowVScrollBar(bool bShow);
- bool IsVScrollBarVisible() const;
- void SetParamByFlag();
-
- FX_FLOAT GetCharArrayAutoFontSize(int32_t nCharArray);
- CFX_PointF GetWordRightBottomPoint(const CPVT_WordPlace& wpWord);
-
- CPVT_WordRange CombineWordRange(const CPVT_WordRange& wr1,
- const CPVT_WordRange& wr2);
- CPVT_WordRange GetLatinWordsRange(const CFX_PointF& point) const;
- CPVT_WordRange GetLatinWordsRange(const CPVT_WordPlace& place) const;
- CPVT_WordRange GetArabicWordsRange(const CPVT_WordPlace& place) const;
- CPVT_WordRange GetSameWordsRange(const CPVT_WordPlace& place,
- bool bLatin,
- bool bArabic) const;
- IPWL_Filler_Notify* m_pFillerNotify;
- bool m_bFocus;
- CFX_FloatRect m_rcOldWindow;
- CFFL_FormFiller* m_pFormFiller; // Not owned.
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_EDIT_H_
diff --git a/fpdfsdk/pdfwindow/PWL_EditCtrl.cpp b/fpdfsdk/pdfwindow/PWL_EditCtrl.cpp
deleted file mode 100644
index 4921ab7..0000000
--- a/fpdfsdk/pdfwindow/PWL_EditCtrl.cpp
+++ /dev/null
@@ -1,577 +0,0 @@
-// Copyright 2014 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/PWL_EditCtrl.h"
-
-#include "core/fpdfdoc/cpvt_section.h"
-#include "core/fpdfdoc/cpvt_word.h"
-#include "core/fxge/fx_font.h"
-#include "fpdfsdk/fxedit/fxet_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_Caret.h"
-#include "fpdfsdk/pdfwindow/PWL_FontMap.h"
-#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-#include "public/fpdf_fwlevent.h"
-
-CPWL_EditCtrl::CPWL_EditCtrl()
- : m_pEdit(new CFX_Edit),
- m_pEditCaret(nullptr),
- m_bMouseDown(false),
- m_nCharSet(FXFONT_DEFAULT_CHARSET),
- m_nCodePage(0) {}
-
-CPWL_EditCtrl::~CPWL_EditCtrl() {}
-
-void CPWL_EditCtrl::OnCreate(PWL_CREATEPARAM& cp) {
- cp.eCursorType = FXCT_VBEAM;
-}
-
-void CPWL_EditCtrl::OnCreated() {
- SetFontSize(GetCreationParam().fFontSize);
-
- m_pEdit->SetFontMap(GetFontMap());
- m_pEdit->SetNotify(this);
- m_pEdit->Initialize();
-}
-
-bool CPWL_EditCtrl::IsWndHorV() {
- CFX_Matrix mt = GetWindowMatrix();
- return mt.Transform(CFX_PointF(1, 1)).y == mt.Transform(CFX_PointF(0, 1)).y;
-}
-
-void CPWL_EditCtrl::SetCursor() {
- if (IsValid()) {
- if (CFX_SystemHandler* pSH = GetSystemHandler()) {
- if (IsWndHorV())
- pSH->SetCursor(FXCT_VBEAM);
- else
- pSH->SetCursor(FXCT_HBEAM);
- }
- }
-}
-
-void CPWL_EditCtrl::RePosChildWnd() {
- m_pEdit->SetPlateRect(GetClientRect());
-}
-
-void CPWL_EditCtrl::OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam,
- intptr_t lParam) {
- CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
-
- switch (msg) {
- case PNM_SETSCROLLINFO:
- switch (wParam) {
- case SBT_VSCROLL:
- if (CPWL_Wnd* pChild = GetVScrollBar()) {
- pChild->OnNotify(pWnd, PNM_SETSCROLLINFO, wParam, lParam);
- }
- break;
- }
- break;
- case PNM_SETSCROLLPOS:
- switch (wParam) {
- case SBT_VSCROLL:
- if (CPWL_Wnd* pChild = GetVScrollBar()) {
- pChild->OnNotify(pWnd, PNM_SETSCROLLPOS, wParam, lParam);
- }
- break;
- }
- break;
- case PNM_SCROLLWINDOW: {
- FX_FLOAT fPos = *(FX_FLOAT*)lParam;
- switch (wParam) {
- case SBT_VSCROLL:
- m_pEdit->SetScrollPos(CFX_PointF(m_pEdit->GetScrollPos().x, fPos));
- break;
- }
- } break;
- case PNM_SETCARETINFO: {
- if (PWL_CARET_INFO* pCaretInfo = (PWL_CARET_INFO*)wParam) {
- SetCaret(pCaretInfo->bVisible, pCaretInfo->ptHead, pCaretInfo->ptFoot);
- }
- } break;
- }
-}
-
-void CPWL_EditCtrl::CreateChildWnd(const PWL_CREATEPARAM& cp) {
- if (!IsReadOnly())
- CreateEditCaret(cp);
-}
-
-void CPWL_EditCtrl::CreateEditCaret(const PWL_CREATEPARAM& cp) {
- if (m_pEditCaret)
- return;
-
- m_pEditCaret = new CPWL_Caret;
- m_pEditCaret->SetInvalidRect(GetClientRect());
-
- PWL_CREATEPARAM ecp = cp;
- ecp.pParentWnd = this;
- ecp.dwFlags = PWS_CHILD | PWS_NOREFRESHCLIP;
- ecp.dwBorderWidth = 0;
- ecp.nBorderStyle = BorderStyle::SOLID;
- ecp.rcRectWnd = CFX_FloatRect(0, 0, 0, 0);
-
- m_pEditCaret->Create(ecp);
-}
-
-void CPWL_EditCtrl::SetFontSize(FX_FLOAT fFontSize) {
- m_pEdit->SetFontSize(fFontSize);
-}
-
-FX_FLOAT CPWL_EditCtrl::GetFontSize() const {
- return m_pEdit->GetFontSize();
-}
-
-bool CPWL_EditCtrl::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
- if (m_bMouseDown)
- return true;
-
- bool bRet = CPWL_Wnd::OnKeyDown(nChar, nFlag);
-
- // FILTER
- switch (nChar) {
- default:
- return false;
- case FWL_VKEY_Delete:
- case FWL_VKEY_Up:
- case FWL_VKEY_Down:
- case FWL_VKEY_Left:
- case FWL_VKEY_Right:
- case FWL_VKEY_Home:
- case FWL_VKEY_End:
- case FWL_VKEY_Insert:
- case 'C':
- case 'V':
- case 'X':
- case 'A':
- case 'Z':
- case 'c':
- case 'v':
- case 'x':
- case 'a':
- case 'z':
- break;
- }
-
- if (nChar == FWL_VKEY_Delete && m_pEdit->IsSelected())
- nChar = FWL_VKEY_Unknown;
-
- switch (nChar) {
- case FWL_VKEY_Delete:
- Delete();
- return true;
- case FWL_VKEY_Insert:
- if (IsSHIFTpressed(nFlag))
- PasteText();
- return true;
- case FWL_VKEY_Up:
- m_pEdit->OnVK_UP(IsSHIFTpressed(nFlag), false);
- return true;
- case FWL_VKEY_Down:
- m_pEdit->OnVK_DOWN(IsSHIFTpressed(nFlag), false);
- return true;
- case FWL_VKEY_Left:
- m_pEdit->OnVK_LEFT(IsSHIFTpressed(nFlag), false);
- return true;
- case FWL_VKEY_Right:
- m_pEdit->OnVK_RIGHT(IsSHIFTpressed(nFlag), false);
- return true;
- case FWL_VKEY_Home:
- m_pEdit->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- return true;
- case FWL_VKEY_End:
- m_pEdit->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- return true;
- case FWL_VKEY_Unknown:
- if (!IsSHIFTpressed(nFlag))
- Clear();
- else
- CutText();
- return true;
- default:
- break;
- }
-
- return bRet;
-}
-
-bool CPWL_EditCtrl::OnChar(uint16_t nChar, uint32_t nFlag) {
- if (m_bMouseDown)
- return true;
-
- CPWL_Wnd::OnChar(nChar, nFlag);
-
- // FILTER
- switch (nChar) {
- case 0x0A:
- case 0x1B:
- return false;
- default:
- break;
- }
-
- bool bCtrl = IsCTRLpressed(nFlag);
- bool bAlt = IsALTpressed(nFlag);
- bool bShift = IsSHIFTpressed(nFlag);
-
- uint16_t word = nChar;
-
- if (bCtrl && !bAlt) {
- switch (nChar) {
- case 'C' - 'A' + 1:
- CopyText();
- return true;
- case 'V' - 'A' + 1:
- PasteText();
- return true;
- case 'X' - 'A' + 1:
- CutText();
- return true;
- case 'A' - 'A' + 1:
- SelectAll();
- return true;
- case 'Z' - 'A' + 1:
- if (bShift)
- Redo();
- else
- Undo();
- return true;
- default:
- if (nChar < 32)
- return false;
- }
- }
-
- if (IsReadOnly())
- return true;
-
- if (m_pEdit->IsSelected() && word == FWL_VKEY_Back)
- word = FWL_VKEY_Unknown;
-
- Clear();
-
- switch (word) {
- case FWL_VKEY_Back:
- Backspace();
- break;
- case FWL_VKEY_Return:
- InsertReturn();
- break;
- case FWL_VKEY_Unknown:
- break;
- default:
- InsertWord(word, GetCharSet());
- break;
- }
-
- return true;
-}
-
-bool CPWL_EditCtrl::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonDown(point, nFlag);
-
- if (ClientHitTest(point)) {
- if (m_bMouseDown)
- InvalidateRect();
-
- m_bMouseDown = true;
- SetCapture();
-
- m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- }
-
- return true;
-}
-
-bool CPWL_EditCtrl::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonUp(point, nFlag);
-
- if (m_bMouseDown) {
- // can receive keybord message
- if (ClientHitTest(point) && !IsFocused())
- SetFocus();
-
- ReleaseCapture();
- m_bMouseDown = false;
- }
-
- return true;
-}
-
-bool CPWL_EditCtrl::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnMouseMove(point, nFlag);
-
- if (m_bMouseDown)
- m_pEdit->OnMouseMove(point, false, false);
-
- return true;
-}
-
-CFX_FloatRect CPWL_EditCtrl::GetContentRect() const {
- return m_pEdit->GetContentRect();
-}
-
-void CPWL_EditCtrl::SetEditCaret(bool bVisible) {
- CFX_PointF ptHead;
- CFX_PointF ptFoot;
- if (bVisible)
- GetCaretInfo(&ptHead, &ptFoot);
-
- CPVT_WordPlace wpTemp = m_pEdit->GetCaretWordPlace();
- IOnSetCaret(bVisible, ptHead, ptFoot, wpTemp);
-}
-
-void CPWL_EditCtrl::GetCaretInfo(CFX_PointF* ptHead, CFX_PointF* ptFoot) const {
- CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator();
- pIterator->SetAt(m_pEdit->GetCaret());
- CPVT_Word word;
- CPVT_Line line;
- if (pIterator->GetWord(word)) {
- ptHead->x = word.ptWord.x + word.fWidth;
- ptHead->y = word.ptWord.y + word.fAscent;
- ptFoot->x = word.ptWord.x + word.fWidth;
- ptFoot->y = word.ptWord.y + word.fDescent;
- } else if (pIterator->GetLine(line)) {
- ptHead->x = line.ptLine.x;
- ptHead->y = line.ptLine.y + line.fLineAscent;
- ptFoot->x = line.ptLine.x;
- ptFoot->y = line.ptLine.y + line.fLineDescent;
- }
-}
-
-void CPWL_EditCtrl::SetCaret(bool bVisible,
- const CFX_PointF& ptHead,
- const CFX_PointF& ptFoot) {
- if (m_pEditCaret) {
- if (!IsFocused() || m_pEdit->IsSelected())
- bVisible = false;
-
- m_pEditCaret->SetCaret(bVisible, ptHead, ptFoot);
- }
-}
-
-CFX_WideString CPWL_EditCtrl::GetText() const {
- return m_pEdit->GetText();
-}
-
-void CPWL_EditCtrl::SetSel(int32_t nStartChar, int32_t nEndChar) {
- m_pEdit->SetSel(nStartChar, nEndChar);
-}
-
-void CPWL_EditCtrl::GetSel(int32_t& nStartChar, int32_t& nEndChar) const {
- m_pEdit->GetSel(nStartChar, nEndChar);
-}
-
-void CPWL_EditCtrl::Clear() {
- if (!IsReadOnly())
- m_pEdit->Clear();
-}
-
-void CPWL_EditCtrl::SelectAll() {
- m_pEdit->SelectAll();
-}
-
-void CPWL_EditCtrl::Paint() {
- m_pEdit->Paint();
-}
-
-void CPWL_EditCtrl::EnableRefresh(bool bRefresh) {
- m_pEdit->EnableRefresh(bRefresh);
-}
-
-int32_t CPWL_EditCtrl::GetCaret() const {
- return m_pEdit->GetCaret();
-}
-
-void CPWL_EditCtrl::SetCaret(int32_t nPos) {
- m_pEdit->SetCaret(nPos);
-}
-
-int32_t CPWL_EditCtrl::GetTotalWords() const {
- return m_pEdit->GetTotalWords();
-}
-
-void CPWL_EditCtrl::SetScrollPos(const CFX_PointF& point) {
- m_pEdit->SetScrollPos(point);
-}
-
-CFX_PointF CPWL_EditCtrl::GetScrollPos() const {
- return m_pEdit->GetScrollPos();
-}
-
-CPDF_Font* CPWL_EditCtrl::GetCaretFont() const {
- int32_t nFontIndex = 0;
-
- CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator();
- pIterator->SetAt(m_pEdit->GetCaret());
- CPVT_Word word;
- CPVT_Section section;
- if (pIterator->GetWord(word)) {
- nFontIndex = word.nFontIndex;
- } else if (HasFlag(PES_RICH)) {
- if (pIterator->GetSection(section)) {
- nFontIndex = section.WordProps.nFontIndex;
- }
- }
-
- if (IPVT_FontMap* pFontMap = GetFontMap())
- return pFontMap->GetPDFFont(nFontIndex);
-
- return nullptr;
-}
-
-FX_FLOAT CPWL_EditCtrl::GetCaretFontSize() const {
- FX_FLOAT fFontSize = GetFontSize();
-
- CFX_Edit_Iterator* pIterator = m_pEdit->GetIterator();
- pIterator->SetAt(m_pEdit->GetCaret());
- CPVT_Word word;
- CPVT_Section section;
- if (pIterator->GetWord(word)) {
- fFontSize = word.fFontSize;
- } else if (HasFlag(PES_RICH)) {
- if (pIterator->GetSection(section)) {
- fFontSize = section.WordProps.fFontSize;
- }
- }
-
- return fFontSize;
-}
-
-void CPWL_EditCtrl::SetText(const CFX_WideString& wsText) {
- m_pEdit->SetText(wsText);
-}
-
-void CPWL_EditCtrl::CopyText() {}
-
-void CPWL_EditCtrl::PasteText() {}
-
-void CPWL_EditCtrl::CutText() {}
-
-void CPWL_EditCtrl::ShowVScrollBar(bool bShow) {}
-
-void CPWL_EditCtrl::InsertText(const CFX_WideString& wsText) {
- if (!IsReadOnly())
- m_pEdit->InsertText(wsText, FXFONT_DEFAULT_CHARSET);
-}
-
-void CPWL_EditCtrl::InsertWord(uint16_t word, int32_t nCharset) {
- if (!IsReadOnly())
- m_pEdit->InsertWord(word, nCharset);
-}
-
-void CPWL_EditCtrl::InsertReturn() {
- if (!IsReadOnly())
- m_pEdit->InsertReturn();
-}
-
-void CPWL_EditCtrl::Delete() {
- if (!IsReadOnly())
- m_pEdit->Delete();
-}
-
-void CPWL_EditCtrl::Backspace() {
- if (!IsReadOnly())
- m_pEdit->Backspace();
-}
-
-bool CPWL_EditCtrl::CanUndo() const {
- return !IsReadOnly() && m_pEdit->CanUndo();
-}
-
-bool CPWL_EditCtrl::CanRedo() const {
- return !IsReadOnly() && m_pEdit->CanRedo();
-}
-
-void CPWL_EditCtrl::Redo() {
- if (CanRedo())
- m_pEdit->Redo();
-}
-
-void CPWL_EditCtrl::Undo() {
- if (CanUndo())
- m_pEdit->Undo();
-}
-
-void CPWL_EditCtrl::IOnSetScrollInfoY(FX_FLOAT fPlateMin,
- FX_FLOAT fPlateMax,
- FX_FLOAT fContentMin,
- FX_FLOAT fContentMax,
- FX_FLOAT fSmallStep,
- FX_FLOAT fBigStep) {
- PWL_SCROLL_INFO Info;
-
- Info.fPlateWidth = fPlateMax - fPlateMin;
- Info.fContentMin = fContentMin;
- Info.fContentMax = fContentMax;
- Info.fSmallStep = fSmallStep;
- Info.fBigStep = fBigStep;
-
- OnNotify(this, PNM_SETSCROLLINFO, SBT_VSCROLL, (intptr_t)&Info);
-
- if (IsFloatBigger(Info.fPlateWidth, Info.fContentMax - Info.fContentMin) ||
- IsFloatEqual(Info.fPlateWidth, Info.fContentMax - Info.fContentMin)) {
- ShowVScrollBar(false);
- } else {
- ShowVScrollBar(true);
- }
-}
-
-void CPWL_EditCtrl::IOnSetScrollPosY(FX_FLOAT fy) {
- OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (intptr_t)&fy);
-}
-
-void CPWL_EditCtrl::IOnSetCaret(bool bVisible,
- const CFX_PointF& ptHead,
- const CFX_PointF& ptFoot,
- const CPVT_WordPlace& place) {
- PWL_CARET_INFO cInfo;
- cInfo.bVisible = bVisible;
- cInfo.ptHead = ptHead;
- cInfo.ptFoot = ptFoot;
-
- OnNotify(this, PNM_SETCARETINFO, (intptr_t)&cInfo, (intptr_t) nullptr);
-}
-
-void CPWL_EditCtrl::IOnCaretChange(const CPVT_SecProps& secProps,
- const CPVT_WordProps& wordProps) {}
-
-void CPWL_EditCtrl::IOnContentChange(const CFX_FloatRect& rcContent) {}
-
-void CPWL_EditCtrl::IOnInvalidateRect(CFX_FloatRect* pRect) {
- InvalidateRect(pRect);
-}
-
-int32_t CPWL_EditCtrl::GetCharSet() const {
- return m_nCharSet < 0 ? FXFONT_DEFAULT_CHARSET : m_nCharSet;
-}
-
-void CPWL_EditCtrl::GetTextRange(const CFX_FloatRect& rect,
- int32_t& nStartChar,
- int32_t& nEndChar) const {
- nStartChar = m_pEdit->WordPlaceToWordIndex(
- m_pEdit->SearchWordPlace(CFX_PointF(rect.left, rect.top)));
- nEndChar = m_pEdit->WordPlaceToWordIndex(
- m_pEdit->SearchWordPlace(CFX_PointF(rect.right, rect.bottom)));
-}
-
-CFX_WideString CPWL_EditCtrl::GetText(int32_t& nStartChar,
- int32_t& nEndChar) const {
- CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStartChar);
- CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEndChar);
- return m_pEdit->GetRangeText(CPVT_WordRange(wpStart, wpEnd));
-}
-
-void CPWL_EditCtrl::SetReadyToInput() {
- if (m_bMouseDown) {
- ReleaseCapture();
- m_bMouseDown = false;
- }
-}
diff --git a/fpdfsdk/pdfwindow/PWL_EditCtrl.h b/fpdfsdk/pdfwindow/PWL_EditCtrl.h
deleted file mode 100644
index 498570b..0000000
--- a/fpdfsdk/pdfwindow/PWL_EditCtrl.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2014 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_PWL_EDITCTRL_H_
-#define FPDFSDK_PDFWINDOW_PWL_EDITCTRL_H_
-
-#include <memory>
-
-#include "core/fxcrt/fx_string.h"
-#include "fpdfsdk/fxedit/fx_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-class CFX_Edit;
-class CPWL_Caret;
-class CPWL_Edit;
-class CPWL_EditCtrl;
-struct CPVT_SecProps;
-struct CPVT_WordPlace;
-struct CPVT_WordProps;
-struct CPVT_WordRange;
-
-enum PWL_EDIT_ALIGNFORMAT_H { PEAH_LEFT = 0, PEAH_MIDDLE, PEAH_RIGHT };
-
-enum PWL_EDIT_ALIGNFORMAT_V { PEAV_TOP = 0, PEAV_CENTER, PEAV_BOTTOM };
-
-class CPWL_EditCtrl : public CPWL_Wnd {
- friend class CPWL_Edit_Notify;
-
- public:
- CPWL_EditCtrl();
- ~CPWL_EditCtrl() override;
-
- CFX_FloatRect GetContentRect() const;
-
- CFX_WideString GetText() const;
- void SetSel(int32_t nStartChar, int32_t nEndChar);
- void GetSel(int32_t& nStartChar, int32_t& nEndChar) const;
- void GetTextRange(const CFX_FloatRect& rect,
- int32_t& nStartChar,
- int32_t& nEndChar) const;
- CFX_WideString GetText(int32_t& nStartChar, int32_t& nEndChar) const;
- void Clear();
- void SelectAll();
-
- int32_t GetCaret() const;
- void SetCaret(int32_t nPos);
- int32_t GetTotalWords() const;
-
- void Paint();
-
- void EnableRefresh(bool bRefresh);
- CFX_PointF GetScrollPos() const;
- void SetScrollPos(const CFX_PointF& point);
-
- void SetCharSet(uint8_t nCharSet) { m_nCharSet = nCharSet; }
- int32_t GetCharSet() const;
-
- void SetCodePage(int32_t nCodePage) { m_nCodePage = nCodePage; }
- int32_t GetCodePage() const { return m_nCodePage; }
-
- CPDF_Font* GetCaretFont() const;
- FX_FLOAT GetCaretFontSize() const;
-
- bool CanUndo() const;
- bool CanRedo() const;
- void Redo();
- void Undo();
-
- void SetReadyToInput();
-
- // CPWL_Wnd
- void OnCreate(PWL_CREATEPARAM& cp) override;
- void OnCreated() override;
- bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override;
- bool OnChar(uint16_t nChar, uint32_t nFlag) override;
- bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override;
- void OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam = 0,
- intptr_t lParam = 0) override;
- void CreateChildWnd(const PWL_CREATEPARAM& cp) override;
- void RePosChildWnd() override;
- void SetFontSize(FX_FLOAT fFontSize) override;
- FX_FLOAT GetFontSize() const override;
- void SetCursor() override;
-
- void IOnSetScrollInfoY(FX_FLOAT fPlateMin,
- FX_FLOAT fPlateMax,
- FX_FLOAT fContentMin,
- FX_FLOAT fContentMax,
- FX_FLOAT fSmallStep,
- FX_FLOAT fBigStep);
- void IOnSetScrollPosY(FX_FLOAT fy);
- void IOnSetCaret(bool bVisible,
- const CFX_PointF& ptHead,
- const CFX_PointF& ptFoot,
- const CPVT_WordPlace& place);
- void IOnCaretChange(const CPVT_SecProps& secProps,
- const CPVT_WordProps& wordProps);
- void IOnContentChange(const CFX_FloatRect& rcContent);
- void IOnInvalidateRect(CFX_FloatRect* pRect);
-
- protected:
- void InsertText(const CFX_WideString& wsText);
- void SetText(const CFX_WideString& wsText);
- void CopyText();
- void PasteText();
- void CutText();
- void ShowVScrollBar(bool bShow);
- void InsertWord(uint16_t word, int32_t nCharset);
- void InsertReturn();
-
- bool IsWndHorV();
-
- void Delete();
- void Backspace();
-
- void GetCaretInfo(CFX_PointF* ptHead, CFX_PointF* ptFoot) const;
- void SetCaret(bool bVisible,
- const CFX_PointF& ptHead,
- const CFX_PointF& ptFoot);
-
- void SetEditCaret(bool bVisible);
-
- std::unique_ptr<CFX_Edit> m_pEdit;
- CPWL_Caret* m_pEditCaret;
- bool m_bMouseDown;
-
- private:
- void CreateEditCaret(const PWL_CREATEPARAM& cp);
-
- int32_t m_nCharSet;
- int32_t m_nCodePage;
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_EDITCTRL_H_
diff --git a/fpdfsdk/pdfwindow/PWL_FontMap.cpp b/fpdfsdk/pdfwindow/PWL_FontMap.cpp
deleted file mode 100644
index 9a2962c..0000000
--- a/fpdfsdk/pdfwindow/PWL_FontMap.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-// Copyright 2014 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/PWL_FontMap.h"
-
-#include <utility>
-
-#include "core/fpdfapi/cpdf_modulemgr.h"
-#include "core/fpdfapi/font/cpdf_font.h"
-#include "core/fpdfapi/font/cpdf_fontencoding.h"
-#include "core/fpdfapi/parser/cpdf_document.h"
-#include "core/fpdfapi/parser/cpdf_parser.h"
-#include "core/fpdfdoc/ipvt_fontmap.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
-
-namespace {
-
-const char kDefaultFontName[] = "Helvetica";
-
-const char* const g_sDEStandardFontName[] = {"Courier",
- "Courier-Bold",
- "Courier-BoldOblique",
- "Courier-Oblique",
- "Helvetica",
- "Helvetica-Bold",
- "Helvetica-BoldOblique",
- "Helvetica-Oblique",
- "Times-Roman",
- "Times-Bold",
- "Times-Italic",
- "Times-BoldItalic",
- "Symbol",
- "ZapfDingbats"};
-
-} // namespace
-
-CPWL_FontMap::CPWL_FontMap(CFX_SystemHandler* pSystemHandler)
- : m_pSystemHandler(pSystemHandler) {
- ASSERT(m_pSystemHandler);
-}
-
-CPWL_FontMap::~CPWL_FontMap() {
- Empty();
-}
-
-CPDF_Document* CPWL_FontMap::GetDocument() {
- if (!m_pPDFDoc) {
- if (CPDF_ModuleMgr::Get()) {
- m_pPDFDoc = pdfium::MakeUnique<CPDF_Document>(nullptr);
- m_pPDFDoc->CreateNewDoc();
- }
- }
-
- return m_pPDFDoc.get();
-}
-
-CPDF_Font* CPWL_FontMap::GetPDFFont(int32_t nFontIndex) {
- if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize<int32_t>(m_Data)) {
- if (m_Data[nFontIndex])
- return m_Data[nFontIndex]->pFont;
- }
- return nullptr;
-}
-
-CFX_ByteString CPWL_FontMap::GetPDFFontAlias(int32_t nFontIndex) {
- if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize<int32_t>(m_Data)) {
- if (m_Data[nFontIndex])
- return m_Data[nFontIndex]->sFontName;
- }
- return CFX_ByteString();
-}
-
-bool CPWL_FontMap::KnowWord(int32_t nFontIndex, uint16_t word) {
- if (nFontIndex >= 0 && nFontIndex < pdfium::CollectionSize<int32_t>(m_Data)) {
- if (m_Data[nFontIndex])
- return CharCodeFromUnicode(nFontIndex, word) >= 0;
- }
- return false;
-}
-
-int32_t CPWL_FontMap::GetWordFontIndex(uint16_t word,
- int32_t nCharset,
- int32_t nFontIndex) {
- if (nFontIndex > 0) {
- if (KnowWord(nFontIndex, word))
- return nFontIndex;
- } else {
- if (const CPWL_FontMap_Data* pData = GetFontMapData(0)) {
- if (nCharset == FXFONT_DEFAULT_CHARSET ||
- pData->nCharset == FXFONT_SYMBOL_CHARSET ||
- nCharset == pData->nCharset) {
- if (KnowWord(0, word))
- return 0;
- }
- }
- }
-
- int32_t nNewFontIndex =
- GetFontIndex(GetNativeFontName(nCharset), nCharset, true);
- if (nNewFontIndex >= 0) {
- if (KnowWord(nNewFontIndex, word))
- return nNewFontIndex;
- }
- nNewFontIndex =
- GetFontIndex("Arial Unicode MS", FXFONT_DEFAULT_CHARSET, false);
- if (nNewFontIndex >= 0) {
- if (KnowWord(nNewFontIndex, word))
- return nNewFontIndex;
- }
- return -1;
-}
-
-int32_t CPWL_FontMap::CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) {
- if (nFontIndex < 0 || nFontIndex >= pdfium::CollectionSize<int32_t>(m_Data))
- return -1;
-
- CPWL_FontMap_Data* pData = m_Data[nFontIndex].get();
- if (!pData || !pData->pFont)
- return -1;
-
- if (pData->pFont->IsUnicodeCompatible())
- return pData->pFont->CharCodeFromUnicode(word);
-
- return word < 0xFF ? word : -1;
-}
-
-CFX_ByteString CPWL_FontMap::GetNativeFontName(int32_t nCharset) {
- for (const auto& pData : m_NativeFont) {
- if (pData && pData->nCharset == nCharset)
- return pData->sFontName;
- }
-
- CFX_ByteString sNew = GetNativeFont(nCharset);
- if (sNew.IsEmpty())
- return CFX_ByteString();
-
- auto pNewData = pdfium::MakeUnique<CPWL_FontMap_Native>();
- pNewData->nCharset = nCharset;
- pNewData->sFontName = sNew;
- m_NativeFont.push_back(std::move(pNewData));
- return sNew;
-}
-
-void CPWL_FontMap::Empty() {
- m_Data.clear();
- m_NativeFont.clear();
-}
-
-void CPWL_FontMap::Initialize() {
- GetFontIndex(kDefaultFontName, FXFONT_ANSI_CHARSET, false);
-}
-
-bool CPWL_FontMap::IsStandardFont(const CFX_ByteString& sFontName) {
- for (size_t i = 0; i < FX_ArraySize(g_sDEStandardFontName); ++i) {
- if (sFontName == g_sDEStandardFontName[i])
- return true;
- }
-
- return false;
-}
-
-int32_t CPWL_FontMap::FindFont(const CFX_ByteString& sFontName,
- int32_t nCharset) {
- int32_t i = 0;
- for (const auto& pData : m_Data) {
- if (pData &&
- (nCharset == FXFONT_DEFAULT_CHARSET || nCharset == pData->nCharset) &&
- (sFontName.IsEmpty() || pData->sFontName == sFontName)) {
- return i;
- }
- ++i;
- }
- return -1;
-}
-
-int32_t CPWL_FontMap::GetFontIndex(const CFX_ByteString& sFontName,
- int32_t nCharset,
- bool bFind) {
- int32_t nFontIndex = FindFont(EncodeFontAlias(sFontName, nCharset), nCharset);
- if (nFontIndex >= 0)
- return nFontIndex;
-
- CFX_ByteString sAlias;
- CPDF_Font* pFont = nullptr;
- if (bFind)
- pFont = FindFontSameCharset(sAlias, nCharset);
-
- if (!pFont) {
- CFX_ByteString sTemp = sFontName;
- pFont = AddFontToDocument(GetDocument(), sTemp, nCharset);
- sAlias = EncodeFontAlias(sTemp, nCharset);
- }
- AddedFont(pFont, sAlias);
- return AddFontData(pFont, sAlias, nCharset);
-}
-
-CPDF_Font* CPWL_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias,
- int32_t nCharset) {
- return nullptr;
-}
-
-int32_t CPWL_FontMap::AddFontData(CPDF_Font* pFont,
- const CFX_ByteString& sFontAlias,
- int32_t nCharset) {
- auto pNewData = pdfium::MakeUnique<CPWL_FontMap_Data>();
- pNewData->pFont = pFont;
- pNewData->sFontName = sFontAlias;
- pNewData->nCharset = nCharset;
- m_Data.push_back(std::move(pNewData));
- return pdfium::CollectionSize<int32_t>(m_Data) - 1;
-}
-
-void CPWL_FontMap::AddedFont(CPDF_Font* pFont,
- const CFX_ByteString& sFontAlias) {}
-
-CFX_ByteString CPWL_FontMap::GetNativeFont(int32_t nCharset) {
- if (nCharset == FXFONT_DEFAULT_CHARSET)
- nCharset = GetNativeCharset();
-
- CFX_ByteString sFontName = GetDefaultFontByCharset(nCharset);
- if (!m_pSystemHandler->FindNativeTrueTypeFont(sFontName))
- return CFX_ByteString();
-
- return sFontName;
-}
-
-CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc,
- CFX_ByteString& sFontName,
- uint8_t nCharset) {
- if (IsStandardFont(sFontName))
- return AddStandardFont(pDoc, sFontName);
-
- return AddSystemFont(pDoc, sFontName, nCharset);
-}
-
-CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc,
- CFX_ByteString& sFontName) {
- if (!pDoc)
- return nullptr;
-
- CPDF_Font* pFont = nullptr;
-
- if (sFontName == "ZapfDingbats") {
- pFont = pDoc->AddStandardFont(sFontName.c_str(), nullptr);
- } else {
- CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI);
- pFont = pDoc->AddStandardFont(sFontName.c_str(), &fe);
- }
-
- return pFont;
-}
-
-CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc,
- CFX_ByteString& sFontName,
- uint8_t nCharset) {
- if (!pDoc)
- return nullptr;
-
- if (sFontName.IsEmpty())
- sFontName = GetNativeFont(nCharset);
- if (nCharset == FXFONT_DEFAULT_CHARSET)
- nCharset = GetNativeCharset();
-
- return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName,
- nCharset);
-}
-
-CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName,
- int32_t nCharset) {
- CFX_ByteString sPostfix;
- sPostfix.Format("_%02X", nCharset);
- return EncodeFontAlias(sFontName) + sPostfix;
-}
-
-CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName) {
- CFX_ByteString sRet = sFontName;
- sRet.Remove(' ');
- return sRet;
-}
-
-const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(int32_t nIndex) const {
- if (nIndex < 0 || nIndex >= pdfium::CollectionSize<int32_t>(m_Data))
- return nullptr;
-
- return m_Data[nIndex].get();
-}
-
-int32_t CPWL_FontMap::GetNativeCharset() {
- uint8_t nCharset = FXFONT_ANSI_CHARSET;
- int32_t iCodePage = FXSYS_GetACP();
- switch (iCodePage) {
- case 932: // Japan
- nCharset = FXFONT_SHIFTJIS_CHARSET;
- break;
- case 936: // Chinese (PRC, Singapore)
- nCharset = FXFONT_GB2312_CHARSET;
- break;
- case 950: // Chinese (Taiwan; Hong Kong SAR, PRC)
- nCharset = FXFONT_GB2312_CHARSET;
- break;
- case 1252: // Windows 3.1 Latin 1 (US, Western Europe)
- nCharset = FXFONT_ANSI_CHARSET;
- break;
- case 874: // Thai
- nCharset = FXFONT_THAI_CHARSET;
- break;
- case 949: // Korean
- nCharset = FXFONT_HANGUL_CHARSET;
- break;
- case 1200: // Unicode (BMP of ISO 10646)
- nCharset = FXFONT_ANSI_CHARSET;
- break;
- case 1250: // Windows 3.1 Eastern European
- nCharset = FXFONT_EASTEUROPE_CHARSET;
- break;
- case 1251: // Windows 3.1 Cyrillic
- nCharset = FXFONT_RUSSIAN_CHARSET;
- break;
- case 1253: // Windows 3.1 Greek
- nCharset = FXFONT_GREEK_CHARSET;
- break;
- case 1254: // Windows 3.1 Turkish
- nCharset = FXFONT_TURKISH_CHARSET;
- break;
- case 1255: // Hebrew
- nCharset = FXFONT_HEBREW_CHARSET;
- break;
- case 1256: // Arabic
- nCharset = FXFONT_ARABIC_CHARSET;
- break;
- case 1257: // Baltic
- nCharset = FXFONT_BALTIC_CHARSET;
- break;
- case 1258: // Vietnamese
- nCharset = FXFONT_VIETNAMESE_CHARSET;
- break;
- case 1361: // Korean(Johab)
- nCharset = FXFONT_JOHAB_CHARSET;
- break;
- }
- return nCharset;
-}
-
-const FPDF_CharsetFontMap CPWL_FontMap::defaultTTFMap[] = {
- {FXFONT_ANSI_CHARSET, "Helvetica"},
- {FXFONT_GB2312_CHARSET, "SimSun"},
- {FXFONT_CHINESEBIG5_CHARSET, "MingLiU"},
- {FXFONT_SHIFTJIS_CHARSET, "MS Gothic"},
- {FXFONT_HANGUL_CHARSET, "Batang"},
- {FXFONT_RUSSIAN_CHARSET, "Arial"},
-#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || \
- _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
- {FXFONT_EASTEUROPE_CHARSET, "Arial"},
-#else
- {FXFONT_EASTEUROPE_CHARSET, "Tahoma"},
-#endif
- {FXFONT_ARABIC_CHARSET, "Arial"},
- {-1, nullptr}};
-
-CFX_ByteString CPWL_FontMap::GetDefaultFontByCharset(int32_t nCharset) {
- int i = 0;
- while (defaultTTFMap[i].charset != -1) {
- if (nCharset == defaultTTFMap[i].charset)
- return defaultTTFMap[i].fontname;
- ++i;
- }
- return "";
-}
-
-int32_t CPWL_FontMap::CharSetFromUnicode(uint16_t word, int32_t nOldCharset) {
- // to avoid CJK Font to show ASCII
- if (word < 0x7F)
- return FXFONT_ANSI_CHARSET;
- // follow the old charset
- if (nOldCharset != FXFONT_DEFAULT_CHARSET)
- return nOldCharset;
-
- // find new charset
- if ((word >= 0x4E00 && word <= 0x9FA5) ||
- (word >= 0xE7C7 && word <= 0xE7F3) ||
- (word >= 0x3000 && word <= 0x303F) ||
- (word >= 0x2000 && word <= 0x206F)) {
- return FXFONT_GB2312_CHARSET;
- }
-
- if (((word >= 0x3040) && (word <= 0x309F)) ||
- ((word >= 0x30A0) && (word <= 0x30FF)) ||
- ((word >= 0x31F0) && (word <= 0x31FF)) ||
- ((word >= 0xFF00) && (word <= 0xFFEF))) {
- return FXFONT_SHIFTJIS_CHARSET;
- }
-
- if (((word >= 0xAC00) && (word <= 0xD7AF)) ||
- ((word >= 0x1100) && (word <= 0x11FF)) ||
- ((word >= 0x3130) && (word <= 0x318F))) {
- return FXFONT_HANGUL_CHARSET;
- }
-
- if (word >= 0x0E00 && word <= 0x0E7F)
- return FXFONT_THAI_CHARSET;
-
- if ((word >= 0x0370 && word <= 0x03FF) || (word >= 0x1F00 && word <= 0x1FFF))
- return FXFONT_GREEK_CHARSET;
-
- if ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
- return FXFONT_ARABIC_CHARSET;
-
- if (word >= 0x0590 && word <= 0x05FF)
- return FXFONT_HEBREW_CHARSET;
-
- if (word >= 0x0400 && word <= 0x04FF)
- return FXFONT_RUSSIAN_CHARSET;
-
- if (word >= 0x0100 && word <= 0x024F)
- return FXFONT_EASTEUROPE_CHARSET;
-
- if (word >= 0x1E00 && word <= 0x1EFF)
- return FXFONT_VIETNAMESE_CHARSET;
-
- return FXFONT_ANSI_CHARSET;
-}
diff --git a/fpdfsdk/pdfwindow/PWL_FontMap.h b/fpdfsdk/pdfwindow/PWL_FontMap.h
deleted file mode 100644
index c14fcd7..0000000
--- a/fpdfsdk/pdfwindow/PWL_FontMap.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2014 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_PWL_FONTMAP_H_
-#define FPDFSDK_PDFWINDOW_PWL_FONTMAP_H_
-
-#include <memory>
-#include <vector>
-
-#include "core/fpdfdoc/ipvt_fontmap.h"
-#include "core/fxge/fx_font.h"
-#include "fpdfsdk/fxedit/fx_edit.h"
-#include "public/fpdf_sysfontinfo.h"
-
-class CPDF_Document;
-class CFX_SystemHandler;
-
-struct CPWL_FontMap_Data {
- CPDF_Font* pFont;
- int32_t nCharset;
- CFX_ByteString sFontName;
-};
-
-struct CPWL_FontMap_Native {
- int32_t nCharset;
- CFX_ByteString sFontName;
-};
-
-class CPWL_FontMap : public IPVT_FontMap {
- public:
- explicit CPWL_FontMap(CFX_SystemHandler* pSystemHandler);
- ~CPWL_FontMap() override;
-
- // IPVT_FontMap
- CPDF_Font* GetPDFFont(int32_t nFontIndex) override;
- CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) override;
- int32_t GetWordFontIndex(uint16_t word,
- int32_t nCharset,
- int32_t nFontIndex) override;
- int32_t CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) override;
- int32_t CharSetFromUnicode(uint16_t word, int32_t nOldCharset) override;
-
- const CPWL_FontMap_Data* GetFontMapData(int32_t nIndex) const;
- static int32_t GetNativeCharset();
- CFX_ByteString GetNativeFontName(int32_t nCharset);
-
- static CFX_ByteString GetDefaultFontByCharset(int32_t nCharset);
- static const FPDF_CharsetFontMap defaultTTFMap[];
-
- protected:
- virtual void Initialize();
- virtual CPDF_Document* GetDocument();
- virtual CPDF_Font* FindFontSameCharset(CFX_ByteString& sFontAlias,
- int32_t nCharset);
- virtual void AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias);
-
- bool KnowWord(int32_t nFontIndex, uint16_t word);
-
- void Empty();
- int32_t GetFontIndex(const CFX_ByteString& sFontName,
- int32_t nCharset,
- bool bFind);
- int32_t AddFontData(CPDF_Font* pFont,
- const CFX_ByteString& sFontAlias,
- int32_t nCharset = FXFONT_DEFAULT_CHARSET);
-
- CFX_ByteString EncodeFontAlias(const CFX_ByteString& sFontName,
- int32_t nCharset);
- CFX_ByteString EncodeFontAlias(const CFX_ByteString& sFontName);
-
- std::vector<std::unique_ptr<CPWL_FontMap_Data>> m_Data;
- std::vector<std::unique_ptr<CPWL_FontMap_Native>> m_NativeFont;
-
- private:
- int32_t FindFont(const CFX_ByteString& sFontName,
- int32_t nCharset = FXFONT_DEFAULT_CHARSET);
-
- CFX_ByteString GetNativeFont(int32_t nCharset);
- CPDF_Font* AddFontToDocument(CPDF_Document* pDoc,
- CFX_ByteString& sFontName,
- uint8_t nCharset);
- bool IsStandardFont(const CFX_ByteString& sFontName);
- CPDF_Font* AddStandardFont(CPDF_Document* pDoc, CFX_ByteString& sFontName);
- CPDF_Font* AddSystemFont(CPDF_Document* pDoc,
- CFX_ByteString& sFontName,
- uint8_t nCharset);
-
- std::unique_ptr<CPDF_Document> m_pPDFDoc;
- CFX_SystemHandler* const m_pSystemHandler;
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_FONTMAP_H_
diff --git a/fpdfsdk/pdfwindow/PWL_Icon.cpp b/fpdfsdk/pdfwindow/PWL_Icon.cpp
deleted file mode 100644
index b0d0c76..0000000
--- a/fpdfsdk/pdfwindow/PWL_Icon.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2014 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/PWL_Icon.h"
-
-#include <algorithm>
-
-#include "core/fpdfapi/parser/cpdf_array.h"
-#include "core/fpdfapi/parser/cpdf_stream.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-CPWL_Image::CPWL_Image() : m_pPDFStream(nullptr) {}
-
-CPWL_Image::~CPWL_Image() {}
-
-CFX_ByteString CPWL_Image::GetImageAppStream() {
- CFX_ByteTextBuf sAppStream;
-
- CFX_ByteString sAlias = GetImageAlias();
- CFX_FloatRect rcPlate = GetClientRect();
- CFX_Matrix mt;
- mt.SetReverse(GetImageMatrix());
-
- FX_FLOAT fHScale = 1.0f;
- FX_FLOAT fVScale = 1.0f;
- GetScale(fHScale, fVScale);
-
- FX_FLOAT fx = 0.0f;
- FX_FLOAT fy = 0.0f;
- GetImageOffset(fx, fy);
-
- if (m_pPDFStream && sAlias.GetLength() > 0) {
- sAppStream << "q\n";
- sAppStream << rcPlate.left << " " << rcPlate.bottom << " "
- << rcPlate.right - rcPlate.left << " "
- << rcPlate.top - rcPlate.bottom << " re W n\n";
-
- sAppStream << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx
- << " " << rcPlate.bottom + fy << " cm\n";
- sAppStream << mt.a << " " << mt.b << " " << mt.c << " " << mt.d << " "
- << mt.e << " " << mt.f << " cm\n";
-
- sAppStream << "0 g 0 G 1 w /" << sAlias.AsStringC() << " Do\n"
- << "Q\n";
- }
-
- return sAppStream.MakeString();
-}
-
-void CPWL_Image::SetPDFStream(CPDF_Stream* pStream) {
- m_pPDFStream = pStream;
-}
-
-CPDF_Stream* CPWL_Image::GetPDFStream() {
- return m_pPDFStream;
-}
-
-void CPWL_Image::GetImageSize(FX_FLOAT& fWidth, FX_FLOAT& fHeight) {
- fWidth = 0.0f;
- fHeight = 0.0f;
-
- if (m_pPDFStream) {
- if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) {
- CFX_FloatRect rect = pDict->GetRectFor("BBox");
-
- fWidth = rect.right - rect.left;
- fHeight = rect.top - rect.bottom;
- }
- }
-}
-
-CFX_Matrix CPWL_Image::GetImageMatrix() {
- if (m_pPDFStream) {
- if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) {
- return pDict->GetMatrixFor("Matrix");
- }
- }
-
- return CFX_Matrix();
-}
-
-CFX_ByteString CPWL_Image::GetImageAlias() {
- if (!m_sImageAlias.IsEmpty())
- return m_sImageAlias;
-
- if (m_pPDFStream) {
- if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) {
- return pDict->GetStringFor("Name");
- }
- }
-
- return CFX_ByteString();
-}
-
-void CPWL_Image::SetImageAlias(const FX_CHAR* sImageAlias) {
- m_sImageAlias = sImageAlias;
-}
-
-void CPWL_Image::GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) {
- fHScale = 1.0f;
- fVScale = 1.0f;
-}
-
-void CPWL_Image::GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) {
- x = 0.0f;
- y = 0.0f;
-}
-
-CPWL_Icon::CPWL_Icon() : m_pIconFit(nullptr) {}
-
-CPWL_Icon::~CPWL_Icon() {}
-
-CPDF_IconFit* CPWL_Icon::GetIconFit() {
- return m_pIconFit;
-}
-
-int32_t CPWL_Icon::GetScaleMethod() {
- if (m_pIconFit)
- return m_pIconFit->GetScaleMethod();
-
- return 0;
-}
-
-bool CPWL_Icon::IsProportionalScale() {
- if (m_pIconFit)
- return m_pIconFit->IsProportionalScale();
-
- return false;
-}
-
-void CPWL_Icon::GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom) {
- if (m_pIconFit) {
- fLeft = 0.0f;
- fBottom = 0.0f;
- CPDF_Array* pA = m_pIconFit->GetDict()
- ? m_pIconFit->GetDict()->GetArrayFor("A")
- : nullptr;
- if (pA) {
- size_t dwCount = pA->GetCount();
- if (dwCount > 0)
- fLeft = pA->GetNumberAt(0);
- if (dwCount > 1)
- fBottom = pA->GetNumberAt(1);
- }
- } else {
- fLeft = 0.0f;
- fBottom = 0.0f;
- }
-}
-
-void CPWL_Icon::GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) {
- fHScale = 1.0f;
- fVScale = 1.0f;
-
- if (m_pPDFStream) {
- FX_FLOAT fImageWidth, fImageHeight;
- FX_FLOAT fPlateWidth, fPlateHeight;
-
- CFX_FloatRect rcPlate = GetClientRect();
- fPlateWidth = rcPlate.right - rcPlate.left;
- fPlateHeight = rcPlate.top - rcPlate.bottom;
-
- GetImageSize(fImageWidth, fImageHeight);
-
- int32_t nScaleMethod = GetScaleMethod();
-
- switch (nScaleMethod) {
- default:
- case 0:
- fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
- fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
- break;
- case 1:
- if (fPlateWidth < fImageWidth)
- fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
- if (fPlateHeight < fImageHeight)
- fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
- break;
- case 2:
- if (fPlateWidth > fImageWidth)
- fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
- if (fPlateHeight > fImageHeight)
- fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
- break;
- case 3:
- break;
- }
-
- FX_FLOAT fMinScale;
- if (IsProportionalScale()) {
- fMinScale = std::min(fHScale, fVScale);
- fHScale = fMinScale;
- fVScale = fMinScale;
- }
- }
-}
-
-void CPWL_Icon::GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) {
- FX_FLOAT fLeft, fBottom;
-
- GetIconPosition(fLeft, fBottom);
- x = 0.0f;
- y = 0.0f;
-
- FX_FLOAT fImageWidth, fImageHeight;
- GetImageSize(fImageWidth, fImageHeight);
-
- FX_FLOAT fHScale, fVScale;
- GetScale(fHScale, fVScale);
-
- FX_FLOAT fImageFactWidth = fImageWidth * fHScale;
- FX_FLOAT fImageFactHeight = fImageHeight * fVScale;
-
- FX_FLOAT fPlateWidth, fPlateHeight;
- CFX_FloatRect rcPlate = GetClientRect();
- fPlateWidth = rcPlate.right - rcPlate.left;
- fPlateHeight = rcPlate.top - rcPlate.bottom;
-
- x = (fPlateWidth - fImageFactWidth) * fLeft;
- y = (fPlateHeight - fImageFactHeight) * fBottom;
-}
diff --git a/fpdfsdk/pdfwindow/PWL_Icon.h b/fpdfsdk/pdfwindow/PWL_Icon.h
deleted file mode 100644
index 4b62db4..0000000
--- a/fpdfsdk/pdfwindow/PWL_Icon.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 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_PWL_ICON_H_
-#define FPDFSDK_PDFWINDOW_PWL_ICON_H_
-
-#include "core/fxcrt/fx_string.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-class CPWL_Image : public CPWL_Wnd {
- public:
- CPWL_Image();
- ~CPWL_Image() override;
-
- virtual CFX_ByteString GetImageAppStream();
-
- virtual void GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale);
- virtual void GetImageOffset(FX_FLOAT& x, FX_FLOAT& y);
- virtual CPDF_Stream* GetPDFStream();
-
- public:
- void SetPDFStream(CPDF_Stream* pStream);
- void GetImageSize(FX_FLOAT& fWidth, FX_FLOAT& fHeight);
- CFX_Matrix GetImageMatrix();
- CFX_ByteString GetImageAlias();
- void SetImageAlias(const FX_CHAR* sImageAlias);
-
- protected:
- CPDF_Stream* m_pPDFStream;
- CFX_ByteString m_sImageAlias;
-};
-
-class CPWL_Icon : public CPWL_Image {
- public:
- CPWL_Icon();
- ~CPWL_Icon() override;
-
- virtual CPDF_IconFit* GetIconFit();
-
- // CPWL_Image
- void GetScale(FX_FLOAT& fHScale, FX_FLOAT& fVScale) override;
- void GetImageOffset(FX_FLOAT& x, FX_FLOAT& y) override;
-
- int32_t GetScaleMethod();
- bool IsProportionalScale();
- void GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom);
-
- void SetIconFit(CPDF_IconFit* pIconFit) { m_pIconFit = pIconFit; }
-
- private:
- CPDF_IconFit* m_pIconFit;
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_ICON_H_
diff --git a/fpdfsdk/pdfwindow/PWL_ListBox.cpp b/fpdfsdk/pdfwindow/PWL_ListBox.cpp
deleted file mode 100644
index ed96e20..0000000
--- a/fpdfsdk/pdfwindow/PWL_ListBox.cpp
+++ /dev/null
@@ -1,459 +0,0 @@
-// Copyright 2014 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/PWL_ListBox.h"
-
-#include "fpdfsdk/fxedit/fxet_edit.h"
-#include "fpdfsdk/fxedit/fxet_list.h"
-#include "fpdfsdk/pdfwindow/PWL_Edit.h"
-#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h"
-#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-#include "public/fpdf_fwlevent.h"
-#include "third_party/base/ptr_util.h"
-
-CPWL_List_Notify::CPWL_List_Notify(CPWL_ListBox* pList) : m_pList(pList) {
- ASSERT(m_pList);
-}
-
-CPWL_List_Notify::~CPWL_List_Notify() {}
-
-void CPWL_List_Notify::IOnSetScrollInfoY(FX_FLOAT fPlateMin,
- FX_FLOAT fPlateMax,
- FX_FLOAT fContentMin,
- FX_FLOAT fContentMax,
- FX_FLOAT fSmallStep,
- FX_FLOAT fBigStep) {
- PWL_SCROLL_INFO Info;
-
- Info.fPlateWidth = fPlateMax - fPlateMin;
- Info.fContentMin = fContentMin;
- Info.fContentMax = fContentMax;
- Info.fSmallStep = fSmallStep;
- Info.fBigStep = fBigStep;
-
- m_pList->OnNotify(m_pList, PNM_SETSCROLLINFO, SBT_VSCROLL, (intptr_t)&Info);
-
- if (CPWL_ScrollBar* pScroll = m_pList->GetVScrollBar()) {
- if (IsFloatBigger(Info.fPlateWidth, Info.fContentMax - Info.fContentMin) ||
- IsFloatEqual(Info.fPlateWidth, Info.fContentMax - Info.fContentMin)) {
- if (pScroll->IsVisible()) {
- pScroll->SetVisible(false);
- m_pList->RePosChildWnd();
- }
- } else {
- if (!pScroll->IsVisible()) {
- pScroll->SetVisible(true);
- m_pList->RePosChildWnd();
- }
- }
- }
-}
-
-void CPWL_List_Notify::IOnSetScrollPosY(FX_FLOAT fy) {
- m_pList->OnNotify(m_pList, PNM_SETSCROLLPOS, SBT_VSCROLL, (intptr_t)&fy);
-}
-
-void CPWL_List_Notify::IOnInvalidateRect(CFX_FloatRect* pRect) {
- m_pList->InvalidateRect(pRect);
-}
-
-CPWL_ListBox::CPWL_ListBox()
- : m_pList(new CFX_ListCtrl),
- m_bMouseDown(false),
- m_bHoverSel(false),
- m_pFillerNotify(nullptr) {}
-
-CPWL_ListBox::~CPWL_ListBox() {
-}
-
-CFX_ByteString CPWL_ListBox::GetClassName() const {
- return "CPWL_ListBox";
-}
-
-void CPWL_ListBox::OnCreated() {
- m_pList->SetFontMap(GetFontMap());
- m_pListNotify = pdfium::MakeUnique<CPWL_List_Notify>(this);
- m_pList->SetNotify(m_pListNotify.get());
-
- SetHoverSel(HasFlag(PLBS_HOVERSEL));
- m_pList->SetMultipleSel(HasFlag(PLBS_MULTIPLESEL));
- m_pList->SetFontSize(GetCreationParam().fFontSize);
-
- m_bHoverSel = HasFlag(PLBS_HOVERSEL);
-}
-
-void CPWL_ListBox::OnDestroy() {
- // Make sure the notifier is removed from the list as we are about to
- // destroy the notifier and don't want to leave a dangling pointer.
- m_pList->SetNotify(nullptr);
- m_pListNotify.reset();
-}
-
-void CPWL_ListBox::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- CPWL_Wnd::GetThisAppearanceStream(sAppStream);
-
- CFX_ByteTextBuf sListItems;
-
- CFX_FloatRect rcPlate = m_pList->GetPlateRect();
- for (int32_t i = 0, sz = m_pList->GetCount(); i < sz; i++) {
- CFX_FloatRect rcItem = m_pList->GetItemRect(i);
-
- if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom)
- continue;
-
- CFX_PointF ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f);
- if (m_pList->IsItemSelected(i)) {
- sListItems << CPWL_Utils::GetRectFillAppStream(rcItem,
- PWL_DEFAULT_SELBACKCOLOR)
- .AsStringC();
- CFX_ByteString sItem =
- CPWL_Utils::GetEditAppStream(m_pList->GetItemEdit(i), ptOffset);
- if (sItem.GetLength() > 0) {
- sListItems << "BT\n"
- << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELTEXTCOLOR)
- .AsStringC()
- << sItem.AsStringC() << "ET\n";
- }
- } else {
- CFX_ByteString sItem =
- CPWL_Utils::GetEditAppStream(m_pList->GetItemEdit(i), ptOffset);
- if (sItem.GetLength() > 0) {
- sListItems << "BT\n"
- << CPWL_Utils::GetColorAppStream(GetTextColor()).AsStringC()
- << sItem.AsStringC() << "ET\n";
- }
- }
- }
-
- if (sListItems.GetLength() > 0) {
- CFX_ByteTextBuf sClip;
- CFX_FloatRect rcClient = GetClientRect();
-
- sClip << "q\n";
- sClip << rcClient.left << " " << rcClient.bottom << " "
- << rcClient.right - rcClient.left << " "
- << rcClient.top - rcClient.bottom << " re W n\n";
-
- sClip << sListItems << "Q\n";
-
- sAppStream << "/Tx BMC\n" << sClip << "EMC\n";
- }
-}
-
-void CPWL_ListBox::DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
-
- CFX_FloatRect rcPlate = m_pList->GetPlateRect();
- CFX_FloatRect rcList = GetListRect();
- CFX_FloatRect rcClient = GetClientRect();
-
- for (int32_t i = 0, sz = m_pList->GetCount(); i < sz; i++) {
- CFX_FloatRect rcItem = m_pList->GetItemRect(i);
- if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom)
- continue;
-
- CFX_PointF ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f);
- if (CFX_Edit* pEdit = m_pList->GetItemEdit(i)) {
- CFX_FloatRect rcContent = pEdit->GetContentRect();
- if (rcContent.Width() > rcClient.Width())
- rcItem.Intersect(rcList);
- else
- rcItem.Intersect(rcClient);
- }
-
- if (m_pList->IsItemSelected(i)) {
- CFX_SystemHandler* pSysHandler = GetSystemHandler();
- if (pSysHandler && pSysHandler->IsSelectionImplemented()) {
- CFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i),
- GetTextColor().ToFXColor(255), rcList, ptOffset,
- nullptr, pSysHandler, m_pFormFiller);
- pSysHandler->OutputSelectedRect(m_pFormFiller, rcItem);
- } else {
- CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcItem,
- ArgbEncode(255, 0, 51, 113));
- CFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i),
- ArgbEncode(255, 255, 255, 255), rcList, ptOffset,
- nullptr, pSysHandler, m_pFormFiller);
- }
- } else {
- CFX_SystemHandler* pSysHandler = GetSystemHandler();
- CFX_Edit::DrawEdit(pDevice, pUser2Device, m_pList->GetItemEdit(i),
- GetTextColor().ToFXColor(255), rcList, ptOffset,
- nullptr, pSysHandler, nullptr);
- }
- }
-}
-
-bool CPWL_ListBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
- CPWL_Wnd::OnKeyDown(nChar, nFlag);
-
- switch (nChar) {
- default:
- return false;
- case FWL_VKEY_Up:
- case FWL_VKEY_Down:
- case FWL_VKEY_Home:
- case FWL_VKEY_Left:
- case FWL_VKEY_End:
- case FWL_VKEY_Right:
- break;
- }
-
- switch (nChar) {
- case FWL_VKEY_Up:
- m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Down:
- m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Home:
- m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Left:
- m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_End:
- m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Right:
- m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- break;
- case FWL_VKEY_Delete:
- break;
- }
-
- bool bExit = false;
- OnNotifySelChanged(true, bExit, nFlag);
-
- return true;
-}
-
-bool CPWL_ListBox::OnChar(uint16_t nChar, uint32_t nFlag) {
- CPWL_Wnd::OnChar(nChar, nFlag);
-
- if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)))
- return false;
-
- bool bExit = false;
- OnNotifySelChanged(true, bExit, nFlag);
-
- return true;
-}
-
-bool CPWL_ListBox::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonDown(point, nFlag);
-
- if (ClientHitTest(point)) {
- m_bMouseDown = true;
- SetFocus();
- SetCapture();
-
- m_pList->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- }
-
- return true;
-}
-
-bool CPWL_ListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonUp(point, nFlag);
-
- if (m_bMouseDown) {
- ReleaseCapture();
- m_bMouseDown = false;
- }
-
- bool bExit = false;
- OnNotifySelChanged(false, bExit, nFlag);
-
- return true;
-}
-
-void CPWL_ListBox::SetHoverSel(bool bHoverSel) {
- m_bHoverSel = bHoverSel;
-}
-
-bool CPWL_ListBox::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnMouseMove(point, nFlag);
-
- if (m_bHoverSel && !IsCaptureMouse() && ClientHitTest(point))
- m_pList->Select(m_pList->GetItemIndex(point));
- if (m_bMouseDown)
- m_pList->OnMouseMove(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
-
- return true;
-}
-
-void CPWL_ListBox::OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam,
- intptr_t lParam) {
- CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
-
- FX_FLOAT fPos;
-
- switch (msg) {
- case PNM_SETSCROLLINFO:
- switch (wParam) {
- case SBT_VSCROLL:
- if (CPWL_Wnd* pChild = GetVScrollBar()) {
- pChild->OnNotify(pWnd, PNM_SETSCROLLINFO, wParam, lParam);
- }
- break;
- }
- break;
- case PNM_SETSCROLLPOS:
- switch (wParam) {
- case SBT_VSCROLL:
- if (CPWL_Wnd* pChild = GetVScrollBar()) {
- pChild->OnNotify(pWnd, PNM_SETSCROLLPOS, wParam, lParam);
- }
- break;
- }
- break;
- case PNM_SCROLLWINDOW:
- fPos = *(FX_FLOAT*)lParam;
- switch (wParam) {
- case SBT_VSCROLL:
- m_pList->SetScrollPos(CFX_PointF(0, fPos));
- break;
- }
- break;
- }
-}
-
-void CPWL_ListBox::KillFocus() {
- CPWL_Wnd::KillFocus();
-}
-
-void CPWL_ListBox::RePosChildWnd() {
- CPWL_Wnd::RePosChildWnd();
-
- m_pList->SetPlateRect(GetListRect());
-}
-
-void CPWL_ListBox::OnNotifySelChanged(bool bKeyDown,
- bool& bExit,
- uint32_t nFlag) {
- if (!m_pFillerNotify)
- return;
-
- bool bRC = true;
- CFX_WideString swChange = GetText();
- CFX_WideString strChangeEx;
- int nSelStart = 0;
- int nSelEnd = swChange.GetLength();
- m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), swChange, strChangeEx,
- nSelStart, nSelEnd, bKeyDown, bRC, bExit,
- nFlag);
-}
-
-CFX_FloatRect CPWL_ListBox::GetFocusRect() const {
- if (m_pList->IsMultipleSel()) {
- CFX_FloatRect rcCaret = m_pList->GetItemRect(m_pList->GetCaret());
- rcCaret.Intersect(GetClientRect());
- return rcCaret;
- }
-
- return CPWL_Wnd::GetFocusRect();
-}
-
-void CPWL_ListBox::AddString(const CFX_WideString& str) {
- m_pList->AddString(str);
-}
-
-CFX_WideString CPWL_ListBox::GetText() const {
- return m_pList->GetText();
-}
-
-void CPWL_ListBox::SetFontSize(FX_FLOAT fFontSize) {
- m_pList->SetFontSize(fFontSize);
-}
-
-FX_FLOAT CPWL_ListBox::GetFontSize() const {
- return m_pList->GetFontSize();
-}
-
-void CPWL_ListBox::Select(int32_t nItemIndex) {
- m_pList->Select(nItemIndex);
-}
-
-void CPWL_ListBox::SetCaret(int32_t nItemIndex) {
- m_pList->SetCaret(nItemIndex);
-}
-
-void CPWL_ListBox::SetTopVisibleIndex(int32_t nItemIndex) {
- m_pList->SetTopItem(nItemIndex);
-}
-
-void CPWL_ListBox::ScrollToListItem(int32_t nItemIndex) {
- m_pList->ScrollToListItem(nItemIndex);
-}
-
-void CPWL_ListBox::ResetContent() {
- m_pList->Empty();
-}
-
-void CPWL_ListBox::Reset() {
- m_pList->Cancel();
-}
-
-bool CPWL_ListBox::IsMultipleSel() const {
- return m_pList->IsMultipleSel();
-}
-
-int32_t CPWL_ListBox::GetCaretIndex() const {
- return m_pList->GetCaret();
-}
-
-int32_t CPWL_ListBox::GetCurSel() const {
- return m_pList->GetSelect();
-}
-
-bool CPWL_ListBox::IsItemSelected(int32_t nItemIndex) const {
- return m_pList->IsItemSelected(nItemIndex);
-}
-
-int32_t CPWL_ListBox::GetTopVisibleIndex() const {
- m_pList->ScrollToListItem(m_pList->GetFirstSelected());
- return m_pList->GetTopItem();
-}
-
-int32_t CPWL_ListBox::GetCount() const {
- return m_pList->GetCount();
-}
-
-int32_t CPWL_ListBox::FindNext(int32_t nIndex, FX_WCHAR nChar) const {
- return m_pList->FindNext(nIndex, nChar);
-}
-
-CFX_FloatRect CPWL_ListBox::GetContentRect() const {
- return m_pList->GetContentRect();
-}
-
-FX_FLOAT CPWL_ListBox::GetFirstHeight() const {
- return m_pList->GetFirstHeight();
-}
-
-CFX_FloatRect CPWL_ListBox::GetListRect() const {
- return CPWL_Utils::DeflateRect(
- GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
-}
-
-bool CPWL_ListBox::OnMouseWheel(short zDelta,
- const CFX_PointF& point,
- uint32_t nFlag) {
- if (zDelta < 0)
- m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
- else
- m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
-
- bool bExit = false;
- OnNotifySelChanged(false, bExit, nFlag);
- return true;
-}
diff --git a/fpdfsdk/pdfwindow/PWL_ListBox.h b/fpdfsdk/pdfwindow/PWL_ListBox.h
deleted file mode 100644
index f9108a1..0000000
--- a/fpdfsdk/pdfwindow/PWL_ListBox.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2014 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_PWL_LISTBOX_H_
-#define FPDFSDK_PDFWINDOW_PWL_LISTBOX_H_
-
-#include <memory>
-
-#include "fpdfsdk/fxedit/fx_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-class CFX_ListCtrl;
-class CPWL_List_Notify;
-class CPWL_ListBox;
-class IPWL_Filler_Notify;
-struct CPVT_SecProps;
-struct CPVT_WordPlace;
-struct CPVT_WordProps;
-
-class CPWL_List_Notify {
- public:
- explicit CPWL_List_Notify(CPWL_ListBox* pList);
- ~CPWL_List_Notify();
-
- void IOnSetScrollInfoY(FX_FLOAT fPlateMin,
- FX_FLOAT fPlateMax,
- FX_FLOAT fContentMin,
- FX_FLOAT fContentMax,
- FX_FLOAT fSmallStep,
- FX_FLOAT fBigStep);
- void IOnSetScrollPosY(FX_FLOAT fy);
- void IOnInvalidateRect(CFX_FloatRect* pRect);
-
- void IOnSetCaret(bool bVisible,
- const CFX_PointF& ptHead,
- const CFX_PointF& ptFoot,
- const CPVT_WordPlace& place);
-
- private:
- CPWL_ListBox* m_pList;
-};
-
-class CPWL_ListBox : public CPWL_Wnd {
- public:
- CPWL_ListBox();
- ~CPWL_ListBox() override;
-
- // CPWL_Wnd
- CFX_ByteString GetClassName() const override;
- void OnCreated() override;
- void OnDestroy() override;
- void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override;
- void DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
- bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override;
- bool OnChar(uint16_t nChar, uint32_t nFlag) override;
- bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override;
- bool OnMouseWheel(short zDelta,
- const CFX_PointF& point,
- uint32_t nFlag) override;
- void KillFocus() override;
- void OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam = 0,
- intptr_t lParam = 0) override;
- void RePosChildWnd() override;
- CFX_FloatRect GetFocusRect() const override;
- void SetFontSize(FX_FLOAT fFontSize) override;
- FX_FLOAT GetFontSize() const override;
-
- virtual CFX_WideString GetText() const;
-
- void OnNotifySelChanged(bool bKeyDown, bool& bExit, uint32_t nFlag);
-
- void AddString(const CFX_WideString& str);
- void SetTopVisibleIndex(int32_t nItemIndex);
- void ScrollToListItem(int32_t nItemIndex);
- void ResetContent();
- void Reset();
- void Select(int32_t nItemIndex);
- void SetCaret(int32_t nItemIndex);
- void SetHoverSel(bool bHoverSel);
-
- int32_t GetCount() const;
- bool IsMultipleSel() const;
- int32_t GetCaretIndex() const;
- int32_t GetCurSel() const;
- bool IsItemSelected(int32_t nItemIndex) const;
- int32_t GetTopVisibleIndex() const;
- int32_t FindNext(int32_t nIndex, FX_WCHAR nChar) const;
- CFX_FloatRect GetContentRect() const;
- FX_FLOAT GetFirstHeight() const;
- CFX_FloatRect GetListRect() const;
-
- void SetFillerNotify(IPWL_Filler_Notify* pNotify) {
- m_pFillerNotify = pNotify;
- }
-
- void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; }
-
- protected:
- std::unique_ptr<CFX_ListCtrl> m_pList;
- std::unique_ptr<CPWL_List_Notify> m_pListNotify;
- bool m_bMouseDown;
- bool m_bHoverSel;
- IPWL_Filler_Notify* m_pFillerNotify;
-
- private:
- CFFL_FormFiller* m_pFormFiller; // Not owned.
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_LISTBOX_H_
diff --git a/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp b/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp
deleted file mode 100644
index e379936..0000000
--- a/fpdfsdk/pdfwindow/PWL_ScrollBar.cpp
+++ /dev/null
@@ -1,1175 +0,0 @@
-// Copyright 2014 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/PWL_ScrollBar.h"
-
-#include "core/fxge/cfx_pathdata.h"
-#include "core/fxge/cfx_renderdevice.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-PWL_FLOATRANGE::PWL_FLOATRANGE() {
- Default();
-}
-
-PWL_FLOATRANGE::PWL_FLOATRANGE(FX_FLOAT min, FX_FLOAT max) {
- Set(min, max);
-}
-
-void PWL_FLOATRANGE::Default() {
- fMin = 0;
- fMax = 0;
-}
-
-void PWL_FLOATRANGE::Set(FX_FLOAT min, FX_FLOAT max) {
- if (min > max) {
- fMin = max;
- fMax = min;
- } else {
- fMin = min;
- fMax = max;
- }
-}
-
-bool PWL_FLOATRANGE::In(FX_FLOAT x) const {
- return (IsFloatBigger(x, fMin) || IsFloatEqual(x, fMin)) &&
- (IsFloatSmaller(x, fMax) || IsFloatEqual(x, fMax));
-}
-
-FX_FLOAT PWL_FLOATRANGE::GetWidth() const {
- return fMax - fMin;
-}
-
-PWL_SCROLL_PRIVATEDATA::PWL_SCROLL_PRIVATEDATA() {
- Default();
-}
-
-void PWL_SCROLL_PRIVATEDATA::Default() {
- ScrollRange.Default();
- fScrollPos = ScrollRange.fMin;
- fClientWidth = 0;
- fBigStep = 10;
- fSmallStep = 1;
-}
-
-void PWL_SCROLL_PRIVATEDATA::SetScrollRange(FX_FLOAT min, FX_FLOAT max) {
- ScrollRange.Set(min, max);
-
- if (IsFloatSmaller(fScrollPos, ScrollRange.fMin))
- fScrollPos = ScrollRange.fMin;
- if (IsFloatBigger(fScrollPos, ScrollRange.fMax))
- fScrollPos = ScrollRange.fMax;
-}
-
-void PWL_SCROLL_PRIVATEDATA::SetClientWidth(FX_FLOAT width) {
- fClientWidth = width;
-}
-
-void PWL_SCROLL_PRIVATEDATA::SetSmallStep(FX_FLOAT step) {
- fSmallStep = step;
-}
-
-void PWL_SCROLL_PRIVATEDATA::SetBigStep(FX_FLOAT step) {
- fBigStep = step;
-}
-
-bool PWL_SCROLL_PRIVATEDATA::SetPos(FX_FLOAT pos) {
- if (ScrollRange.In(pos)) {
- fScrollPos = pos;
- return true;
- }
- return false;
-}
-
-void PWL_SCROLL_PRIVATEDATA::AddSmall() {
- if (!SetPos(fScrollPos + fSmallStep))
- SetPos(ScrollRange.fMax);
-}
-
-void PWL_SCROLL_PRIVATEDATA::SubSmall() {
- if (!SetPos(fScrollPos - fSmallStep))
- SetPos(ScrollRange.fMin);
-}
-
-void PWL_SCROLL_PRIVATEDATA::AddBig() {
- if (!SetPos(fScrollPos + fBigStep))
- SetPos(ScrollRange.fMax);
-}
-
-void PWL_SCROLL_PRIVATEDATA::SubBig() {
- if (!SetPos(fScrollPos - fBigStep))
- SetPos(ScrollRange.fMin);
-}
-
-CPWL_SBButton::CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType,
- PWL_SBBUTTON_TYPE eButtonType) {
- m_eScrollBarType = eScrollBarType;
- m_eSBButtonType = eButtonType;
-
- m_bMouseDown = false;
-}
-
-CPWL_SBButton::~CPWL_SBButton() {}
-
-CFX_ByteString CPWL_SBButton::GetClassName() const {
- return "CPWL_SBButton";
-}
-
-void CPWL_SBButton::OnCreate(PWL_CREATEPARAM& cp) {
- cp.eCursorType = FXCT_ARROW;
-}
-
-void CPWL_SBButton::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- CPWL_Wnd::GetThisAppearanceStream(sAppStream);
-
- if (!IsVisible())
- return;
-
- CFX_ByteTextBuf sButton;
-
- CFX_FloatRect rectWnd = GetWindowRect();
-
- if (rectWnd.IsEmpty())
- return;
-
- sAppStream << "q\n";
-
- CFX_PointF ptCenter = GetCenterPoint();
-
- switch (m_eScrollBarType) {
- case SBT_HSCROLL:
- switch (m_eSBButtonType) {
- case PSBT_MIN: {
- CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y);
- CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f,
- ptCenter.y + PWL_TRIANGLE_HALFLEN);
- CFX_PointF pt3(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f,
- ptCenter.y - PWL_TRIANGLE_HALFLEN);
-
- if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
- rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
- sButton << "0 g\n";
- sButton << pt1.x << " " << pt1.y << " m\n";
- sButton << pt2.x << " " << pt2.y << " l\n";
- sButton << pt3.x << " " << pt3.y << " l\n";
- sButton << pt1.x << " " << pt1.y << " l f\n";
-
- sAppStream << sButton;
- }
- } break;
- case PSBT_MAX: {
- CFX_PointF pt1(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y);
- CFX_PointF pt2(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f,
- ptCenter.y + PWL_TRIANGLE_HALFLEN);
- CFX_PointF pt3(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f,
- ptCenter.y - PWL_TRIANGLE_HALFLEN);
-
- if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
- rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
- sButton << "0 g\n";
- sButton << pt1.x << " " << pt1.y << " m\n";
- sButton << pt2.x << " " << pt2.y << " l\n";
- sButton << pt3.x << " " << pt3.y << " l\n";
- sButton << pt1.x << " " << pt1.y << " l f\n";
-
- sAppStream << sButton;
- }
- } break;
- default:
- break;
- }
- break;
- case SBT_VSCROLL:
- switch (m_eSBButtonType) {
- case PSBT_MIN: {
- CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN,
- ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f);
- CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN,
- ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f);
- CFX_PointF pt3(ptCenter.x, ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f);
-
- if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
- rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
- sButton << "0 g\n";
- sButton << pt1.x << " " << pt1.y << " m\n";
- sButton << pt2.x << " " << pt2.y << " l\n";
- sButton << pt3.x << " " << pt3.y << " l\n";
- sButton << pt1.x << " " << pt1.y << " l f\n";
-
- sAppStream << sButton;
- }
- } break;
- case PSBT_MAX: {
- CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN,
- ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f);
- CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN,
- ptCenter.y + PWL_TRIANGLE_HALFLEN * 0.5f);
- CFX_PointF pt3(ptCenter.x, ptCenter.y - PWL_TRIANGLE_HALFLEN * 0.5f);
-
- if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
- rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
- sButton << "0 g\n";
- sButton << pt1.x << " " << pt1.y << " m\n";
- sButton << pt2.x << " " << pt2.y << " l\n";
- sButton << pt3.x << " " << pt3.y << " l\n";
- sButton << pt1.x << " " << pt1.y << " l f\n";
-
- sAppStream << sButton;
- }
- } break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- sAppStream << "Q\n";
-}
-
-void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- if (!IsVisible())
- return;
-
- CFX_FloatRect rectWnd = GetWindowRect();
- if (rectWnd.IsEmpty())
- return;
-
- CFX_PointF ptCenter = GetCenterPoint();
- int32_t nTransparency = GetTransparency();
-
- switch (m_eScrollBarType) {
- case SBT_HSCROLL:
- CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
- switch (m_eSBButtonType) {
- case PSBT_MIN: {
- CFX_PointF pt1(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y);
- CFX_PointF pt2(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f,
- ptCenter.y + PWL_TRIANGLE_HALFLEN);
- CFX_PointF pt3(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f,
- ptCenter.y - PWL_TRIANGLE_HALFLEN);
-
- if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
- rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
- CFX_PathData path;
- path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
- path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
- path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
- path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
-
- pDevice->DrawPath(&path, pUser2Device, nullptr,
- PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency),
- 0, FXFILL_ALTERNATE);
- }
- } break;
- case PSBT_MAX: {
- CFX_PointF pt1(ptCenter.x + PWL_TRIANGLE_HALFLEN * 0.5f, ptCenter.y);
- CFX_PointF pt2(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f,
- ptCenter.y + PWL_TRIANGLE_HALFLEN);
- CFX_PointF pt3(ptCenter.x - PWL_TRIANGLE_HALFLEN * 0.5f,
- ptCenter.y - PWL_TRIANGLE_HALFLEN);
-
- if (rectWnd.right - rectWnd.left > PWL_TRIANGLE_HALFLEN * 2 &&
- rectWnd.top - rectWnd.bottom > PWL_TRIANGLE_HALFLEN) {
- CFX_PathData path;
- path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
- path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
- path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
- path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
-
- pDevice->DrawPath(&path, pUser2Device, nullptr,
- PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency),
- 0, FXFILL_ALTERNATE);
- }
- } break;
- default:
- break;
- }
- break;
- case SBT_VSCROLL:
- switch (m_eSBButtonType) {
- case PSBT_MIN: {
- // draw border
- CFX_FloatRect rcDraw = rectWnd;
- CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(nTransparency, 100, 100, 100),
- 0.0f);
-
- // draw inner border
- rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f);
- CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(nTransparency, 255, 255, 255),
- 1.0f);
-
- // draw background
-
- rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f);
-
- if (IsEnabled())
- CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw,
- nTransparency, 80, 220);
- else
- CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(255, 255, 255, 255));
-
- // draw arrow
-
- if (rectWnd.top - rectWnd.bottom > 6.0f) {
- FX_FLOAT fX = rectWnd.left + 1.5f;
- FX_FLOAT fY = rectWnd.bottom;
- CFX_PointF pts[7] = {CFX_PointF(fX + 2.5f, fY + 4.0f),
- CFX_PointF(fX + 2.5f, fY + 3.0f),
- CFX_PointF(fX + 4.5f, fY + 5.0f),
- CFX_PointF(fX + 6.5f, fY + 3.0f),
- CFX_PointF(fX + 6.5f, fY + 4.0f),
- CFX_PointF(fX + 4.5f, fY + 6.0f),
- CFX_PointF(fX + 2.5f, fY + 4.0f)};
-
- if (IsEnabled())
- CPWL_Utils::DrawFillArea(
- pDevice, pUser2Device, pts, 7,
- ArgbEncode(nTransparency, 255, 255, 255));
- else
- CPWL_Utils::DrawFillArea(
- pDevice, pUser2Device, pts, 7,
- PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255));
- }
- } break;
- case PSBT_MAX: {
- // draw border
- CFX_FloatRect rcDraw = rectWnd;
- CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(nTransparency, 100, 100, 100),
- 0.0f);
-
- // draw inner border
- rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f);
- CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(nTransparency, 255, 255, 255),
- 1.0f);
-
- // draw background
- rcDraw = CPWL_Utils::DeflateRect(rectWnd, 1.0f);
- if (IsEnabled())
- CPWL_Utils::DrawShadow(pDevice, pUser2Device, true, false, rcDraw,
- nTransparency, 80, 220);
- else
- CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(255, 255, 255, 255));
-
- // draw arrow
-
- if (rectWnd.top - rectWnd.bottom > 6.0f) {
- FX_FLOAT fX = rectWnd.left + 1.5f;
- FX_FLOAT fY = rectWnd.bottom;
-
- CFX_PointF pts[7] = {CFX_PointF(fX + 2.5f, fY + 5.0f),
- CFX_PointF(fX + 2.5f, fY + 6.0f),
- CFX_PointF(fX + 4.5f, fY + 4.0f),
- CFX_PointF(fX + 6.5f, fY + 6.0f),
- CFX_PointF(fX + 6.5f, fY + 5.0f),
- CFX_PointF(fX + 4.5f, fY + 3.0f),
- CFX_PointF(fX + 2.5f, fY + 5.0f)};
-
- if (IsEnabled())
- CPWL_Utils::DrawFillArea(
- pDevice, pUser2Device, pts, 7,
- ArgbEncode(nTransparency, 255, 255, 255));
- else
- CPWL_Utils::DrawFillArea(
- pDevice, pUser2Device, pts, 7,
- PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255));
- }
- } break;
- case PSBT_POS: {
- // draw border
- CFX_FloatRect rcDraw = rectWnd;
- CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(nTransparency, 100, 100, 100),
- 0.0f);
-
- // draw inner border
- rcDraw = CPWL_Utils::DeflateRect(rectWnd, 0.5f);
- CPWL_Utils::DrawStrokeRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(nTransparency, 255, 255, 255),
- 1.0f);
-
- if (IsEnabled()) {
- // draw shadow effect
-
- CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f);
- CFX_PointF ptBottom =
- CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f);
-
- ptTop.x += 1.5f;
- ptBottom.x += 1.5f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 210, 210, 210),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 220, 220, 220),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 240, 240, 240),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 240, 240, 240),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 210, 210, 210),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 180, 180, 180),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 150, 150, 150),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 150, 150, 150),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 180, 180, 180),
- 1.0f);
-
- ptTop.x += 1.0f;
- ptBottom.x += 1.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptTop, ptBottom,
- ArgbEncode(nTransparency, 210, 210, 210),
- 1.0f);
- } else {
- CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcDraw,
- ArgbEncode(255, 255, 255, 255));
- }
-
- // draw friction
-
- if (rectWnd.Height() > 8.0f) {
- FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120);
- if (!IsEnabled())
- crStroke = PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255);
-
- FX_FLOAT nFrictionWidth = 5.0f;
- FX_FLOAT nFrictionHeight = 5.5f;
-
- CFX_PointF ptLeft =
- CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f,
- ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
- CFX_PointF ptRight =
- CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f,
- ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight,
- crStroke, 1.0f);
-
- ptLeft.y += 2.0f;
- ptRight.y += 2.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight,
- crStroke, 1.0f);
-
- ptLeft.y += 2.0f;
- ptRight.y += 2.0f;
-
- CPWL_Utils::DrawStrokeLine(pDevice, pUser2Device, ptLeft, ptRight,
- crStroke, 1.0f);
- }
- } break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-}
-
-bool CPWL_SBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonDown(point, nFlag);
-
- if (CPWL_Wnd* pParent = GetParentWindow())
- pParent->OnNotify(this, PNM_LBUTTONDOWN, 0, (intptr_t)&point);
-
- m_bMouseDown = true;
- SetCapture();
-
- return true;
-}
-
-bool CPWL_SBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonUp(point, nFlag);
-
- if (CPWL_Wnd* pParent = GetParentWindow())
- pParent->OnNotify(this, PNM_LBUTTONUP, 0, (intptr_t)&point);
-
- m_bMouseDown = false;
- ReleaseCapture();
-
- return true;
-}
-
-bool CPWL_SBButton::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnMouseMove(point, nFlag);
-
- if (CPWL_Wnd* pParent = GetParentWindow()) {
- pParent->OnNotify(this, PNM_MOUSEMOVE, 0, (intptr_t)&point);
- }
-
- return true;
-}
-
-CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType)
- : m_sbType(sbType),
- m_pMinButton(nullptr),
- m_pMaxButton(nullptr),
- m_pPosButton(nullptr),
- m_bMouseDown(false),
- m_bMinOrMax(false),
- m_bNotifyForever(true) {}
-
-CPWL_ScrollBar::~CPWL_ScrollBar() {}
-
-CFX_ByteString CPWL_ScrollBar::GetClassName() const {
- return "CPWL_ScrollBar";
-}
-
-void CPWL_ScrollBar::OnCreate(PWL_CREATEPARAM& cp) {
- cp.eCursorType = FXCT_ARROW;
-}
-
-void CPWL_ScrollBar::RePosChildWnd() {
- CFX_FloatRect rcClient = GetClientRect();
- CFX_FloatRect rcMinButton, rcMaxButton;
- FX_FLOAT fBWidth = 0;
-
- switch (m_sbType) {
- case SBT_HSCROLL:
- if (rcClient.right - rcClient.left >
- PWL_SCROLLBAR_BUTTON_WIDTH * 2 + PWL_SCROLLBAR_POSBUTTON_MINWIDTH +
- 2) {
- rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
- rcClient.left + PWL_SCROLLBAR_BUTTON_WIDTH,
- rcClient.top);
- rcMaxButton =
- CFX_FloatRect(rcClient.right - PWL_SCROLLBAR_BUTTON_WIDTH,
- rcClient.bottom, rcClient.right, rcClient.top);
- } else {
- fBWidth = (rcClient.right - rcClient.left -
- PWL_SCROLLBAR_POSBUTTON_MINWIDTH - 2) /
- 2;
-
- if (fBWidth > 0) {
- rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
- rcClient.left + fBWidth, rcClient.top);
- rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom,
- rcClient.right, rcClient.top);
- } else {
- SetVisible(false);
- }
- }
- break;
- case SBT_VSCROLL:
- if (IsFloatBigger(rcClient.top - rcClient.bottom,
- PWL_SCROLLBAR_BUTTON_WIDTH * 2 +
- PWL_SCROLLBAR_POSBUTTON_MINWIDTH + 2)) {
- rcMinButton = CFX_FloatRect(rcClient.left,
- rcClient.top - PWL_SCROLLBAR_BUTTON_WIDTH,
- rcClient.right, rcClient.top);
- rcMaxButton =
- CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
- rcClient.bottom + PWL_SCROLLBAR_BUTTON_WIDTH);
- } else {
- fBWidth = (rcClient.top - rcClient.bottom -
- PWL_SCROLLBAR_POSBUTTON_MINWIDTH - 2) /
- 2;
-
- if (IsFloatBigger(fBWidth, 0)) {
- rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth,
- rcClient.right, rcClient.top);
- rcMaxButton =
- CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
- rcClient.bottom + fBWidth);
- } else {
- SetVisible(false);
- }
- }
- break;
- }
-
- if (m_pMinButton)
- m_pMinButton->Move(rcMinButton, true, false);
- if (m_pMaxButton)
- m_pMaxButton->Move(rcMaxButton, true, false);
- MovePosButton(false);
-}
-
-void CPWL_ScrollBar::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- CFX_FloatRect rectWnd = GetWindowRect();
-
- if (IsVisible() && !rectWnd.IsEmpty()) {
- CFX_ByteTextBuf sButton;
-
- sButton << "q\n";
- sButton << "0 w\n"
- << CPWL_Utils::GetColorAppStream(GetBackgroundColor(), true)
- .AsStringC();
- sButton << rectWnd.left << " " << rectWnd.bottom << " "
- << rectWnd.right - rectWnd.left << " "
- << rectWnd.top - rectWnd.bottom << " re b Q\n";
-
- sAppStream << sButton;
- }
-}
-
-void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- CFX_FloatRect rectWnd = GetWindowRect();
-
- if (IsVisible() && !rectWnd.IsEmpty()) {
- CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rectWnd,
- GetBackgroundColor(), GetTransparency());
-
- CPWL_Utils::DrawStrokeLine(
- pDevice, pUser2Device,
- CFX_PointF(rectWnd.left + 2.0f, rectWnd.top - 2.0f),
- CFX_PointF(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f),
- ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
-
- CPWL_Utils::DrawStrokeLine(
- pDevice, pUser2Device,
- CFX_PointF(rectWnd.right - 2.0f, rectWnd.top - 2.0f),
- CFX_PointF(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f),
- ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
- }
-}
-
-bool CPWL_ScrollBar::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonDown(point, nFlag);
-
- if (HasFlag(PWS_AUTOTRANSPARENT)) {
- if (GetTransparency() != 255) {
- SetTransparency(255);
- InvalidateRect();
- }
- }
-
- CFX_FloatRect rcMinArea, rcMaxArea;
-
- if (m_pPosButton && m_pPosButton->IsVisible()) {
- CFX_FloatRect rcClient = GetClientRect();
- CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
-
- switch (m_sbType) {
- case SBT_HSCROLL:
- rcMinArea =
- CFX_FloatRect(rcClient.left + PWL_SCROLLBAR_BUTTON_WIDTH,
- rcClient.bottom, rcPosButton.left, rcClient.top);
- rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom,
- rcClient.right - PWL_SCROLLBAR_BUTTON_WIDTH,
- rcClient.top);
-
- break;
- case SBT_VSCROLL:
- rcMinArea =
- CFX_FloatRect(rcClient.left, rcPosButton.top, rcClient.right,
- rcClient.top - PWL_SCROLLBAR_BUTTON_WIDTH);
- rcMaxArea = CFX_FloatRect(rcClient.left,
- rcClient.bottom + PWL_SCROLLBAR_BUTTON_WIDTH,
- rcClient.right, rcPosButton.bottom);
- break;
- }
-
- rcMinArea.Normalize();
- rcMaxArea.Normalize();
-
- if (rcMinArea.Contains(point)) {
- m_sData.SubBig();
- MovePosButton(true);
- NotifyScrollWindow();
- }
-
- if (rcMaxArea.Contains(point)) {
- m_sData.AddBig();
- MovePosButton(true);
- NotifyScrollWindow();
- }
- }
-
- return true;
-}
-
-bool CPWL_ScrollBar::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
- CPWL_Wnd::OnLButtonUp(point, nFlag);
-
- if (HasFlag(PWS_AUTOTRANSPARENT)) {
- if (GetTransparency() != PWL_SCROLLBAR_TRANSPARENCY) {
- SetTransparency(PWL_SCROLLBAR_TRANSPARENCY);
- InvalidateRect();
- }
- }
-
- EndTimer();
- m_bMouseDown = false;
-
- return true;
-}
-
-void CPWL_ScrollBar::OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam,
- intptr_t lParam) {
- CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
-
- switch (msg) {
- case PNM_LBUTTONDOWN:
- if (pWnd == m_pMinButton) {
- OnMinButtonLBDown(*(CFX_PointF*)lParam);
- }
-
- if (pWnd == m_pMaxButton) {
- OnMaxButtonLBDown(*(CFX_PointF*)lParam);
- }
-
- if (pWnd == m_pPosButton) {
- OnPosButtonLBDown(*(CFX_PointF*)lParam);
- }
- break;
- case PNM_LBUTTONUP:
- if (pWnd == m_pMinButton) {
- OnMinButtonLBUp(*(CFX_PointF*)lParam);
- }
-
- if (pWnd == m_pMaxButton) {
- OnMaxButtonLBUp(*(CFX_PointF*)lParam);
- }
-
- if (pWnd == m_pPosButton) {
- OnPosButtonLBUp(*(CFX_PointF*)lParam);
- }
- break;
- case PNM_MOUSEMOVE:
- if (pWnd == m_pMinButton) {
- OnMinButtonMouseMove(*(CFX_PointF*)lParam);
- }
-
- if (pWnd == m_pMaxButton) {
- OnMaxButtonMouseMove(*(CFX_PointF*)lParam);
- }
-
- if (pWnd == m_pPosButton) {
- OnPosButtonMouseMove(*(CFX_PointF*)lParam);
- }
- break;
- case PNM_SETSCROLLINFO: {
- PWL_SCROLL_INFO* pInfo = reinterpret_cast<PWL_SCROLL_INFO*>(lParam);
- if (pInfo && *pInfo != m_OriginInfo) {
- m_OriginInfo = *pInfo;
- FX_FLOAT fMax =
- pInfo->fContentMax - pInfo->fContentMin - pInfo->fPlateWidth;
- fMax = fMax > 0.0f ? fMax : 0.0f;
- SetScrollRange(0, fMax, pInfo->fPlateWidth);
- SetScrollStep(pInfo->fBigStep, pInfo->fSmallStep);
- }
- } break;
- case PNM_SETSCROLLPOS: {
- FX_FLOAT fPos = *(FX_FLOAT*)lParam;
- switch (m_sbType) {
- case SBT_HSCROLL:
- fPos = fPos - m_OriginInfo.fContentMin;
- break;
- case SBT_VSCROLL:
- fPos = m_OriginInfo.fContentMax - fPos;
- break;
- }
- SetScrollPos(fPos);
- } break;
- }
-}
-
-void CPWL_ScrollBar::CreateButtons(const PWL_CREATEPARAM& cp) {
- PWL_CREATEPARAM scp = cp;
- scp.pParentWnd = this;
- scp.dwBorderWidth = 2;
- scp.nBorderStyle = BorderStyle::BEVELED;
-
- scp.dwFlags =
- PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP;
-
- if (!m_pMinButton) {
- m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN);
- m_pMinButton->Create(scp);
- }
-
- if (!m_pMaxButton) {
- m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX);
- m_pMaxButton->Create(scp);
- }
-
- if (!m_pPosButton) {
- m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS);
- m_pPosButton->SetVisible(false);
- m_pPosButton->Create(scp);
- }
-}
-
-FX_FLOAT CPWL_ScrollBar::GetScrollBarWidth() const {
- if (!IsVisible())
- return 0;
-
- return PWL_SCROLLBAR_WIDTH;
-}
-
-void CPWL_ScrollBar::SetScrollRange(FX_FLOAT fMin,
- FX_FLOAT fMax,
- FX_FLOAT fClientWidth) {
- if (m_pPosButton) {
- m_sData.SetScrollRange(fMin, fMax);
- m_sData.SetClientWidth(fClientWidth);
-
- if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) {
- m_pPosButton->SetVisible(false);
- } else {
- m_pPosButton->SetVisible(true);
- MovePosButton(true);
- }
- }
-}
-
-void CPWL_ScrollBar::SetScrollPos(FX_FLOAT fPos) {
- FX_FLOAT fOldPos = m_sData.fScrollPos;
-
- m_sData.SetPos(fPos);
-
- if (!IsFloatEqual(m_sData.fScrollPos, fOldPos))
- MovePosButton(true);
-}
-
-void CPWL_ScrollBar::SetScrollStep(FX_FLOAT fBigStep, FX_FLOAT fSmallStep) {
- m_sData.SetBigStep(fBigStep);
- m_sData.SetSmallStep(fSmallStep);
-}
-
-void CPWL_ScrollBar::MovePosButton(bool bRefresh) {
- ASSERT(m_pMinButton);
- ASSERT(m_pMaxButton);
-
- if (m_pPosButton->IsVisible()) {
- CFX_FloatRect rcClient;
- CFX_FloatRect rcPosArea, rcPosButton;
-
- rcClient = GetClientRect();
- rcPosArea = GetScrollArea();
-
- FX_FLOAT fLeft, fRight, fTop, fBottom;
-
- switch (m_sbType) {
- case SBT_HSCROLL:
- fLeft = TrueToFace(m_sData.fScrollPos);
- fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
-
- if (fRight - fLeft < PWL_SCROLLBAR_POSBUTTON_MINWIDTH)
- fRight = fLeft + PWL_SCROLLBAR_POSBUTTON_MINWIDTH;
-
- if (fRight > rcPosArea.right) {
- fRight = rcPosArea.right;
- fLeft = fRight - PWL_SCROLLBAR_POSBUTTON_MINWIDTH;
- }
-
- rcPosButton =
- CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top);
-
- break;
- case SBT_VSCROLL:
- fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
- fTop = TrueToFace(m_sData.fScrollPos);
-
- if (IsFloatSmaller(fTop - fBottom, PWL_SCROLLBAR_POSBUTTON_MINWIDTH))
- fBottom = fTop - PWL_SCROLLBAR_POSBUTTON_MINWIDTH;
-
- if (IsFloatSmaller(fBottom, rcPosArea.bottom)) {
- fBottom = rcPosArea.bottom;
- fTop = fBottom + PWL_SCROLLBAR_POSBUTTON_MINWIDTH;
- }
-
- rcPosButton =
- CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop);
-
- break;
- }
-
- m_pPosButton->Move(rcPosButton, true, bRefresh);
- }
-}
-
-void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_PointF& point) {
- m_sData.SubSmall();
- MovePosButton(true);
- NotifyScrollWindow();
-
- m_bMinOrMax = true;
-
- EndTimer();
- BeginTimer(100);
-}
-
-void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {}
-
-void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_PointF& point) {}
-
-void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_PointF& point) {
- m_sData.AddSmall();
- MovePosButton(true);
- NotifyScrollWindow();
-
- m_bMinOrMax = false;
-
- EndTimer();
- BeginTimer(100);
-}
-
-void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {}
-
-void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_PointF& point) {}
-
-void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_PointF& point) {
- m_bMouseDown = true;
-
- if (m_pPosButton) {
- CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
-
- switch (m_sbType) {
- case SBT_HSCROLL:
- m_nOldPos = point.x;
- m_fOldPosButton = rcPosButton.left;
- break;
- case SBT_VSCROLL:
- m_nOldPos = point.y;
- m_fOldPosButton = rcPosButton.top;
- break;
- }
- }
-}
-
-void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_PointF& point) {
- if (m_bMouseDown) {
- if (!m_bNotifyForever)
- NotifyScrollWindow();
- }
- m_bMouseDown = false;
-}
-
-void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_PointF& point) {
- FX_FLOAT fOldScrollPos = m_sData.fScrollPos;
-
- FX_FLOAT fNewPos = 0;
-
- switch (m_sbType) {
- case SBT_HSCROLL:
- if (FXSYS_fabs(point.x - m_nOldPos) < 1)
- return;
- fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos);
- break;
- case SBT_VSCROLL:
- if (FXSYS_fabs(point.y - m_nOldPos) < 1)
- return;
- fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos);
- break;
- }
-
- if (m_bMouseDown) {
- switch (m_sbType) {
- case SBT_HSCROLL:
-
- if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
- fNewPos = m_sData.ScrollRange.fMin;
- }
-
- if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
- fNewPos = m_sData.ScrollRange.fMax;
- }
-
- m_sData.SetPos(fNewPos);
-
- break;
- case SBT_VSCROLL:
-
- if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
- fNewPos = m_sData.ScrollRange.fMin;
- }
-
- if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
- fNewPos = m_sData.ScrollRange.fMax;
- }
-
- m_sData.SetPos(fNewPos);
-
- break;
- }
-
- if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) {
- MovePosButton(true);
-
- if (m_bNotifyForever)
- NotifyScrollWindow();
- }
- }
-}
-
-void CPWL_ScrollBar::NotifyScrollWindow() {
- if (CPWL_Wnd* pParent = GetParentWindow()) {
- FX_FLOAT fPos;
- switch (m_sbType) {
- case SBT_HSCROLL:
- fPos = m_OriginInfo.fContentMin + m_sData.fScrollPos;
- break;
- case SBT_VSCROLL:
- fPos = m_OriginInfo.fContentMax - m_sData.fScrollPos;
- break;
- }
- pParent->OnNotify(this, PNM_SCROLLWINDOW, (intptr_t)m_sbType,
- (intptr_t)&fPos);
- }
-}
-
-CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const {
- CFX_FloatRect rcClient = GetClientRect();
- CFX_FloatRect rcArea;
-
- if (!m_pMinButton || !m_pMaxButton)
- return rcClient;
-
- CFX_FloatRect rcMin = m_pMinButton->GetWindowRect();
- CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect();
-
- FX_FLOAT fMinWidth = rcMin.right - rcMin.left;
- FX_FLOAT fMinHeight = rcMin.top - rcMin.bottom;
- FX_FLOAT fMaxWidth = rcMax.right - rcMax.left;
- FX_FLOAT fMaxHeight = rcMax.top - rcMax.bottom;
-
- switch (m_sbType) {
- case SBT_HSCROLL:
- if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) {
- rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
- rcClient.right - fMaxWidth - 1, rcClient.top);
- } else {
- rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
- rcClient.left + fMinWidth + 1, rcClient.top);
- }
- break;
- case SBT_VSCROLL:
- if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) {
- rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
- rcClient.right, rcClient.top - fMaxHeight - 1);
- } else {
- rcArea =
- CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
- rcClient.right, rcClient.bottom + fMinHeight + 1);
- }
- break;
- }
-
- rcArea.Normalize();
-
- return rcArea;
-}
-
-FX_FLOAT CPWL_ScrollBar::TrueToFace(FX_FLOAT fTrue) {
- CFX_FloatRect rcPosArea;
- rcPosArea = GetScrollArea();
-
- FX_FLOAT fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
- fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
-
- FX_FLOAT fFace = 0;
-
- switch (m_sbType) {
- case SBT_HSCROLL:
- fFace = rcPosArea.left +
- fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth;
- break;
- case SBT_VSCROLL:
- fFace = rcPosArea.top -
- fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth;
- break;
- }
-
- return fFace;
-}
-
-FX_FLOAT CPWL_ScrollBar::FaceToTrue(FX_FLOAT fFace) {
- CFX_FloatRect rcPosArea;
- rcPosArea = GetScrollArea();
-
- FX_FLOAT fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
- fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
-
- FX_FLOAT fTrue = 0;
-
- switch (m_sbType) {
- case SBT_HSCROLL:
- fTrue = (fFace - rcPosArea.left) * fFactWidth /
- (rcPosArea.right - rcPosArea.left);
- break;
- case SBT_VSCROLL:
- fTrue = (rcPosArea.top - fFace) * fFactWidth /
- (rcPosArea.top - rcPosArea.bottom);
- break;
- }
-
- return fTrue;
-}
-
-void CPWL_ScrollBar::CreateChildWnd(const PWL_CREATEPARAM& cp) {
- CreateButtons(cp);
-}
-
-void CPWL_ScrollBar::TimerProc() {
- PWL_SCROLL_PRIVATEDATA sTemp = m_sData;
- if (m_bMinOrMax)
- m_sData.SubSmall();
- else
- m_sData.AddSmall();
-
- if (sTemp != m_sData) {
- MovePosButton(true);
- NotifyScrollWindow();
- }
-}
diff --git a/fpdfsdk/pdfwindow/PWL_Utils.cpp b/fpdfsdk/pdfwindow/PWL_Utils.cpp
deleted file mode 100644
index 45668b6..0000000
--- a/fpdfsdk/pdfwindow/PWL_Utils.cpp
+++ /dev/null
@@ -1,1172 +0,0 @@
-// Copyright 2014 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/PWL_Utils.h"
-
-#include <algorithm>
-#include <memory>
-
-#include "core/fpdfdoc/cpvt_word.h"
-#include "core/fxge/cfx_graphstatedata.h"
-#include "core/fxge/cfx_pathdata.h"
-#include "core/fxge/cfx_renderdevice.h"
-#include "fpdfsdk/fxedit/fxet_edit.h"
-#include "fpdfsdk/pdfwindow/PWL_Icon.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-CFX_FloatRect CPWL_Utils::OffsetRect(const CFX_FloatRect& rect,
- FX_FLOAT x,
- FX_FLOAT y) {
- return CFX_FloatRect(rect.left + x, rect.bottom + y, rect.right + x,
- rect.top + y);
-}
-
-CPVT_WordRange CPWL_Utils::OverlapWordRange(const CPVT_WordRange& wr1,
- const CPVT_WordRange& wr2) {
- CPVT_WordRange wrRet;
-
- if (wr2.EndPos.WordCmp(wr1.BeginPos) < 0 ||
- wr2.BeginPos.WordCmp(wr1.EndPos) > 0)
- return wrRet;
- if (wr1.EndPos.WordCmp(wr2.BeginPos) < 0 ||
- wr1.BeginPos.WordCmp(wr2.EndPos) > 0)
- return wrRet;
-
- if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0) {
- wrRet.BeginPos = wr2.BeginPos;
- } else {
- wrRet.BeginPos = wr1.BeginPos;
- }
-
- if (wr1.EndPos.WordCmp(wr2.EndPos) < 0) {
- wrRet.EndPos = wr1.EndPos;
- } else {
- wrRet.EndPos = wr2.EndPos;
- }
-
- return wrRet;
-}
-
-CFX_ByteString CPWL_Utils::GetAP_Check(const CFX_FloatRect& crBBox) {
- const FX_FLOAT fWidth = crBBox.right - crBBox.left;
- const FX_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;
- }
- }
-
- CFX_ByteTextBuf 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;
-
- FX_FLOAT px1 = pts[i][1].x - pts[i][0].x;
- FX_FLOAT py1 = pts[i][1].y - pts[i][0].y;
- FX_FLOAT px2 = pts[i][2].x - pts[nNext][0].x;
- FX_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 csAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAP_Circle(const CFX_FloatRect& crBBox) {
- CFX_ByteTextBuf csAP;
-
- FX_FLOAT fWidth = crBBox.right - crBBox.left;
- FX_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";
-
- FX_FLOAT px = pt2.x - pt1.x;
- FX_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 csAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAP_Cross(const CFX_FloatRect& crBBox) {
- CFX_ByteTextBuf 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 csAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAP_Diamond(const CFX_FloatRect& crBBox) {
- CFX_ByteTextBuf csAP;
-
- FX_FLOAT fWidth = crBBox.right - crBBox.left;
- FX_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 csAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAP_Square(const CFX_FloatRect& crBBox) {
- CFX_ByteTextBuf 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 csAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAP_Star(const CFX_FloatRect& crBBox) {
- CFX_ByteTextBuf csAP;
-
- FX_FLOAT fRadius =
- (crBBox.top - crBBox.bottom) / (1 + (FX_FLOAT)cos(FX_PI / 5.0f));
- CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f,
- (crBBox.top + crBBox.bottom) / 2.0f);
-
- FX_FLOAT px[5], py[5];
-
- FX_FLOAT fAngel = FX_PI / 10.0f;
-
- for (int32_t i = 0; i < 5; i++) {
- px[i] = ptCenter.x + fRadius * (FX_FLOAT)cos(fAngel);
- py[i] = ptCenter.y + fRadius * (FX_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 csAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAP_HalfCircle(const CFX_FloatRect& crBBox,
- FX_FLOAT fRotate) {
- CFX_ByteTextBuf csAP;
-
- FX_FLOAT fWidth = crBBox.right - crBBox.left;
- FX_FLOAT fHeight = crBBox.top - crBBox.bottom;
-
- CFX_PointF pt1(-fWidth / 2, 0);
- CFX_PointF pt2(0, fHeight / 2);
- CFX_PointF pt3(fWidth / 2, 0);
-
- FX_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 csAP.MakeString();
-}
-
-CFX_FloatRect CPWL_Utils::InflateRect(const CFX_FloatRect& rcRect,
- FX_FLOAT fSize) {
- if (rcRect.IsEmpty())
- return rcRect;
-
- CFX_FloatRect rcNew(rcRect.left - fSize, rcRect.bottom - fSize,
- rcRect.right + fSize, rcRect.top + fSize);
- rcNew.Normalize();
- return rcNew;
-}
-
-CFX_FloatRect CPWL_Utils::DeflateRect(const CFX_FloatRect& rcRect,
- FX_FLOAT fSize) {
- if (rcRect.IsEmpty())
- return rcRect;
-
- CFX_FloatRect rcNew(rcRect.left + fSize, rcRect.bottom + fSize,
- rcRect.right - fSize, rcRect.top - fSize);
- rcNew.Normalize();
- return rcNew;
-}
-
-CFX_FloatRect CPWL_Utils::ScaleRect(const CFX_FloatRect& rcRect,
- FX_FLOAT fScale) {
- FX_FLOAT fHalfWidth = (rcRect.right - rcRect.left) / 2.0f;
- FX_FLOAT fHalfHeight = (rcRect.top - rcRect.bottom) / 2.0f;
-
- CFX_PointF ptCenter = CFX_PointF((rcRect.left + rcRect.right) / 2,
- (rcRect.top + rcRect.bottom) / 2);
-
- return CFX_FloatRect(
- ptCenter.x - fHalfWidth * fScale, ptCenter.y - fHalfHeight * fScale,
- ptCenter.x + fHalfWidth * fScale, ptCenter.y + fHalfHeight * fScale);
-}
-
-CFX_ByteString CPWL_Utils::GetRectFillAppStream(const CFX_FloatRect& rect,
- const CPWL_Color& color) {
- CFX_ByteTextBuf sAppStream;
- CFX_ByteString sColor = GetColorAppStream(color, true);
- if (sColor.GetLength() > 0) {
- sAppStream << "q\n" << sColor;
- sAppStream << rect.left << " " << rect.bottom << " "
- << rect.right - rect.left << " " << rect.top - rect.bottom
- << " re f\nQ\n";
- }
-
- return sAppStream.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetCircleFillAppStream(const CFX_FloatRect& rect,
- const CPWL_Color& color) {
- CFX_ByteTextBuf sAppStream;
- CFX_ByteString sColor = GetColorAppStream(color, true);
- if (sColor.GetLength() > 0) {
- sAppStream << "q\n" << sColor << CPWL_Utils::GetAP_Circle(rect) << "f\nQ\n";
- }
- return sAppStream.MakeString();
-}
-
-CFX_FloatRect CPWL_Utils::GetCenterSquare(const CFX_FloatRect& rect) {
- FX_FLOAT fWidth = rect.right - rect.left;
- FX_FLOAT fHeight = rect.top - rect.bottom;
-
- FX_FLOAT fCenterX = (rect.left + rect.right) / 2.0f;
- FX_FLOAT fCenterY = (rect.top + rect.bottom) / 2.0f;
-
- FX_FLOAT fRadius = (fWidth > fHeight) ? fHeight / 2 : fWidth / 2;
-
- return CFX_FloatRect(fCenterX - fRadius, fCenterY - fRadius,
- fCenterX + fRadius, fCenterY + fRadius);
-}
-
-CFX_ByteString CPWL_Utils::GetEditAppStream(CFX_Edit* pEdit,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange,
- bool bContinuous,
- uint16_t SubWord) {
- return CFX_Edit::GetEditAppearanceStream(pEdit, ptOffset, pRange, bContinuous,
- SubWord);
-}
-
-CFX_ByteString CPWL_Utils::GetEditSelAppStream(CFX_Edit* pEdit,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange) {
- 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 CPWL_Color& crText,
- FX_FLOAT fFontSize,
- int32_t nLayOut) {
- const FX_FLOAT fAutoFontScale = 1.0f / 3.0f;
-
- std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit);
- 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(0, 0, 0, 0);
- CFX_FloatRect rcIcon = CFX_FloatRect(0, 0, 0, 0);
- FX_FLOAT fWidth = 0.0f;
- FX_FLOAT fHeight = 0.0f;
-
- switch (nLayOut) {
- case PPBL_LABEL:
- rcLabel = rcBBox;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- break;
- case PPBL_ICON:
- rcIcon = rcBBox;
- rcLabel = CFX_FloatRect(0, 0, 0, 0);
- 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) {
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- 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;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- }
-
- 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) {
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- 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;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- }
-
- break;
- case PPBL_ICONLEFTLABELRIGHT:
-
- if (pIconStream) {
- if (IsFloatZero(fFontSize)) {
- fWidth = rcBBox.right - rcBBox.left;
- rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale,
- rcBBox.bottom, rcBBox.right, rcBBox.top);
- rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left,
- rcBBox.top);
-
- if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
- } 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;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- }
- }
- } else {
- fWidth = rcLabelContent.Width();
-
- if (rcBBox.left + fWidth > rcBBox.right) {
- rcLabel = rcBBox;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- } 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;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- }
-
- break;
- case PPBL_LABELLEFTICONRIGHT:
-
- if (pIconStream) {
- if (IsFloatZero(fFontSize)) {
- fWidth = rcBBox.right - rcBBox.left;
- rcLabel =
- CFX_FloatRect(rcBBox.left, rcBBox.bottom,
- rcBBox.left + fWidth * fAutoFontScale, rcBBox.top);
- rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right,
- rcBBox.top);
-
- if (rcLabelContent.Width() < fWidth * fAutoFontScale) {
- } 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;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- }
- }
- } else {
- fWidth = rcLabelContent.Width();
-
- if (rcBBox.left + fWidth > rcBBox.right) {
- rcLabel = rcBBox;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- } 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;
- rcIcon = CFX_FloatRect(0, 0, 0, 0);
- }
-
- break;
- case PPBL_LABELOVERICON:
- rcLabel = rcBBox;
- rcIcon = rcBBox;
- break;
- }
-
- CFX_ByteTextBuf sAppStream, 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.GetSize() > 0) {
- sAppStream << "q\n"
- << rcBBox.left << " " << rcBBox.bottom << " "
- << rcBBox.right - rcBBox.left << " "
- << rcBBox.top - rcBBox.bottom << " re W n\n";
- sAppStream << sTemp << "Q\n";
- }
- return sAppStream.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetColorAppStream(const CPWL_Color& color,
- const bool& bFillOrStroke) {
- CFX_ByteTextBuf sColorStream;
-
- switch (color.nColorType) {
- case COLORTYPE_RGB:
- sColorStream << color.fColor1 << " " << color.fColor2 << " "
- << color.fColor3 << " " << (bFillOrStroke ? "rg" : "RG")
- << "\n";
- break;
- case COLORTYPE_GRAY:
- sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G")
- << "\n";
- break;
- case COLORTYPE_CMYK:
- sColorStream << color.fColor1 << " " << color.fColor2 << " "
- << color.fColor3 << " " << color.fColor4 << " "
- << (bFillOrStroke ? "k" : "K") << "\n";
- break;
- }
-
- return sColorStream.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetBorderAppStream(const CFX_FloatRect& rect,
- FX_FLOAT fWidth,
- const CPWL_Color& color,
- const CPWL_Color& crLeftTop,
- const CPWL_Color& crRightBottom,
- BorderStyle nStyle,
- const CPWL_Dash& dash) {
- CFX_ByteTextBuf sAppStream;
- CFX_ByteString sColor;
-
- FX_FLOAT fLeft = rect.left;
- FX_FLOAT fRight = rect.right;
- FX_FLOAT fTop = rect.top;
- FX_FLOAT fBottom = rect.bottom;
-
- if (fWidth > 0.0f) {
- FX_FLOAT fHalfWidth = fWidth / 2.0f;
-
- sAppStream << "q\n";
-
- switch (nStyle) {
- default:
- case BorderStyle::SOLID:
- sColor = CPWL_Utils::GetColorAppStream(color, true);
- if (sColor.GetLength() > 0) {
- sAppStream << sColor;
- sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
- << fTop - fBottom << " re\n";
- sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " "
- << fRight - fLeft - fWidth * 2 << " "
- << fTop - fBottom - fWidth * 2 << " re\n";
- sAppStream << "f*\n";
- }
- break;
- case BorderStyle::DASH:
- sColor = CPWL_Utils::GetColorAppStream(color, false);
- if (sColor.GetLength() > 0) {
- sAppStream << sColor;
- sAppStream << fWidth << " w"
- << " [" << dash.nDash << " " << dash.nGap << "] "
- << dash.nPhase << " d\n";
- sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2
- << " m\n";
- sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2
- << " l\n";
- sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2
- << " l\n";
- sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2
- << " l\n";
- sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2
- << " l S\n";
- }
- break;
- case BorderStyle::BEVELED:
- case BorderStyle::INSET:
- sColor = CPWL_Utils::GetColorAppStream(crLeftTop, true);
- if (sColor.GetLength() > 0) {
- sAppStream << sColor;
- sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth
- << " m\n";
- sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth
- << " l\n";
- sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth
- << " l\n";
- sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
- << " l\n";
- sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
- << " l\n";
- sAppStream << fLeft + fHalfWidth * 2 << " "
- << fBottom + fHalfWidth * 2 << " l f\n";
- }
-
- sColor = CPWL_Utils::GetColorAppStream(crRightBottom, true);
- if (sColor.GetLength() > 0) {
- sAppStream << sColor;
- sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth
- << " m\n";
- sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth
- << " l\n";
- sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth
- << " l\n";
- sAppStream << fLeft + fHalfWidth * 2 << " "
- << fBottom + fHalfWidth * 2 << " l\n";
- sAppStream << fRight - fHalfWidth * 2 << " "
- << fBottom + fHalfWidth * 2 << " l\n";
- sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
- << " l f\n";
- }
-
- sColor = CPWL_Utils::GetColorAppStream(color, true);
- if (sColor.GetLength() > 0) {
- sAppStream << sColor;
- sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
- << fTop - fBottom << " re\n";
- sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
- << fRight - fLeft - fHalfWidth * 2 << " "
- << fTop - fBottom - fHalfWidth * 2 << " re f*\n";
- }
- break;
- case BorderStyle::UNDERLINE:
- sColor = CPWL_Utils::GetColorAppStream(color, false);
- if (sColor.GetLength() > 0) {
- sAppStream << sColor;
- sAppStream << fWidth << " w\n";
- sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n";
- sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n";
- }
- break;
- }
-
- sAppStream << "Q\n";
- }
-
- return sAppStream.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetCircleBorderAppStream(
- const CFX_FloatRect& rect,
- FX_FLOAT fWidth,
- const CPWL_Color& color,
- const CPWL_Color& crLeftTop,
- const CPWL_Color& crRightBottom,
- BorderStyle nStyle,
- const CPWL_Dash& dash) {
- CFX_ByteTextBuf sAppStream;
- CFX_ByteString sColor;
-
- if (fWidth > 0.0f) {
- sAppStream << "q\n";
-
- 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(
- CPWL_Utils::DeflateRect(rect, fWidth / 2.0f))
- << " 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(
- CPWL_Utils::DeflateRect(rect, fWidth / 2.0f))
- << " S\nQ\n";
- }
- } break;
- case BorderStyle::BEVELED: {
- FX_FLOAT fHalfWidth = fWidth / 2.0f;
-
- 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(
- CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f),
- 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(
- CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f),
- FX_PI * 5 / 4.0f)
- << " S\nQ\n";
- }
- } break;
- case BorderStyle::INSET: {
- FX_FLOAT fHalfWidth = fWidth / 2.0f;
-
- 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(
- CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f),
- 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(
- CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f),
- FX_PI * 5 / 4.0f)
- << " S\nQ\n";
- }
- } break;
- }
-
- sAppStream << "Q\n";
- }
-
- return sAppStream.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAppStream_Check(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText) {
- CFX_ByteTextBuf sAP;
- sAP << "q\n"
- << CPWL_Utils::GetColorAppStream(crText, true)
- << CPWL_Utils::GetAP_Check(rcBBox) << "f\nQ\n";
- return sAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAppStream_Circle(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText) {
- CFX_ByteTextBuf sAP;
- sAP << "q\n"
- << CPWL_Utils::GetColorAppStream(crText, true)
- << CPWL_Utils::GetAP_Circle(rcBBox) << "f\nQ\n";
- return sAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAppStream_Cross(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText) {
- CFX_ByteTextBuf sAP;
- sAP << "q\n"
- << CPWL_Utils::GetColorAppStream(crText, false)
- << CPWL_Utils::GetAP_Cross(rcBBox) << "S\nQ\n";
- return sAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAppStream_Diamond(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText) {
- CFX_ByteTextBuf sAP;
- sAP << "q\n1 w\n"
- << CPWL_Utils::GetColorAppStream(crText, true)
- << CPWL_Utils::GetAP_Diamond(rcBBox) << "f\nQ\n";
- return sAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAppStream_Square(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText) {
- CFX_ByteTextBuf sAP;
- sAP << "q\n"
- << CPWL_Utils::GetColorAppStream(crText, true)
- << CPWL_Utils::GetAP_Square(rcBBox) << "f\nQ\n";
- return sAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetAppStream_Star(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText) {
- CFX_ByteTextBuf sAP;
- sAP << "q\n"
- << CPWL_Utils::GetColorAppStream(crText, true)
- << CPWL_Utils::GetAP_Star(rcBBox) << "f\nQ\n";
- return sAP.MakeString();
-}
-
-CFX_ByteString CPWL_Utils::GetCheckBoxAppStream(const CFX_FloatRect& rcBBox,
- int32_t nStyle,
- const CPWL_Color& crText) {
- CFX_FloatRect rcCenter = GetCenterSquare(rcBBox);
- switch (nStyle) {
- default:
- case PCS_CHECK:
- return GetAppStream_Check(rcCenter, crText);
- case PCS_CIRCLE:
- return GetAppStream_Circle(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
- case PCS_CROSS:
- return GetAppStream_Cross(rcCenter, crText);
- case PCS_DIAMOND:
- return GetAppStream_Diamond(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
- case PCS_SQUARE:
- return GetAppStream_Square(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
- case PCS_STAR:
- return GetAppStream_Star(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
- }
-}
-
-CFX_ByteString CPWL_Utils::GetRadioButtonAppStream(const CFX_FloatRect& rcBBox,
- int32_t nStyle,
- const CPWL_Color& crText) {
- CFX_FloatRect rcCenter = GetCenterSquare(rcBBox);
- switch (nStyle) {
- default:
- case PCS_CHECK:
- return GetAppStream_Check(rcCenter, crText);
- case PCS_CIRCLE:
- return GetAppStream_Circle(ScaleRect(rcCenter, 1.0f / 2.0f), crText);
- case PCS_CROSS:
- return GetAppStream_Cross(rcCenter, crText);
- case PCS_DIAMOND:
- return GetAppStream_Diamond(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
- case PCS_SQUARE:
- return GetAppStream_Square(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
- case PCS_STAR:
- return GetAppStream_Star(ScaleRect(rcCenter, 2.0f / 3.0f), crText);
- }
-}
-
-CFX_ByteString CPWL_Utils::GetDropButtonAppStream(const CFX_FloatRect& rcBBox) {
- CFX_ByteTextBuf sAppStream;
-
- if (!rcBBox.IsEmpty()) {
- sAppStream << "q\n"
- << CPWL_Utils::GetColorAppStream(
- CPWL_Color(COLORTYPE_RGB, 220.0f / 255.0f,
- 220.0f / 255.0f, 220.0f / 255.0f),
- true);
- sAppStream << rcBBox.left << " " << rcBBox.bottom << " "
- << rcBBox.right - rcBBox.left << " "
- << rcBBox.top - rcBBox.bottom << " re f\n";
- sAppStream << "Q\n";
-
- sAppStream << "q\n"
- << CPWL_Utils::GetBorderAppStream(
- rcBBox, 2, CPWL_Color(COLORTYPE_GRAY, 0),
- CPWL_Color(COLORTYPE_GRAY, 1),
- CPWL_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";
- sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n";
- sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n";
- sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n";
- sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n";
- sAppStream << "Q\n";
- }
- }
-
- return sAppStream.MakeString();
-}
-
-void CPWL_Utils::DrawFillRect(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_FloatRect& rect,
- const FX_COLORREF& color) {
- CFX_PathData path;
- CFX_FloatRect rcTemp(rect);
- path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top);
- pDevice->DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_WINDING);
-}
-
-void CPWL_Utils::DrawFillArea(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_PointF* pPts,
- int32_t nCount,
- const FX_COLORREF& color) {
- CFX_PathData path;
- path.AppendPoint(pPts[0], FXPT_TYPE::MoveTo, false);
- for (int32_t i = 1; i < nCount; i++)
- path.AppendPoint(pPts[i], FXPT_TYPE::LineTo, false);
-
- pDevice->DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_ALTERNATE);
-}
-
-void CPWL_Utils::DrawStrokeRect(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_FloatRect& rect,
- const FX_COLORREF& color,
- FX_FLOAT fWidth) {
- CFX_PathData path;
- CFX_FloatRect rcTemp(rect);
- path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top);
-
- CFX_GraphStateData gsd;
- gsd.m_LineWidth = fWidth;
-
- pDevice->DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE);
-}
-
-void CPWL_Utils::DrawStrokeLine(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_PointF& ptMoveTo,
- const CFX_PointF& ptLineTo,
- const FX_COLORREF& color,
- FX_FLOAT fWidth) {
- CFX_PathData path;
- path.AppendPoint(ptMoveTo, FXPT_TYPE::MoveTo, false);
- path.AppendPoint(ptLineTo, FXPT_TYPE::LineTo, false);
-
- CFX_GraphStateData gsd;
- gsd.m_LineWidth = fWidth;
-
- pDevice->DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE);
-}
-
-void CPWL_Utils::DrawFillRect(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_FloatRect& rect,
- const CPWL_Color& color,
- int32_t nTransparency) {
- CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rect,
- color.ToFXColor(nTransparency));
-}
-
-void CPWL_Utils::DrawShadow(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- bool bVertical,
- bool bHorizontal,
- CFX_FloatRect rect,
- int32_t nTransparency,
- int32_t nStartGray,
- int32_t nEndGray) {
- FX_FLOAT fStepGray = 1.0f;
-
- if (bVertical) {
- fStepGray = (nEndGray - nStartGray) / rect.Height();
-
- for (FX_FLOAT fy = rect.bottom + 0.5f; fy <= rect.top - 0.5f; fy += 1.0f) {
- int32_t nGray = nStartGray + (int32_t)(fStepGray * (fy - rect.bottom));
- CPWL_Utils::DrawStrokeLine(
- pDevice, pUser2Device, CFX_PointF(rect.left, fy),
- CFX_PointF(rect.right, fy),
- ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f);
- }
- }
-
- if (bHorizontal) {
- fStepGray = (nEndGray - nStartGray) / rect.Width();
-
- for (FX_FLOAT fx = rect.left + 0.5f; fx <= rect.right - 0.5f; fx += 1.0f) {
- int32_t nGray = nStartGray + (int32_t)(fStepGray * (fx - rect.left));
- CPWL_Utils::DrawStrokeLine(
- pDevice, pUser2Device, CFX_PointF(fx, rect.bottom),
- CFX_PointF(fx, rect.top),
- ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f);
- }
- }
-}
-
-void CPWL_Utils::DrawBorder(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_FloatRect& rect,
- FX_FLOAT fWidth,
- const CPWL_Color& color,
- const CPWL_Color& crLeftTop,
- const CPWL_Color& crRightBottom,
- BorderStyle nStyle,
- int32_t nTransparency) {
- FX_FLOAT fLeft = rect.left;
- FX_FLOAT fRight = rect.right;
- FX_FLOAT fTop = rect.top;
- FX_FLOAT fBottom = rect.bottom;
-
- if (fWidth > 0.0f) {
- FX_FLOAT fHalfWidth = fWidth / 2.0f;
-
- switch (nStyle) {
- default:
- case BorderStyle::SOLID: {
- CFX_PathData path;
- path.AppendRect(fLeft, fBottom, fRight, fTop);
- path.AppendRect(fLeft + fWidth, fBottom + fWidth, fRight - fWidth,
- fTop - fWidth);
- pDevice->DrawPath(&path, pUser2Device, nullptr,
- color.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE);
- break;
- }
- case BorderStyle::DASH: {
- CFX_PathData path;
- path.AppendPoint(
- CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f),
- FXPT_TYPE::MoveTo, false);
- path.AppendPoint(
- CFX_PointF(fLeft + fWidth / 2.0f, fTop - fWidth / 2.0f),
- FXPT_TYPE::LineTo, false);
- path.AppendPoint(
- CFX_PointF(fRight - fWidth / 2.0f, fTop - fWidth / 2.0f),
- FXPT_TYPE::LineTo, false);
- path.AppendPoint(
- CFX_PointF(fRight - fWidth / 2.0f, fBottom + fWidth / 2.0f),
- FXPT_TYPE::LineTo, false);
- path.AppendPoint(
- CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f),
- FXPT_TYPE::LineTo, false);
-
- CFX_GraphStateData gsd;
- gsd.SetDashCount(2);
- gsd.m_DashArray[0] = 3.0f;
- gsd.m_DashArray[1] = 3.0f;
- gsd.m_DashPhase = 0;
-
- gsd.m_LineWidth = fWidth;
- pDevice->DrawPath(&path, pUser2Device, &gsd, 0,
- color.ToFXColor(nTransparency), FXFILL_WINDING);
- break;
- }
- case BorderStyle::BEVELED:
- case BorderStyle::INSET: {
- CFX_GraphStateData gsd;
- gsd.m_LineWidth = fHalfWidth;
-
- CFX_PathData pathLT;
-
- pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth),
- FXPT_TYPE::MoveTo, false);
- pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fTop - fHalfWidth),
- FXPT_TYPE::LineTo, false);
- pathLT.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth),
- FXPT_TYPE::LineTo, false);
- pathLT.AppendPoint(
- CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2),
- FXPT_TYPE::LineTo, false);
- pathLT.AppendPoint(
- CFX_PointF(fLeft + fHalfWidth * 2, fTop - fHalfWidth * 2),
- FXPT_TYPE::LineTo, false);
- pathLT.AppendPoint(
- CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2),
- FXPT_TYPE::LineTo, false);
- pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth),
- FXPT_TYPE::LineTo, false);
-
- pDevice->DrawPath(&pathLT, pUser2Device, &gsd,
- crLeftTop.ToFXColor(nTransparency), 0,
- FXFILL_ALTERNATE);
-
- CFX_PathData pathRB;
- pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth),
- FXPT_TYPE::MoveTo, false);
- pathRB.AppendPoint(
- CFX_PointF(fRight - fHalfWidth, fBottom + fHalfWidth),
- FXPT_TYPE::LineTo, false);
- pathRB.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth),
- FXPT_TYPE::LineTo, false);
- pathRB.AppendPoint(
- CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2),
- FXPT_TYPE::LineTo, false);
- pathRB.AppendPoint(
- CFX_PointF(fRight - fHalfWidth * 2, fBottom + fHalfWidth * 2),
- FXPT_TYPE::LineTo, false);
- pathRB.AppendPoint(
- CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2),
- FXPT_TYPE::LineTo, false);
- pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth),
- FXPT_TYPE::LineTo, false);
-
- pDevice->DrawPath(&pathRB, pUser2Device, &gsd,
- crRightBottom.ToFXColor(nTransparency), 0,
- FXFILL_ALTERNATE);
-
- CFX_PathData path;
-
- path.AppendRect(fLeft, fBottom, fRight, fTop);
- path.AppendRect(fLeft + fHalfWidth, fBottom + fHalfWidth,
- fRight - fHalfWidth, fTop - fHalfWidth);
-
- pDevice->DrawPath(&path, pUser2Device, &gsd,
- color.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE);
- break;
- }
- case BorderStyle::UNDERLINE: {
- CFX_PathData path;
- path.AppendPoint(CFX_PointF(fLeft, fBottom + fWidth / 2),
- FXPT_TYPE::MoveTo, false);
- path.AppendPoint(CFX_PointF(fRight, fBottom + fWidth / 2),
- FXPT_TYPE::LineTo, false);
-
- CFX_GraphStateData gsd;
- gsd.m_LineWidth = fWidth;
-
- pDevice->DrawPath(&path, pUser2Device, &gsd, 0,
- color.ToFXColor(nTransparency), FXFILL_ALTERNATE);
- break;
- }
- }
- }
-}
-
diff --git a/fpdfsdk/pdfwindow/PWL_Utils.h b/fpdfsdk/pdfwindow/PWL_Utils.h
deleted file mode 100644
index a4ecc19..0000000
--- a/fpdfsdk/pdfwindow/PWL_Utils.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2014 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_PWL_UTILS_H_
-#define FPDFSDK_PDFWINDOW_PWL_UTILS_H_
-
-#include "core/fpdfdoc/cpvt_wordrange.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-
-class CFX_Edit;
-struct CPWL_Color;
-
-#define PWL_MAKEDWORD(low, high) \
- ((uint32_t)((uint16_t)(low) | (uint32_t)(((uint16_t)(high)) << 16)))
-
-// checkbox & radiobutton style
-#define PCS_CHECK 0
-#define PCS_CIRCLE 1
-#define PCS_CROSS 2
-#define PCS_DIAMOND 3
-#define PCS_SQUARE 4
-#define PCS_STAR 5
-
-// pushbutton layout style
-#define PPBL_LABEL 0
-#define PPBL_ICON 1
-#define PPBL_ICONTOPLABELBOTTOM 2
-#define PPBL_LABELTOPICONBOTTOM 3
-#define PPBL_ICONLEFTLABELRIGHT 4
-#define PPBL_LABELLEFTICONRIGHT 5
-#define PPBL_LABELOVERICON 6
-
-class CPWL_Utils {
- public:
- static CFX_FloatRect InflateRect(const CFX_FloatRect& rcRect, FX_FLOAT fSize);
- static CFX_FloatRect DeflateRect(const CFX_FloatRect& rcRect, FX_FLOAT fSize);
-
- static CPVT_WordRange OverlapWordRange(const CPVT_WordRange& wr1,
- const CPVT_WordRange& wr2);
- static CFX_FloatRect GetCenterSquare(const CFX_FloatRect& rect);
-
- static CFX_FloatRect OffsetRect(const CFX_FloatRect& rect,
- FX_FLOAT x,
- FX_FLOAT y);
-
- static CFX_ByteString GetColorAppStream(const CPWL_Color& color,
- const bool& bFillOrStroke = true);
- static CFX_ByteString GetBorderAppStream(const CFX_FloatRect& rect,
- FX_FLOAT fWidth,
- const CPWL_Color& color,
- const CPWL_Color& crLeftTop,
- const CPWL_Color& crRightBottom,
- BorderStyle nStyle,
- const CPWL_Dash& dash);
- static CFX_ByteString GetCircleBorderAppStream(
- const CFX_FloatRect& rect,
- FX_FLOAT fWidth,
- const CPWL_Color& color,
- const CPWL_Color& crLeftTop,
- const CPWL_Color& crRightBottom,
- BorderStyle nStyle,
- const CPWL_Dash& dash);
- static CFX_ByteString GetRectFillAppStream(const CFX_FloatRect& rect,
- const CPWL_Color& color);
- static CFX_ByteString GetCircleFillAppStream(const CFX_FloatRect& rect,
- const CPWL_Color& color);
- static CFX_ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox,
- IPVT_FontMap* pFontMap,
- CPDF_Stream* pIconStream,
- CPDF_IconFit& IconFit,
- const CFX_WideString& sLabel,
- const CPWL_Color& crText,
- FX_FLOAT fFontSize,
- int32_t nLayOut);
- static CFX_ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox,
- int32_t nStyle,
- const CPWL_Color& crText);
- static CFX_ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox,
- int32_t nStyle,
- const CPWL_Color& crText);
- static CFX_ByteString GetEditAppStream(CFX_Edit* pEdit,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange = nullptr,
- bool bContinuous = true,
- uint16_t SubWord = 0);
- static CFX_ByteString GetEditSelAppStream(
- CFX_Edit* pEdit,
- const CFX_PointF& ptOffset,
- const CPVT_WordRange* pRange = nullptr);
- static CFX_ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox);
-
- static void DrawFillRect(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_FloatRect& rect,
- const CPWL_Color& color,
- int32_t nTransparency);
- static void DrawFillRect(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_FloatRect& rect,
- const FX_COLORREF& color);
- static void DrawStrokeRect(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_FloatRect& rect,
- const FX_COLORREF& color,
- FX_FLOAT fWidth);
- static void DrawStrokeLine(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_PointF& ptMoveTo,
- const CFX_PointF& ptLineTo,
- const FX_COLORREF& color,
- FX_FLOAT fWidth);
- static void DrawBorder(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_FloatRect& rect,
- FX_FLOAT fWidth,
- const CPWL_Color& color,
- const CPWL_Color& crLeftTop,
- const CPWL_Color& crRightBottom,
- BorderStyle nStyle,
- int32_t nTransparency);
- static void DrawFillArea(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- const CFX_PointF* pPts,
- int32_t nCount,
- const FX_COLORREF& color);
- static void DrawShadow(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device,
- bool bVertical,
- bool bHorizontal,
- CFX_FloatRect rect,
- int32_t nTransparency,
- int32_t nStartGray,
- int32_t nEndGray);
-
- private:
- static CFX_FloatRect ScaleRect(const CFX_FloatRect& rcRect, FX_FLOAT fScale);
-
- static CFX_ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText);
- static CFX_ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText);
- static CFX_ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText);
- static CFX_ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText);
- static CFX_ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox,
- const CPWL_Color& crText);
- static CFX_ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox,
- const CPWL_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,
- FX_FLOAT fRotate);
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_UTILS_H_
diff --git a/fpdfsdk/pdfwindow/PWL_Wnd.cpp b/fpdfsdk/pdfwindow/PWL_Wnd.cpp
deleted file mode 100644
index 14024dd..0000000
--- a/fpdfsdk/pdfwindow/PWL_Wnd.cpp
+++ /dev/null
@@ -1,915 +0,0 @@
-// Copyright 2014 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 <map>
-#include <vector>
-
-#include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
-
-static std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
- // Leak the object at shutdown.
- static auto timeMap = new std::map<int32_t, CPWL_Timer*>;
- return *timeMap;
-}
-
-PWL_CREATEPARAM::PWL_CREATEPARAM()
- : rcRectWnd(0, 0, 0, 0),
- pSystemHandler(nullptr),
- pFontMap(nullptr),
- pProvider(nullptr),
- pFocusHandler(nullptr),
- dwFlags(0),
- sBackgroundColor(),
- pAttachedWidget(nullptr),
- nBorderStyle(BorderStyle::SOLID),
- dwBorderWidth(1),
- sBorderColor(),
- sTextColor(),
- nTransparency(255),
- fFontSize(PWL_DEFAULT_FONTSIZE),
- sDash(3, 0, 0),
- pAttachedData(nullptr),
- pParentWnd(nullptr),
- pMsgControl(nullptr),
- eCursorType(FXCT_ARROW),
- mtChild(1, 0, 0, 1, 0, 0) {}
-
-PWL_CREATEPARAM::PWL_CREATEPARAM(const PWL_CREATEPARAM& other) = default;
-
-CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached,
- CFX_SystemHandler* pSystemHandler)
- : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) {
- ASSERT(m_pAttached);
- ASSERT(m_pSystemHandler);
-}
-
-CPWL_Timer::~CPWL_Timer() {
- KillPWLTimer();
-}
-
-int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) {
- if (m_nTimerID != 0)
- KillPWLTimer();
- m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);
-
- GetPWLTimeMap()[m_nTimerID] = this;
- return m_nTimerID;
-}
-
-void CPWL_Timer::KillPWLTimer() {
- if (m_nTimerID == 0)
- return;
-
- m_pSystemHandler->KillTimer(m_nTimerID);
- GetPWLTimeMap().erase(m_nTimerID);
- m_nTimerID = 0;
-}
-
-void CPWL_Timer::TimerProc(int32_t idEvent) {
- auto it = GetPWLTimeMap().find(idEvent);
- if (it == GetPWLTimeMap().end())
- return;
-
- CPWL_Timer* pTimer = it->second;
- if (pTimer->m_pAttached)
- pTimer->m_pAttached->TimerProc();
-}
-
-CPWL_TimerHandler::CPWL_TimerHandler() {}
-
-CPWL_TimerHandler::~CPWL_TimerHandler() {}
-
-void CPWL_TimerHandler::BeginTimer(int32_t nElapse) {
- if (!m_pTimer)
- m_pTimer = pdfium::MakeUnique<CPWL_Timer>(this, GetSystemHandler());
-
- m_pTimer->SetPWLTimer(nElapse);
-}
-
-void CPWL_TimerHandler::EndTimer() {
- if (m_pTimer)
- m_pTimer->KillPWLTimer();
-}
-
-void CPWL_TimerHandler::TimerProc() {}
-
-class CPWL_MsgControl {
- friend class CPWL_Wnd;
-
- public:
- explicit CPWL_MsgControl(CPWL_Wnd* pWnd) {
- m_pCreatedWnd = pWnd;
- Default();
- }
-
- ~CPWL_MsgControl() { Default(); }
-
- void Default() {
- m_aMousePath.clear();
- m_aKeyboardPath.clear();
- m_pMainMouseWnd = nullptr;
- m_pMainKeyboardWnd = nullptr;
- }
-
- bool IsWndCreated(const CPWL_Wnd* pWnd) const {
- return m_pCreatedWnd == pWnd;
- }
-
- bool IsMainCaptureMouse(const CPWL_Wnd* pWnd) const {
- return pWnd == m_pMainMouseWnd;
- }
-
- bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
- return pWnd && pdfium::ContainsValue(m_aMousePath, pWnd);
- }
-
- bool IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
- return pWnd == m_pMainKeyboardWnd;
- }
-
- bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
- return pWnd && pdfium::ContainsValue(m_aKeyboardPath, pWnd);
- }
-
- void SetFocus(CPWL_Wnd* pWnd) {
- m_aKeyboardPath.clear();
- if (pWnd) {
- m_pMainKeyboardWnd = pWnd;
- CPWL_Wnd* pParent = pWnd;
- while (pParent) {
- m_aKeyboardPath.push_back(pParent);
- pParent = pParent->GetParentWindow();
- }
- pWnd->OnSetFocus();
- }
- }
-
- void KillFocus() {
- if (!m_aKeyboardPath.empty())
- if (CPWL_Wnd* pWnd = m_aKeyboardPath[0])
- pWnd->OnKillFocus();
-
- m_pMainKeyboardWnd = nullptr;
- m_aKeyboardPath.clear();
- }
-
- void SetCapture(CPWL_Wnd* pWnd) {
- m_aMousePath.clear();
- if (pWnd) {
- m_pMainMouseWnd = pWnd;
- CPWL_Wnd* pParent = pWnd;
- while (pParent) {
- m_aMousePath.push_back(pParent);
- pParent = pParent->GetParentWindow();
- }
- }
- }
-
- void ReleaseCapture() {
- m_pMainMouseWnd = nullptr;
- m_aMousePath.clear();
- }
-
- private:
- std::vector<CPWL_Wnd*> m_aMousePath;
- std::vector<CPWL_Wnd*> m_aKeyboardPath;
- CPWL_Wnd* m_pCreatedWnd;
- CPWL_Wnd* m_pMainMouseWnd;
- CPWL_Wnd* m_pMainKeyboardWnd;
-};
-
-CPWL_Wnd::CPWL_Wnd()
- : m_pVScrollBar(nullptr),
- m_rcWindow(),
- m_rcClip(),
- m_bCreated(false),
- m_bVisible(false),
- m_bNotifying(false),
- m_bEnabled(true) {}
-
-CPWL_Wnd::~CPWL_Wnd() {
- ASSERT(m_bCreated == false);
-}
-
-CFX_ByteString CPWL_Wnd::GetClassName() const {
- return "CPWL_Wnd";
-}
-
-void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) {
- if (!IsValid()) {
- m_sPrivateParam = cp;
-
- OnCreate(m_sPrivateParam);
-
- m_sPrivateParam.rcRectWnd.Normalize();
- m_rcWindow = m_sPrivateParam.rcRectWnd;
- m_rcClip = CPWL_Utils::InflateRect(m_rcWindow, 1.0f);
-
- CreateMsgControl();
-
- if (m_sPrivateParam.pParentWnd)
- m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD);
-
- PWL_CREATEPARAM ccp = m_sPrivateParam;
-
- ccp.dwFlags &= 0xFFFF0000L; // remove sub styles
- ccp.mtChild = CFX_Matrix(1, 0, 0, 1, 0, 0);
-
- CreateScrollBar(ccp);
- CreateChildWnd(ccp);
-
- m_bVisible = HasFlag(PWS_VISIBLE);
-
- OnCreated();
-
- RePosChildWnd();
- m_bCreated = true;
- }
-}
-
-void CPWL_Wnd::OnCreate(PWL_CREATEPARAM& cp) {}
-
-void CPWL_Wnd::OnCreated() {}
-
-void CPWL_Wnd::OnDestroy() {}
-
-void CPWL_Wnd::InvalidateFocusHandler(IPWL_FocusHandler* handler) {
- if (m_sPrivateParam.pFocusHandler == handler)
- m_sPrivateParam.pFocusHandler = nullptr;
-}
-
-void CPWL_Wnd::InvalidateProvider(IPWL_Provider* provider) {
- if (m_sPrivateParam.pProvider.Get() == provider)
- m_sPrivateParam.pProvider.Reset();
-}
-
-void CPWL_Wnd::Destroy() {
- KillFocus();
- OnDestroy();
- if (m_bCreated) {
- for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) {
- if (CPWL_Wnd* pChild = *it) {
- *it = nullptr;
- pChild->Destroy();
- delete pChild;
- }
- }
- if (m_sPrivateParam.pParentWnd)
- m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD);
-
- m_bCreated = false;
- }
- DestroyMsgControl();
- m_sPrivateParam.Reset();
- m_Children.clear();
- m_pVScrollBar = nullptr;
-}
-
-void CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) {
- if (IsValid()) {
- CFX_FloatRect rcOld = GetWindowRect();
-
- m_rcWindow = rcNew;
- m_rcWindow.Normalize();
-
- if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
- rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
- if (bReset) {
- RePosChildWnd();
- }
- }
- if (bRefresh) {
- InvalidateRectMove(rcOld, rcNew);
- }
-
- m_sPrivateParam.rcRectWnd = m_rcWindow;
- }
-}
-
-void CPWL_Wnd::InvalidateRectMove(const CFX_FloatRect& rcOld,
- const CFX_FloatRect& rcNew) {
- CFX_FloatRect rcUnion = rcOld;
- rcUnion.Union(rcNew);
-
- InvalidateRect(&rcUnion);
-}
-
-void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- if (IsValid() && IsVisible()) {
- GetThisAppearanceStream(sAppStream);
- GetChildAppearanceStream(sAppStream);
- }
-}
-
-// if don't set,Get default apperance stream
-void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- CFX_FloatRect rectWnd = GetWindowRect();
- if (!rectWnd.IsEmpty()) {
- CFX_ByteTextBuf sThis;
-
- if (HasFlag(PWS_BACKGROUND))
- sThis << CPWL_Utils::GetRectFillAppStream(rectWnd, GetBackgroundColor());
-
- if (HasFlag(PWS_BORDER)) {
- sThis << CPWL_Utils::GetBorderAppStream(
- rectWnd, (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
- GetBorderLeftTopColor(GetBorderStyle()),
- GetBorderRightBottomColor(GetBorderStyle()), GetBorderStyle(),
- GetBorderDash());
- }
-
- sAppStream << sThis;
- }
-}
-
-void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream) {
- for (CPWL_Wnd* pChild : m_Children) {
- if (pChild)
- pChild->GetAppearanceStream(sAppStream);
- }
-}
-
-void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- if (IsValid() && IsVisible()) {
- DrawThisAppearance(pDevice, pUser2Device);
- DrawChildAppearance(pDevice, pUser2Device);
- }
-}
-
-void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- CFX_FloatRect rectWnd = GetWindowRect();
- if (!rectWnd.IsEmpty()) {
- if (HasFlag(PWS_BACKGROUND)) {
- CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(
- rectWnd, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
- CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient,
- GetBackgroundColor(), GetTransparency());
- }
-
- if (HasFlag(PWS_BORDER))
- CPWL_Utils::DrawBorder(pDevice, pUser2Device, rectWnd,
- (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
- GetBorderLeftTopColor(GetBorderStyle()),
- GetBorderRightBottomColor(GetBorderStyle()),
- GetBorderStyle(), GetTransparency());
- }
-}
-
-void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) {
- for (CPWL_Wnd* pChild : m_Children) {
- if (!pChild)
- continue;
-
- CFX_Matrix mt = pChild->GetChildMatrix();
- if (mt.IsIdentity()) {
- pChild->DrawAppearance(pDevice, pUser2Device);
- } else {
- mt.Concat(*pUser2Device);
- pChild->DrawAppearance(pDevice, &mt);
- }
- }
-}
-
-void CPWL_Wnd::InvalidateRect(CFX_FloatRect* pRect) {
- if (IsValid()) {
- CFX_FloatRect rcRefresh = pRect ? *pRect : GetWindowRect();
-
- if (!HasFlag(PWS_NOREFRESHCLIP)) {
- CFX_FloatRect rcClip = GetClipRect();
- if (!rcClip.IsEmpty()) {
- rcRefresh.Intersect(rcClip);
- }
- }
-
- FX_RECT rcWin = PWLtoWnd(rcRefresh);
- rcWin.left -= PWL_INVALIDATE_INFLATE;
- rcWin.top -= PWL_INVALIDATE_INFLATE;
- rcWin.right += PWL_INVALIDATE_INFLATE;
- rcWin.bottom += PWL_INVALIDATE_INFLATE;
-
- if (CFX_SystemHandler* pSH = GetSystemHandler()) {
- if (CPDFSDK_Widget* widget = static_cast<CPDFSDK_Widget*>(
- m_sPrivateParam.pAttachedWidget.Get())) {
- pSH->InvalidateRect(widget, rcWin);
- }
- }
- }
-}
-
-#define PWL_IMPLEMENT_KEY_METHOD(key_method_name) \
- bool CPWL_Wnd::key_method_name(uint16_t nChar, uint32_t nFlag) { \
- if (!IsValid() || !IsVisible() || !IsEnabled()) \
- return false; \
- if (!IsWndCaptureKeyboard(this)) \
- return false; \
- for (const auto& pChild : m_Children) { \
- if (pChild && IsWndCaptureKeyboard(pChild)) \
- return pChild->key_method_name(nChar, nFlag); \
- } \
- return false; \
- }
-
-PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
-PWL_IMPLEMENT_KEY_METHOD(OnChar)
-#undef PWL_IMPLEMENT_KEY_METHOD
-
-#define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name) \
- bool CPWL_Wnd::mouse_method_name(const CFX_PointF& point, uint32_t nFlag) { \
- if (!IsValid() || !IsVisible() || !IsEnabled()) \
- return false; \
- if (IsWndCaptureMouse(this)) { \
- for (const auto& pChild : m_Children) { \
- if (pChild && IsWndCaptureMouse(pChild)) { \
- return pChild->mouse_method_name(pChild->ParentToChild(point), \
- nFlag); \
- } \
- } \
- SetCursor(); \
- return false; \
- } \
- for (const auto& pChild : m_Children) { \
- if (pChild && pChild->WndHitTest(pChild->ParentToChild(point))) { \
- return pChild->mouse_method_name(pChild->ParentToChild(point), nFlag); \
- } \
- } \
- if (WndHitTest(point)) \
- SetCursor(); \
- return false; \
- }
-
-PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
-PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
-PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
-PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
-PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
-PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)
-#undef PWL_IMPLEMENT_MOUSE_METHOD
-
-bool CPWL_Wnd::OnMouseWheel(short zDelta,
- const CFX_PointF& point,
- uint32_t nFlag) {
- if (!IsValid() || !IsVisible() || !IsEnabled())
- return false;
-
- SetCursor();
- if (!IsWndCaptureKeyboard(this))
- return false;
-
- for (const auto& pChild : m_Children) {
- if (pChild && IsWndCaptureKeyboard(pChild))
- return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point), nFlag);
- }
- return false;
-}
-
-void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) {
- m_Children.push_back(pWnd);
-}
-
-void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
- for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) {
- if (*it && *it == pWnd) {
- m_Children.erase(std::next(it).base());
- break;
- }
- }
-}
-
-void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam,
- intptr_t lParam) {
- switch (msg) {
- case PNM_ADDCHILD:
- AddChild(pWnd);
- break;
- case PNM_REMOVECHILD:
- RemoveChild(pWnd);
- break;
- default:
- break;
- }
-}
-
-bool CPWL_Wnd::IsValid() const {
- return m_bCreated;
-}
-
-const PWL_CREATEPARAM& CPWL_Wnd::GetCreationParam() const {
- return m_sPrivateParam;
-}
-
-CPWL_Wnd* CPWL_Wnd::GetParentWindow() const {
- return m_sPrivateParam.pParentWnd;
-}
-
-CFX_FloatRect CPWL_Wnd::GetWindowRect() const {
- return m_rcWindow;
-}
-
-CFX_FloatRect CPWL_Wnd::GetClientRect() const {
- CFX_FloatRect rcWindow = GetWindowRect();
- CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(
- rcWindow, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
- if (CPWL_ScrollBar* pVSB = GetVScrollBar())
- rcClient.right -= pVSB->GetScrollBarWidth();
-
- rcClient.Normalize();
- return rcWindow.Contains(rcClient) ? rcClient : CFX_FloatRect();
-}
-
-CFX_PointF CPWL_Wnd::GetCenterPoint() const {
- CFX_FloatRect rcClient = GetClientRect();
- return CFX_PointF((rcClient.left + rcClient.right) * 0.5f,
- (rcClient.top + rcClient.bottom) * 0.5f);
-}
-
-bool CPWL_Wnd::HasFlag(uint32_t dwFlags) const {
- return (m_sPrivateParam.dwFlags & dwFlags) != 0;
-}
-
-void CPWL_Wnd::RemoveFlag(uint32_t dwFlags) {
- m_sPrivateParam.dwFlags &= ~dwFlags;
-}
-
-void CPWL_Wnd::AddFlag(uint32_t dwFlags) {
- m_sPrivateParam.dwFlags |= dwFlags;
-}
-
-CPWL_Color CPWL_Wnd::GetBackgroundColor() const {
- return m_sPrivateParam.sBackgroundColor;
-}
-
-void CPWL_Wnd::SetBackgroundColor(const CPWL_Color& color) {
- m_sPrivateParam.sBackgroundColor = color;
-}
-
-CPWL_Color CPWL_Wnd::GetTextColor() const {
- return m_sPrivateParam.sTextColor;
-}
-
-BorderStyle CPWL_Wnd::GetBorderStyle() const {
- return m_sPrivateParam.nBorderStyle;
-}
-
-void CPWL_Wnd::SetBorderStyle(BorderStyle nBorderStyle) {
- if (HasFlag(PWS_BORDER))
- m_sPrivateParam.nBorderStyle = nBorderStyle;
-}
-
-int32_t CPWL_Wnd::GetBorderWidth() const {
- if (HasFlag(PWS_BORDER))
- return m_sPrivateParam.dwBorderWidth;
-
- return 0;
-}
-
-int32_t CPWL_Wnd::GetInnerBorderWidth() const {
- return 0;
-}
-
-CPWL_Color CPWL_Wnd::GetBorderColor() const {
- if (HasFlag(PWS_BORDER))
- return m_sPrivateParam.sBorderColor;
-
- return CPWL_Color();
-}
-
-const CPWL_Dash& CPWL_Wnd::GetBorderDash() const {
- return m_sPrivateParam.sDash;
-}
-
-void* CPWL_Wnd::GetAttachedData() const {
- return m_sPrivateParam.pAttachedData;
-}
-
-CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
- if (HasFlag(PWS_VSCROLL))
- return m_pVScrollBar;
-
- return nullptr;
-}
-
-void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM& cp) {
- CreateVScrollBar(cp);
-}
-
-void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM& cp) {
- if (!m_pVScrollBar && HasFlag(PWS_VSCROLL)) {
- PWL_CREATEPARAM scp = cp;
-
- // flags
- scp.dwFlags =
- PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;
-
- scp.pParentWnd = this;
- scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
- scp.eCursorType = FXCT_ARROW;
- scp.nTransparency = PWL_SCROLLBAR_TRANSPARENCY;
-
- m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL);
- m_pVScrollBar->Create(scp);
- }
-}
-
-void CPWL_Wnd::SetCapture() {
- if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
- pMsgCtrl->SetCapture(this);
-}
-
-void CPWL_Wnd::ReleaseCapture() {
- for (const auto& pChild : m_Children) {
- if (pChild)
- pChild->ReleaseCapture();
- }
- if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
- pMsgCtrl->ReleaseCapture();
-}
-
-void CPWL_Wnd::SetFocus() {
- if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
- if (!pMsgCtrl->IsMainCaptureKeyboard(this))
- pMsgCtrl->KillFocus();
- pMsgCtrl->SetFocus(this);
- }
-}
-
-void CPWL_Wnd::KillFocus() {
- if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
- if (pMsgCtrl->IsWndCaptureKeyboard(this))
- pMsgCtrl->KillFocus();
- }
-}
-
-void CPWL_Wnd::OnSetFocus() {}
-
-void CPWL_Wnd::OnKillFocus() {}
-
-bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const {
- return IsValid() && IsVisible() && GetWindowRect().Contains(point);
-}
-
-bool CPWL_Wnd::ClientHitTest(const CFX_PointF& point) const {
- return IsValid() && IsVisible() && GetClientRect().Contains(point);
-}
-
-const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const {
- if (m_sPrivateParam.pParentWnd)
- return m_sPrivateParam.pParentWnd->GetRootWnd();
-
- return this;
-}
-
-void CPWL_Wnd::SetVisible(bool bVisible) {
- if (!IsValid())
- return;
-
- for (const auto& pChild : m_Children) {
- if (pChild)
- pChild->SetVisible(bVisible);
- }
- if (bVisible != m_bVisible) {
- m_bVisible = bVisible;
- RePosChildWnd();
- InvalidateRect();
- }
-}
-
-void CPWL_Wnd::SetClipRect(const CFX_FloatRect& rect) {
- m_rcClip = rect;
- m_rcClip.Normalize();
-}
-
-const CFX_FloatRect& CPWL_Wnd::GetClipRect() const {
- return m_rcClip;
-}
-
-bool CPWL_Wnd::IsReadOnly() const {
- return HasFlag(PWS_READONLY);
-}
-
-void CPWL_Wnd::RePosChildWnd() {
- CFX_FloatRect rcContent = CPWL_Utils::DeflateRect(
- GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
-
- CPWL_ScrollBar* pVSB = GetVScrollBar();
-
- CFX_FloatRect rcVScroll =
- CFX_FloatRect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom,
- rcContent.right - 1.0f, rcContent.top);
-
- if (pVSB)
- pVSB->Move(rcVScroll, true, false);
-}
-
-void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM& cp) {}
-
-void CPWL_Wnd::SetCursor() {
- if (IsValid()) {
- if (CFX_SystemHandler* pSH = GetSystemHandler()) {
- int32_t nCursorType = GetCreationParam().eCursorType;
- pSH->SetCursor(nCursorType);
- }
- }
-}
-
-void CPWL_Wnd::CreateMsgControl() {
- if (!m_sPrivateParam.pMsgControl)
- m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
-}
-
-void CPWL_Wnd::DestroyMsgControl() {
- if (CPWL_MsgControl* pMsgControl = GetMsgControl())
- if (pMsgControl->IsWndCreated(this))
- delete pMsgControl;
-}
-
-CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
- return m_sPrivateParam.pMsgControl;
-}
-
-bool CPWL_Wnd::IsCaptureMouse() const {
- return IsWndCaptureMouse(this);
-}
-
-bool CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
- if (CPWL_MsgControl* pCtrl = GetMsgControl())
- return pCtrl->IsWndCaptureMouse(pWnd);
-
- return false;
-}
-
-bool CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
- if (CPWL_MsgControl* pCtrl = GetMsgControl())
- return pCtrl->IsWndCaptureKeyboard(pWnd);
-
- return false;
-}
-
-bool CPWL_Wnd::IsFocused() const {
- if (CPWL_MsgControl* pCtrl = GetMsgControl())
- return pCtrl->IsMainCaptureKeyboard(this);
-
- return false;
-}
-
-CFX_FloatRect CPWL_Wnd::GetFocusRect() const {
- return CPWL_Utils::InflateRect(GetWindowRect(), 1);
-}
-
-FX_FLOAT CPWL_Wnd::GetFontSize() const {
- return m_sPrivateParam.fFontSize;
-}
-
-void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize) {
- m_sPrivateParam.fFontSize = fFontSize;
-}
-
-CFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
- return m_sPrivateParam.pSystemHandler;
-}
-
-IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const {
- return m_sPrivateParam.pFocusHandler;
-}
-
-IPWL_Provider* CPWL_Wnd::GetProvider() const {
- return m_sPrivateParam.pProvider.Get();
-}
-
-IPVT_FontMap* CPWL_Wnd::GetFontMap() const {
- return m_sPrivateParam.pFontMap;
-}
-
-CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const {
- switch (nBorderStyle) {
- case BorderStyle::BEVELED:
- return CPWL_Color(COLORTYPE_GRAY, 1);
- case BorderStyle::INSET:
- return CPWL_Color(COLORTYPE_GRAY, 0.5f);
- default:
- return CPWL_Color();
- }
-}
-
-CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(BorderStyle nBorderStyle) const {
- switch (nBorderStyle) {
- case BorderStyle::BEVELED:
- return GetBackgroundColor() / 2.0f;
- case BorderStyle::INSET:
- return CPWL_Color(COLORTYPE_GRAY, 0.75f);
- default:
- return CPWL_Color();
- }
-}
-
-int32_t CPWL_Wnd::GetTransparency() {
- return m_sPrivateParam.nTransparency;
-}
-
-void CPWL_Wnd::SetTransparency(int32_t nTransparency) {
- for (const auto& pChild : m_Children) {
- if (pChild)
- pChild->SetTransparency(nTransparency);
- }
- m_sPrivateParam.nTransparency = nTransparency;
-}
-
-CFX_Matrix CPWL_Wnd::GetWindowMatrix() const {
- CFX_Matrix mt = GetChildToRoot();
- if (IPWL_Provider* pProvider = GetProvider())
- mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
- return mt;
-}
-
-FX_RECT CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const {
- CFX_FloatRect rcTemp = rect;
- CFX_Matrix mt = GetWindowMatrix();
- mt.TransformRect(rcTemp);
- return FX_RECT((int32_t)(rcTemp.left + 0.5), (int32_t)(rcTemp.bottom + 0.5),
- (int32_t)(rcTemp.right + 0.5), (int32_t)(rcTemp.top + 0.5));
-}
-
-CFX_PointF CPWL_Wnd::ParentToChild(const CFX_PointF& point) const {
- CFX_Matrix mt = GetChildMatrix();
- if (mt.IsIdentity())
- return point;
-
- mt.SetReverse(mt);
- return mt.Transform(point);
-}
-
-CFX_FloatRect CPWL_Wnd::ParentToChild(const CFX_FloatRect& rect) const {
- CFX_Matrix mt = GetChildMatrix();
- if (mt.IsIdentity())
- return rect;
-
- mt.SetReverse(mt);
- CFX_FloatRect rc = rect;
- mt.TransformRect(rc);
- return rc;
-}
-
-CFX_Matrix CPWL_Wnd::GetChildToRoot() const {
- CFX_Matrix mt(1, 0, 0, 1, 0, 0);
- if (HasFlag(PWS_CHILD)) {
- const CPWL_Wnd* pParent = this;
- while (pParent) {
- mt.Concat(pParent->GetChildMatrix());
- pParent = pParent->GetParentWindow();
- }
- }
- return mt;
-}
-
-CFX_Matrix CPWL_Wnd::GetChildMatrix() const {
- if (HasFlag(PWS_CHILD))
- return m_sPrivateParam.mtChild;
-
- return CFX_Matrix(1, 0, 0, 1, 0, 0);
-}
-
-void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) {
- m_sPrivateParam.mtChild = mt;
-}
-
-const CPWL_Wnd* CPWL_Wnd::GetFocused() const {
- CPWL_MsgControl* pMsgCtrl = GetMsgControl();
- return pMsgCtrl ? pMsgCtrl->m_pMainKeyboardWnd : nullptr;
-}
-
-void CPWL_Wnd::EnableWindow(bool bEnable) {
- if (m_bEnabled == bEnable)
- return;
-
- for (const auto& pChild : m_Children) {
- if (pChild)
- pChild->EnableWindow(bEnable);
- }
- m_bEnabled = bEnable;
-}
-
-bool CPWL_Wnd::IsCTRLpressed(uint32_t nFlag) const {
- CFX_SystemHandler* pSystemHandler = GetSystemHandler();
- return pSystemHandler && pSystemHandler->IsCTRLKeyDown(nFlag);
-}
-
-bool CPWL_Wnd::IsSHIFTpressed(uint32_t nFlag) const {
- CFX_SystemHandler* pSystemHandler = GetSystemHandler();
- return pSystemHandler && pSystemHandler->IsSHIFTKeyDown(nFlag);
-}
-
-bool CPWL_Wnd::IsALTpressed(uint32_t nFlag) const {
- CFX_SystemHandler* pSystemHandler = GetSystemHandler();
- return pSystemHandler && pSystemHandler->IsALTKeyDown(nFlag);
-}
diff --git a/fpdfsdk/pdfwindow/PWL_Wnd.h b/fpdfsdk/pdfwindow/PWL_Wnd.h
deleted file mode 100644
index 55836d4..0000000
--- a/fpdfsdk/pdfwindow/PWL_Wnd.h
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright 2014 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_PWL_WND_H_
-#define FPDFSDK_PDFWINDOW_PWL_WND_H_
-
-#include <memory>
-#include <vector>
-
-#include "core/fpdfdoc/cpdf_formcontrol.h"
-#include "core/fxcrt/cfx_observable.h"
-#include "core/fxcrt/fx_basic.h"
-#include "fpdfsdk/cfx_systemhandler.h"
-#include "fpdfsdk/cpdfsdk_widget.h"
-#include "fpdfsdk/pdfwindow/cpwl_color.h"
-
-class CPWL_MsgControl;
-class CPWL_ScrollBar;
-class CPWL_Timer;
-class CPWL_TimerHandler;
-class CPWL_Wnd;
-class CFX_SystemHandler;
-class IPVT_FontMap;
-class IPWL_Provider;
-
-// window styles
-#define PWS_CHILD 0x80000000L
-#define PWS_BORDER 0x40000000L
-#define PWS_BACKGROUND 0x20000000L
-#define PWS_HSCROLL 0x10000000L
-#define PWS_VSCROLL 0x08000000L
-#define PWS_VISIBLE 0x04000000L
-#define PWS_DISABLE 0x02000000L
-#define PWS_READONLY 0x01000000L
-#define PWS_AUTOFONTSIZE 0x00800000L
-#define PWS_AUTOTRANSPARENT 0x00400000L
-#define PWS_NOREFRESHCLIP 0x00200000L
-
-// edit and label styles
-#define PES_MULTILINE 0x0001L
-#define PES_PASSWORD 0x0002L
-#define PES_LEFT 0x0004L
-#define PES_RIGHT 0x0008L
-#define PES_MIDDLE 0x0010L
-#define PES_TOP 0x0020L
-#define PES_BOTTOM 0x0040L
-#define PES_CENTER 0x0080L
-#define PES_CHARARRAY 0x0100L
-#define PES_AUTOSCROLL 0x0200L
-#define PES_AUTORETURN 0x0400L
-#define PES_UNDO 0x0800L
-#define PES_RICH 0x1000L
-#define PES_SPELLCHECK 0x2000L
-#define PES_TEXTOVERFLOW 0x4000L
-#define PES_NOREAD 0x8000L
-
-// listbox styles
-#define PLBS_MULTIPLESEL 0x0001L
-#define PLBS_HOVERSEL 0x0008L
-
-// combobox styles
-#define PCBS_ALLOWCUSTOMTEXT 0x0001L
-
-// richedit styles
-#define PRES_MULTILINE 0x0001L
-#define PRES_AUTORETURN 0x0002L
-#define PRES_AUTOSCROLL 0x0004L
-#define PRES_UNDO 0x0100L
-#define PRES_MULTIPAGES 0x0200L
-#define PRES_TEXTOVERFLOW 0x0400L
-
-// notification messages
-#define PNM_ADDCHILD 0x00000000L
-#define PNM_REMOVECHILD 0x00000001L
-#define PNM_SETSCROLLINFO 0x00000002L
-#define PNM_SETSCROLLPOS 0x00000003L
-#define PNM_SCROLLWINDOW 0x00000004L
-#define PNM_LBUTTONDOWN 0x00000005L
-#define PNM_LBUTTONUP 0x00000006L
-#define PNM_MOUSEMOVE 0x00000007L
-#define PNM_NOTERESET 0x00000008L
-#define PNM_SETCARETINFO 0x00000009L
-#define PNM_SELCHANGED 0x0000000AL
-#define PNM_NOTEEDITCHANGED 0x0000000BL
-
-#define PWL_CLASSNAME_EDIT "CPWL_Edit"
-
-struct CPWL_Dash {
- CPWL_Dash() : nDash(0), nGap(0), nPhase(0) {}
- CPWL_Dash(int32_t dash, int32_t gap, int32_t phase)
- : nDash(dash), nGap(gap), nPhase(phase) {}
-
- void Reset() {
- nDash = 0;
- nGap = 0;
- nPhase = 0;
- }
-
- int32_t nDash;
- int32_t nGap;
- int32_t nPhase;
-};
-
-inline bool operator==(const CPWL_Color& c1, const CPWL_Color& c2) {
- return c1.nColorType == c2.nColorType && c1.fColor1 - c2.fColor1 < 0.0001 &&
- c1.fColor1 - c2.fColor1 > -0.0001 &&
- c1.fColor2 - c2.fColor2 < 0.0001 &&
- c1.fColor2 - c2.fColor2 > -0.0001 &&
- c1.fColor3 - c2.fColor3 < 0.0001 &&
- c1.fColor3 - c2.fColor3 > -0.0001 &&
- c1.fColor4 - c2.fColor4 < 0.0001 && c1.fColor4 - c2.fColor4 > -0.0001;
-}
-
-inline bool operator!=(const CPWL_Color& c1, const CPWL_Color& c2) {
- return !(c1 == c2);
-}
-
-#define PWL_SCROLLBAR_WIDTH 12.0f
-#define PWL_SCROLLBAR_BUTTON_WIDTH 9.0f
-#define PWL_SCROLLBAR_POSBUTTON_MINWIDTH 2.0f
-#define PWL_SCROLLBAR_TRANSPARENCY 150
-#define PWL_SCROLLBAR_BKCOLOR \
- CPWL_Color(COLORTYPE_RGB, 220.0f / 255.0f, 220.0f / 255.0f, 220.0f / 255.0f)
-#define PWL_DEFAULT_SELTEXTCOLOR CPWL_Color(COLORTYPE_RGB, 1, 1, 1)
-#define PWL_DEFAULT_SELBACKCOLOR \
- CPWL_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f, 113.0f / 255.0f)
-#define PWL_DEFAULT_BACKCOLOR PWL_DEFAULT_SELTEXTCOLOR
-#define PWL_DEFAULT_TEXTCOLOR CPWL_Color(COLORTYPE_RGB, 0, 0, 0)
-#define PWL_DEFAULT_FONTSIZE 9.0f
-#define PWL_DEFAULT_BLACKCOLOR CPWL_Color(COLORTYPE_GRAY, 0)
-#define PWL_DEFAULT_WHITECOLOR CPWL_Color(COLORTYPE_GRAY, 1)
-#define PWL_DEFAULT_HEAVYGRAYCOLOR CPWL_Color(COLORTYPE_GRAY, 0.50)
-#define PWL_DEFAULT_LIGHTGRAYCOLOR CPWL_Color(COLORTYPE_GRAY, 0.75)
-#define PWL_TRIANGLE_HALFLEN 2.0f
-#define PWL_CBBUTTON_TRIANGLE_HALFLEN 3.0f
-#define PWL_INVALIDATE_INFLATE 2
-
-class IPWL_Provider : public CFX_Observable<IPWL_Provider> {
- public:
- virtual ~IPWL_Provider() {}
-
- // get a matrix which map user space to CWnd client space
- virtual CFX_Matrix GetWindowMatrix(void* pAttachedData) = 0;
-
- /*
- 0 L"&Undo\tCtrl+Z"
- 1 L"&Redo\tCtrl+Shift+Z"
- 2 L"Cu&t\tCtrl+X"
- 3 L"&Copy\tCtrl+C"
- 4 L"&Paste\tCtrl+V"
- 5 L"&Delete"
- 6 L"&Select All\tCtrl+A"
- */
- virtual CFX_WideString LoadPopupMenuString(int32_t nIndex) = 0;
-};
-
-class IPWL_FocusHandler {
- public:
- virtual ~IPWL_FocusHandler() {}
- virtual void OnSetFocus(CPWL_Wnd* pWnd) = 0;
-};
-
-struct PWL_CREATEPARAM {
- public:
- PWL_CREATEPARAM();
- PWL_CREATEPARAM(const PWL_CREATEPARAM& other);
-
- void Reset() {
- rcRectWnd.Reset();
- pSystemHandler = nullptr;
- pFontMap = nullptr;
- pProvider.Reset();
- pFocusHandler = nullptr;
- dwFlags = 0;
- sBackgroundColor.Reset();
- pAttachedWidget.Reset();
- nBorderStyle = BorderStyle::SOLID;
- dwBorderWidth = 0;
- sBorderColor.Reset();
- sTextColor.Reset();
- nTransparency = 0;
- fFontSize = 0.0f;
- sDash.Reset();
- pAttachedData = nullptr;
- pParentWnd = nullptr;
- pMsgControl = nullptr;
- eCursorType = 0;
- mtChild.SetIdentity();
- }
-
- CFX_FloatRect rcRectWnd; // required
- CFX_SystemHandler* pSystemHandler; // required
- IPVT_FontMap* pFontMap; // required
- IPWL_Provider::ObservedPtr pProvider; // required
- IPWL_FocusHandler* pFocusHandler; // optional
- uint32_t dwFlags; // optional
- CPWL_Color sBackgroundColor; // optional
- CPDFSDK_Widget::ObservedPtr pAttachedWidget; // required
- BorderStyle nBorderStyle; // optional
- int32_t dwBorderWidth; // optional
- CPWL_Color sBorderColor; // optional
- CPWL_Color sTextColor; // optional
- int32_t nTransparency; // optional
- FX_FLOAT fFontSize; // optional
- CPWL_Dash sDash; // optional
- void* pAttachedData; // optional
- CPWL_Wnd* pParentWnd; // ignore
- CPWL_MsgControl* pMsgControl; // ignore
- int32_t eCursorType; // ignore
- CFX_Matrix mtChild; // ignore
-};
-
-class CPWL_Timer {
- public:
- CPWL_Timer(CPWL_TimerHandler* pAttached, CFX_SystemHandler* pSystemHandler);
- virtual ~CPWL_Timer();
-
- int32_t SetPWLTimer(int32_t nElapse);
- void KillPWLTimer();
- static void TimerProc(int32_t idEvent);
-
- private:
- int32_t m_nTimerID;
- CPWL_TimerHandler* m_pAttached;
- CFX_SystemHandler* m_pSystemHandler;
-};
-
-class CPWL_TimerHandler {
- public:
- CPWL_TimerHandler();
- virtual ~CPWL_TimerHandler();
-
- void BeginTimer(int32_t nElapse);
- void EndTimer();
- virtual void TimerProc();
- virtual CFX_SystemHandler* GetSystemHandler() const = 0;
-
- private:
- std::unique_ptr<CPWL_Timer> m_pTimer;
-};
-
-class CPWL_Wnd : public CPWL_TimerHandler {
- public:
- CPWL_Wnd();
- ~CPWL_Wnd() override;
-
- virtual CFX_ByteString GetClassName() const;
- virtual void InvalidateRect(CFX_FloatRect* pRect = nullptr);
-
- virtual bool OnKeyDown(uint16_t nChar, uint32_t nFlag);
- virtual bool OnChar(uint16_t nChar, uint32_t nFlag);
- virtual bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag);
- virtual bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag);
- virtual bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag);
- virtual bool OnRButtonDown(const CFX_PointF& point, uint32_t nFlag);
- virtual bool OnRButtonUp(const CFX_PointF& point, uint32_t nFlag);
- virtual bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag);
- virtual bool OnMouseWheel(short zDelta,
- const CFX_PointF& point,
- uint32_t nFlag);
- virtual void OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam = 0,
- intptr_t lParam = 0);
- virtual void SetFocus();
- virtual void KillFocus();
- virtual void SetCursor();
- virtual void SetVisible(bool bVisible);
- virtual void SetFontSize(FX_FLOAT fFontSize);
- virtual FX_FLOAT GetFontSize() const;
-
- virtual CFX_FloatRect GetFocusRect() const;
- virtual CFX_FloatRect GetClientRect() const;
-
- void InvalidateFocusHandler(IPWL_FocusHandler* handler);
- void InvalidateProvider(IPWL_Provider* provider);
- void Create(const PWL_CREATEPARAM& cp);
- void Destroy();
- void Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh);
-
- void SetCapture();
- void ReleaseCapture();
-
- void DrawAppearance(CFX_RenderDevice* pDevice, CFX_Matrix* pUser2Device);
-
- CPWL_Color GetBackgroundColor() const;
- void SetBackgroundColor(const CPWL_Color& color);
- CPWL_Color GetBorderColor() const;
- CPWL_Color GetTextColor() const;
- void SetTextColor(const CPWL_Color& color);
- CPWL_Color GetBorderLeftTopColor(BorderStyle nBorderStyle) const;
- CPWL_Color GetBorderRightBottomColor(BorderStyle nBorderStyle) const;
-
- void SetBorderStyle(BorderStyle eBorderStyle);
- BorderStyle GetBorderStyle() const;
- const CPWL_Dash& GetBorderDash() const;
-
- int32_t GetBorderWidth() const;
- int32_t GetInnerBorderWidth() const;
- CFX_FloatRect GetWindowRect() const;
- CFX_PointF GetCenterPoint() const;
-
- bool IsVisible() const { return m_bVisible; }
- bool HasFlag(uint32_t dwFlags) const;
- void AddFlag(uint32_t dwFlags);
- void RemoveFlag(uint32_t dwFlags);
-
- void SetClipRect(const CFX_FloatRect& rect);
- const CFX_FloatRect& GetClipRect() const;
-
- CPWL_Wnd* GetParentWindow() const;
- void* GetAttachedData() const;
-
- bool WndHitTest(const CFX_PointF& point) const;
- bool ClientHitTest(const CFX_PointF& point) const;
- bool IsCaptureMouse() const;
-
- void EnableWindow(bool bEnable);
- bool IsEnabled() const { return m_bEnabled; }
- const CPWL_Wnd* GetFocused() const;
- bool IsFocused() const;
- bool IsReadOnly() const;
- CPWL_ScrollBar* GetVScrollBar() const;
-
- IPVT_FontMap* GetFontMap() const;
- IPWL_Provider* GetProvider() const;
- IPWL_FocusHandler* GetFocusHandler() const;
-
- int32_t GetTransparency();
- void SetTransparency(int32_t nTransparency);
-
- CFX_Matrix GetChildToRoot() const;
- CFX_Matrix GetChildMatrix() const;
- void SetChildMatrix(const CFX_Matrix& mt);
- CFX_Matrix GetWindowMatrix() const;
-
- protected:
- friend class CPWL_MsgControl;
-
- // CPWL_TimerHandler
- CFX_SystemHandler* GetSystemHandler() const override;
-
- virtual void CreateChildWnd(const PWL_CREATEPARAM& cp);
- virtual void RePosChildWnd();
- virtual void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream);
-
- virtual void DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device);
-
- virtual void OnCreate(PWL_CREATEPARAM& cp);
- virtual void OnCreated();
- virtual void OnDestroy();
-
- virtual void OnSetFocus();
- virtual void OnKillFocus();
-
- void GetAppearanceStream(CFX_ByteTextBuf& sAppStream);
- void SetNotifyFlag(bool bNotifying = true) { m_bNotifying = bNotifying; }
-
- bool IsValid() const;
- const PWL_CREATEPARAM& GetCreationParam() const;
- bool IsNotifying() const { return m_bNotifying; }
-
- void InvalidateRectMove(const CFX_FloatRect& rcOld,
- const CFX_FloatRect& rcNew);
-
- bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const;
- bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const;
- const CPWL_Wnd* GetRootWnd() const;
-
- bool IsCTRLpressed(uint32_t nFlag) const;
- bool IsSHIFTpressed(uint32_t nFlag) const;
- bool IsALTpressed(uint32_t nFlag) const;
-
- private:
- CFX_PointF ParentToChild(const CFX_PointF& point) const;
- CFX_FloatRect ParentToChild(const CFX_FloatRect& rect) const;
-
- void GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream);
- void DrawChildAppearance(CFX_RenderDevice* pDevice, CFX_Matrix* pUser2Device);
-
- FX_RECT PWLtoWnd(const CFX_FloatRect& rect) const;
-
- void AddChild(CPWL_Wnd* pWnd);
- void RemoveChild(CPWL_Wnd* pWnd);
-
- void CreateScrollBar(const PWL_CREATEPARAM& cp);
- void CreateVScrollBar(const PWL_CREATEPARAM& cp);
-
- void AdjustStyle();
- void CreateMsgControl();
- void DestroyMsgControl();
-
- CPWL_MsgControl* GetMsgControl() const;
-
- std::vector<CPWL_Wnd*> m_Children;
- PWL_CREATEPARAM m_sPrivateParam;
- CPWL_ScrollBar* m_pVScrollBar;
- CFX_FloatRect m_rcWindow;
- CFX_FloatRect m_rcClip;
- bool m_bCreated;
- bool m_bVisible;
- bool m_bNotifying;
- bool m_bEnabled;
-};
-
-#endif // FPDFSDK_PDFWINDOW_PWL_WND_H_
diff --git a/fpdfsdk/pdfwindow/cpwl_color.cpp b/fpdfsdk/pdfwindow/cpwl_color.cpp
deleted file mode 100644
index 9c9ca3e..0000000
--- a/fpdfsdk/pdfwindow/cpwl_color.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-// 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_color.h"
-
-#include <algorithm>
-
-namespace {
-
-bool InRange(FX_FLOAT comp) {
- return comp >= 0.0f && comp <= 1.0f;
-}
-
-CPWL_Color ConvertCMYK2GRAY(FX_FLOAT dC,
- FX_FLOAT dM,
- FX_FLOAT dY,
- FX_FLOAT dK) {
- if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK))
- return CPWL_Color(COLORTYPE_GRAY);
- return CPWL_Color(
- COLORTYPE_GRAY,
- 1.0f - std::min(1.0f, 0.3f * dC + 0.59f * dM + 0.11f * dY + dK));
-}
-
-CPWL_Color ConvertGRAY2CMYK(FX_FLOAT dGray) {
- if (!InRange(dGray))
- return CPWL_Color(COLORTYPE_CMYK);
- return CPWL_Color(COLORTYPE_CMYK, 0.0f, 0.0f, 0.0f, 1.0f - dGray);
-}
-
-CPWL_Color ConvertGRAY2RGB(FX_FLOAT dGray) {
- if (!InRange(dGray))
- return CPWL_Color(COLORTYPE_RGB);
- return CPWL_Color(COLORTYPE_RGB, dGray, dGray, dGray);
-}
-
-CPWL_Color ConvertRGB2GRAY(FX_FLOAT dR, FX_FLOAT dG, FX_FLOAT dB) {
- if (!InRange(dR) || !InRange(dG) || !InRange(dB))
- return CPWL_Color(COLORTYPE_GRAY);
- return CPWL_Color(COLORTYPE_GRAY, 0.3f * dR + 0.59f * dG + 0.11f * dB);
-}
-
-CPWL_Color ConvertCMYK2RGB(FX_FLOAT dC, FX_FLOAT dM, FX_FLOAT dY, FX_FLOAT dK) {
- if (!InRange(dC) || !InRange(dM) || !InRange(dY) || !InRange(dK))
- return CPWL_Color(COLORTYPE_RGB);
- return CPWL_Color(COLORTYPE_RGB, 1.0f - std::min(1.0f, dC + dK),
- 1.0f - std::min(1.0f, dM + dK),
- 1.0f - std::min(1.0f, dY + dK));
-}
-
-CPWL_Color ConvertRGB2CMYK(FX_FLOAT dR, FX_FLOAT dG, FX_FLOAT dB) {
- if (!InRange(dR) || !InRange(dG) || !InRange(dB))
- return CPWL_Color(COLORTYPE_CMYK);
-
- FX_FLOAT c = 1.0f - dR;
- FX_FLOAT m = 1.0f - dG;
- FX_FLOAT y = 1.0f - dB;
- return CPWL_Color(COLORTYPE_CMYK, c, m, y, std::min(c, std::min(m, y)));
-}
-
-} // namespace
-
-CPWL_Color CPWL_Color::ConvertColorType(int32_t nConvertColorType) const {
- if (nColorType == nConvertColorType)
- return *this;
-
- CPWL_Color ret;
- switch (nColorType) {
- case COLORTYPE_TRANSPARENT:
- ret = *this;
- ret.nColorType = COLORTYPE_TRANSPARENT;
- break;
- case COLORTYPE_GRAY:
- switch (nConvertColorType) {
- case COLORTYPE_RGB:
- ret = ConvertGRAY2RGB(fColor1);
- break;
- case COLORTYPE_CMYK:
- ret = ConvertGRAY2CMYK(fColor1);
- break;
- }
- break;
- case COLORTYPE_RGB:
- switch (nConvertColorType) {
- case COLORTYPE_GRAY:
- ret = ConvertRGB2GRAY(fColor1, fColor2, fColor3);
- break;
- case COLORTYPE_CMYK:
- ret = ConvertRGB2CMYK(fColor1, fColor2, fColor3);
- break;
- }
- break;
- case COLORTYPE_CMYK:
- switch (nConvertColorType) {
- case COLORTYPE_GRAY:
- ret = ConvertCMYK2GRAY(fColor1, fColor2, fColor3, fColor4);
- break;
- case COLORTYPE_RGB:
- ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
- break;
- }
- break;
- }
- return ret;
-}
-
-FX_COLORREF CPWL_Color::ToFXColor(int32_t nTransparency) const {
- CPWL_Color ret;
- switch (nColorType) {
- case COLORTYPE_TRANSPARENT: {
- ret = CPWL_Color(COLORTYPE_TRANSPARENT, 0, 0, 0, 0);
- break;
- }
- case COLORTYPE_GRAY: {
- ret = ConvertGRAY2RGB(fColor1);
- ret.fColor4 = nTransparency;
- break;
- }
- case COLORTYPE_RGB: {
- ret = CPWL_Color(COLORTYPE_RGB, fColor1, fColor2, fColor3);
- ret.fColor4 = nTransparency;
- break;
- }
- case COLORTYPE_CMYK: {
- ret = ConvertCMYK2RGB(fColor1, fColor2, fColor3, fColor4);
- ret.fColor4 = nTransparency;
- break;
- }
- }
- return ArgbEncode(ret.fColor4, static_cast<int32_t>(ret.fColor1 * 255),
- static_cast<int32_t>(ret.fColor2 * 255),
- static_cast<int32_t>(ret.fColor3 * 255));
-}
-
-CPWL_Color CPWL_Color::operator-(FX_FLOAT fColorSub) const {
- CPWL_Color sRet(nColorType);
- switch (nColorType) {
- case COLORTYPE_TRANSPARENT:
- sRet.nColorType = COLORTYPE_RGB;
- sRet.fColor1 = std::max(1.0f - fColorSub, 0.0f);
- sRet.fColor2 = std::max(1.0f - fColorSub, 0.0f);
- sRet.fColor3 = std::max(1.0f - fColorSub, 0.0f);
- break;
- case COLORTYPE_RGB:
- case COLORTYPE_GRAY:
- case COLORTYPE_CMYK:
- sRet.fColor1 = std::max(fColor1 - fColorSub, 0.0f);
- sRet.fColor2 = std::max(fColor2 - fColorSub, 0.0f);
- sRet.fColor3 = std::max(fColor3 - fColorSub, 0.0f);
- sRet.fColor4 = std::max(fColor4 - fColorSub, 0.0f);
- break;
- }
- return sRet;
-}
-
-CPWL_Color CPWL_Color::operator/(FX_FLOAT fColorDivide) const {
- CPWL_Color sRet(nColorType);
- switch (nColorType) {
- case COLORTYPE_TRANSPARENT:
- sRet.nColorType = COLORTYPE_RGB;
- sRet.fColor1 = 1.0f / fColorDivide;
- sRet.fColor2 = 1.0f / fColorDivide;
- sRet.fColor3 = 1.0f / fColorDivide;
- break;
- case COLORTYPE_RGB:
- case COLORTYPE_GRAY:
- case COLORTYPE_CMYK:
- sRet = *this;
- sRet.fColor1 /= fColorDivide;
- sRet.fColor2 /= fColorDivide;
- sRet.fColor3 /= fColorDivide;
- sRet.fColor4 /= fColorDivide;
- break;
- }
- return sRet;
-}
diff --git a/fpdfsdk/pdfwindow/cpwl_color.h b/fpdfsdk/pdfwindow/cpwl_color.h
deleted file mode 100644
index f1b34c7..0000000
--- a/fpdfsdk/pdfwindow/cpwl_color.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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_COLOR_H_
-#define FPDFSDK_PDFWINDOW_CPWL_COLOR_H_
-
-#include "core/fpdfdoc/cpdf_formcontrol.h"
-
-struct CPWL_Color {
- CPWL_Color(int32_t type = COLORTYPE_TRANSPARENT,
- FX_FLOAT color1 = 0.0f,
- FX_FLOAT color2 = 0.0f,
- FX_FLOAT color3 = 0.0f,
- FX_FLOAT color4 = 0.0f)
- : nColorType(type),
- fColor1(color1),
- fColor2(color2),
- fColor3(color3),
- fColor4(color4) {}
-
- CPWL_Color(int32_t r, int32_t g, int32_t b)
- : nColorType(COLORTYPE_RGB),
- fColor1(r / 255.0f),
- fColor2(g / 255.0f),
- fColor3(b / 255.0f),
- fColor4(0) {}
-
- CPWL_Color operator/(FX_FLOAT fColorDivide) const;
- CPWL_Color operator-(FX_FLOAT fColorSub) const;
-
- CPWL_Color ConvertColorType(int32_t other_nColorType) const;
-
- FX_COLORREF ToFXColor(int32_t nTransparency) const;
-
- void Reset() {
- nColorType = COLORTYPE_TRANSPARENT;
- fColor1 = 0.0f;
- fColor2 = 0.0f;
- fColor3 = 0.0f;
- fColor4 = 0.0f;
- }
-
- int32_t nColorType;
- FX_FLOAT fColor1;
- FX_FLOAT fColor2;
- FX_FLOAT fColor3;
- FX_FLOAT fColor4;
-};
-
-#endif // FPDFSDK_PDFWINDOW_CPWL_COLOR_H_
diff --git a/fpdfsdk/pwl/README.md b/fpdfsdk/pwl/README.md
new file mode 100644
index 0000000..1a73250
--- /dev/null
+++ b/fpdfsdk/pwl/README.md
@@ -0,0 +1,21 @@
+fpdfsdk/pwl is a Widget Library for AcroForms.
+
+CPWL_Wnd is the base class that widget classes extend. The derived widget
+classes are controllers for each widget. The hierarchy is:
+
+* CPWL_Wnd
+ * CPWL_Button
+ * CPWL_CheckBox
+ * CPWL_PushButton
+ * CPWL_RadioButton
+ * CPWL_Caret
+ * CPWL_EditCtrl
+ * CPWL_Edit
+ * CPWL_Icon
+ * CPWL_ListBox
+ * CPWL_CBListBox (combo box)
+ * CPWL_ScrollBar
+
+Widgets are rendered to Appearance Streams, with the case all centralized in
+CPWL_AppStream.
+
diff --git a/fpdfsdk/pwl/cpwl_appstream.cpp b/fpdfsdk/pwl/cpwl_appstream.cpp
new file mode 100644
index 0000000..203a634
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_appstream.cpp
@@ -0,0 +1,1993 @@
+// 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/pwl/cpwl_appstream.h"
+
+#include <utility>
+
+#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 "core/fpdfapi/parser/fpdf_parser_decode.h"
+#include "core/fpdfdoc/cpvt_word.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/pwl/cpwl_edit.h"
+#include "fpdfsdk/pwl/cpwl_edit_impl.h"
+#include "fpdfsdk/pwl/cpwl_icon.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+namespace {
+
+// Checkbox & radiobutton styles.
+enum class CheckStyle { kCheck = 0, kCircle, kCross, kDiamond, kSquare, kStar };
+
+// Pushbutton layout styles.
+enum class ButtonStyle {
+ kLabel = 0,
+ kIcon,
+ kIconTopLabelBottom,
+ kIconBottomLabelTop,
+ kIconLeftLabelRight,
+ kIconRightLabelLeft,
+ kLabelOverIcon
+};
+
+const char kAppendRectOperator[] = "re";
+const char kConcatMatrixOperator[] = "cm";
+const char kCurveToOperator[] = "c";
+const char kEndPathNoFillOrStrokeOperator[] = "n";
+const char kFillOperator[] = "f";
+const char kFillEvenOddOperator[] = "f*";
+const char kInvokeNamedXObjectOperator[] = "Do";
+const char kLineToOperator[] = "l";
+const char kMarkedSequenceBeginOperator[] = "BMC";
+const char kMarkedSequenceEndOperator[] = "EMC";
+const char kMoveTextPositionOperator[] = "Td";
+const char kMoveToOperator[] = "m";
+const char kSetCharacterSpacingOperator[] = "Tc";
+const char kSetCMYKOperator[] = "k";
+const char kSetCMKYStrokedOperator[] = "K";
+const char kSetDashOperator[] = "d";
+const char kSetGrayOperator[] = "g";
+const char kSetGrayStrokedOperator[] = "G";
+const char kSetLineCapStyleOperator[] = "J";
+const char kSetLineJoinStyleOperator[] = "j";
+const char kSetLineWidthOperator[] = "w";
+const char kSetNonZeroWindingClipOperator[] = "W";
+const char kSetRGBOperator[] = "rg";
+const char kSetRGBStrokedOperator[] = "RG";
+const char kSetTextFontAndSizeOperator[] = "Tf";
+const char kSetTextScaleHorizontalOperator[] = "Tz";
+const char kShowTextOperator[] = "Tj";
+const char kStateRestoreOperator[] = "Q";
+const char kStateSaveOperator[] = "q";
+const char kStrokeOperator[] = "S";
+const char kTextBeginOperator[] = "BT";
+const char kTextEndOperator[] = "ET";
+
+class AutoClosedCommand {
+ public:
+ AutoClosedCommand(std::ostringstream* stream,
+ ByteString open,
+ ByteString close)
+ : stream_(stream), close_(close) {
+ *stream_ << open << "\n";
+ }
+
+ virtual ~AutoClosedCommand() { *stream_ << close_ << "\n"; }
+
+ private:
+ std::ostringstream* stream_;
+ ByteString close_;
+};
+
+class AutoClosedQCommand : public AutoClosedCommand {
+ public:
+ explicit AutoClosedQCommand(std::ostringstream* stream)
+ : AutoClosedCommand(stream, kStateSaveOperator, kStateRestoreOperator) {}
+ ~AutoClosedQCommand() override {}
+};
+
+ByteString GetColorAppStream(const CFX_Color& color,
+ const bool& bFillOrStroke) {
+ std::ostringstream sColorStream;
+
+ switch (color.nColorType) {
+ case CFX_Color::kRGB:
+ sColorStream << color.fColor1 << " " << color.fColor2 << " "
+ << color.fColor3 << " "
+ << (bFillOrStroke ? kSetRGBOperator : kSetRGBStrokedOperator)
+ << "\n";
+ break;
+ case CFX_Color::kGray:
+ sColorStream << color.fColor1 << " "
+ << (bFillOrStroke ? kSetGrayOperator
+ : kSetGrayStrokedOperator)
+ << "\n";
+ break;
+ case CFX_Color::kCMYK:
+ sColorStream << color.fColor1 << " " << color.fColor2 << " "
+ << color.fColor3 << " " << color.fColor4 << " "
+ << (bFillOrStroke ? kSetCMYKOperator
+ : kSetCMKYStrokedOperator)
+ << "\n";
+ break;
+ }
+
+ return ByteString(sColorStream);
+}
+
+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 << " " << kMoveToOperator << "\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 << " " << kCurveToOperator << "\n";
+ }
+
+ return ByteString(csAP);
+}
+
+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 << " " << kMoveToOperator << "\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
+ << " " << kCurveToOperator << "\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 << " "
+ << kCurveToOperator << "\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
+ << " " << kCurveToOperator << "\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 << " "
+ << kCurveToOperator << "\n";
+
+ return ByteString(csAP);
+}
+
+ByteString GetAP_Cross(const CFX_FloatRect& crBBox) {
+ std::ostringstream csAP;
+
+ csAP << crBBox.left << " " << crBBox.top << " " << kMoveToOperator << "\n";
+ csAP << crBBox.right << " " << crBBox.bottom << " " << kLineToOperator
+ << "\n";
+ csAP << crBBox.left << " " << crBBox.bottom << " " << kMoveToOperator << "\n";
+ csAP << crBBox.right << " " << crBBox.top << " " << kLineToOperator << "\n";
+
+ return ByteString(csAP);
+}
+
+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 << " " << kMoveToOperator << "\n";
+ csAP << pt2.x << " " << pt2.y << " " << kLineToOperator << "\n";
+ csAP << pt3.x << " " << pt3.y << " " << kLineToOperator << "\n";
+ csAP << pt4.x << " " << pt4.y << " " << kLineToOperator << "\n";
+ csAP << pt1.x << " " << pt1.y << " " << kLineToOperator << "\n";
+
+ return ByteString(csAP);
+}
+
+ByteString GetAP_Square(const CFX_FloatRect& crBBox) {
+ std::ostringstream csAP;
+
+ csAP << crBBox.left << " " << crBBox.top << " " << kMoveToOperator << "\n";
+ csAP << crBBox.right << " " << crBBox.top << " " << kLineToOperator << "\n";
+ csAP << crBBox.right << " " << crBBox.bottom << " " << kLineToOperator
+ << "\n";
+ csAP << crBBox.left << " " << crBBox.bottom << " " << kLineToOperator << "\n";
+ csAP << crBBox.left << " " << crBBox.top << " " << kLineToOperator << "\n";
+
+ return ByteString(csAP);
+}
+
+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] << " " << kMoveToOperator << "\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] << " " << kLineToOperator << "\n";
+ }
+
+ return ByteString(csAP);
+}
+
+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 << " " << kConcatMatrixOperator << "\n";
+
+ csAP << pt1.x << " " << pt1.y << " " << kMoveToOperator << "\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
+ << " " << kCurveToOperator << "\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 << " "
+ << kCurveToOperator << "\n";
+
+ return ByteString(csAP);
+}
+
+ByteString GetAppStream_Check(const CFX_FloatRect& rcBBox,
+ const CFX_Color& crText) {
+ std::ostringstream sAP;
+ {
+ AutoClosedQCommand q(&sAP);
+ sAP << GetColorAppStream(crText, true) << GetAP_Check(rcBBox)
+ << kFillOperator << "\n";
+ }
+ return ByteString(sAP);
+}
+
+ByteString GetAppStream_Circle(const CFX_FloatRect& rcBBox,
+ const CFX_Color& crText) {
+ std::ostringstream sAP;
+ {
+ AutoClosedQCommand q(&sAP);
+ sAP << GetColorAppStream(crText, true) << GetAP_Circle(rcBBox)
+ << kFillOperator << "\n";
+ }
+ return ByteString(sAP);
+}
+
+ByteString GetAppStream_Cross(const CFX_FloatRect& rcBBox,
+ const CFX_Color& crText) {
+ std::ostringstream sAP;
+ {
+ AutoClosedQCommand q(&sAP);
+ sAP << GetColorAppStream(crText, false) << GetAP_Cross(rcBBox)
+ << kStrokeOperator << "\n";
+ }
+ return ByteString(sAP);
+}
+
+ByteString GetAppStream_Diamond(const CFX_FloatRect& rcBBox,
+ const CFX_Color& crText) {
+ std::ostringstream sAP;
+ {
+ AutoClosedQCommand q(&sAP);
+ sAP << "1 " << kSetLineWidthOperator << "\n"
+ << GetColorAppStream(crText, true) << GetAP_Diamond(rcBBox)
+ << kFillOperator << "\n";
+ }
+ return ByteString(sAP);
+}
+
+ByteString GetAppStream_Square(const CFX_FloatRect& rcBBox,
+ const CFX_Color& crText) {
+ std::ostringstream sAP;
+ {
+ AutoClosedQCommand q(&sAP);
+ sAP << GetColorAppStream(crText, true) << GetAP_Square(rcBBox)
+ << kFillOperator << "\n";
+ }
+ return ByteString(sAP);
+}
+
+ByteString GetAppStream_Star(const CFX_FloatRect& rcBBox,
+ const CFX_Color& crText) {
+ std::ostringstream sAP;
+ {
+ AutoClosedQCommand q(&sAP);
+ sAP << GetColorAppStream(crText, true) << GetAP_Star(rcBBox)
+ << kFillOperator << "\n";
+ }
+ return ByteString(sAP);
+}
+
+ByteString GetCircleFillAppStream(const CFX_FloatRect& rect,
+ const CFX_Color& color) {
+ std::ostringstream sAppStream;
+ ByteString sColor = GetColorAppStream(color, true);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q(&sAppStream);
+ sAppStream << sColor << GetAP_Circle(rect) << kFillOperator << "\n";
+ }
+ return ByteString(sAppStream);
+}
+
+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;
+ ByteString sColor;
+
+ if (fWidth > 0.0f) {
+ AutoClosedQCommand q(&sAppStream);
+
+ 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 = GetColorAppStream(color, false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q2(&sAppStream);
+ sAppStream << fWidth << " " << kSetLineWidthOperator << "\n"
+ << sColor << GetAP_Circle(rect_by_2) << " "
+ << kStrokeOperator << "\n";
+ }
+ } break;
+ case BorderStyle::DASH: {
+ sColor = GetColorAppStream(color, false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q2(&sAppStream);
+ sAppStream << fWidth << " " << kSetLineWidthOperator << "\n"
+ << "[" << dash.nDash << " " << dash.nGap << "] "
+ << dash.nPhase << " " << kSetDashOperator << "\n"
+ << sColor << GetAP_Circle(rect_by_2) << " "
+ << kStrokeOperator << "\n";
+ }
+ } break;
+ case BorderStyle::BEVELED: {
+ sColor = GetColorAppStream(color, false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q2(&sAppStream);
+ sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
+ << sColor << GetAP_Circle(rect) << " " << kStrokeOperator
+ << "\n";
+ }
+
+ sColor = GetColorAppStream(crLeftTop, false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q2(&sAppStream);
+ sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
+ << sColor << GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f)
+ << " " << kStrokeOperator << "\n";
+ }
+
+ sColor = GetColorAppStream(crRightBottom, false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q2(&sAppStream);
+ sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
+ << sColor << GetAP_HalfCircle(rect_by_75, FX_PI * 5 / 4.0f)
+ << " " << kStrokeOperator << "\n";
+ }
+ } break;
+ case BorderStyle::INSET: {
+ sColor = GetColorAppStream(color, false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q2(&sAppStream);
+ sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
+ << sColor << GetAP_Circle(rect) << " " << kStrokeOperator
+ << "\n";
+ }
+
+ sColor = GetColorAppStream(crLeftTop, false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q2(&sAppStream);
+ sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
+ << sColor << GetAP_HalfCircle(rect_by_75, FX_PI / 4.0f)
+ << " " << kStrokeOperator << "\n";
+ }
+
+ sColor = GetColorAppStream(crRightBottom, false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q2(&sAppStream);
+ sAppStream << fHalfWidth << " " << kSetLineWidthOperator << "\n"
+ << sColor << GetAP_HalfCircle(rect_by_75, FX_PI * 5 / 4.0f)
+ << " " << kStrokeOperator << "\n";
+ }
+ } break;
+ }
+ }
+ return ByteString(sAppStream);
+}
+
+ByteString GetCheckBoxAppStream(const CFX_FloatRect& rcBBox,
+ CheckStyle nStyle,
+ const CFX_Color& crText) {
+ CFX_FloatRect rcCenter = rcBBox.GetCenterSquare();
+ switch (nStyle) {
+ default:
+ case CheckStyle::kCheck:
+ return GetAppStream_Check(rcCenter, crText);
+ case CheckStyle::kCircle:
+ rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
+ return GetAppStream_Circle(rcCenter, crText);
+ case CheckStyle::kCross:
+ return GetAppStream_Cross(rcCenter, crText);
+ case CheckStyle::kDiamond:
+ rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
+ return GetAppStream_Diamond(rcCenter, crText);
+ case CheckStyle::kSquare:
+ rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
+ return GetAppStream_Square(rcCenter, crText);
+ case CheckStyle::kStar:
+ rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
+ return GetAppStream_Star(rcCenter, crText);
+ }
+}
+
+ByteString GetRadioButtonAppStream(const CFX_FloatRect& rcBBox,
+ CheckStyle nStyle,
+ const CFX_Color& crText) {
+ CFX_FloatRect rcCenter = rcBBox.GetCenterSquare();
+ switch (nStyle) {
+ default:
+ case CheckStyle::kCheck:
+ return GetAppStream_Check(rcCenter, crText);
+ case CheckStyle::kCircle:
+ rcCenter.ScaleFromCenterPoint(1.0f / 2.0f);
+ return GetAppStream_Circle(rcCenter, crText);
+ case CheckStyle::kCross:
+ return GetAppStream_Cross(rcCenter, crText);
+ case CheckStyle::kDiamond:
+ rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
+ return GetAppStream_Diamond(rcCenter, crText);
+ case CheckStyle::kSquare:
+ rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
+ return GetAppStream_Square(rcCenter, crText);
+ case CheckStyle::kStar:
+ rcCenter.ScaleFromCenterPoint(2.0f / 3.0f);
+ return GetAppStream_Star(rcCenter, crText);
+ }
+}
+
+ByteString GetFontSetString(IPVT_FontMap* pFontMap,
+ int32_t nFontIndex,
+ float fFontSize) {
+ if (!pFontMap)
+ return ByteString();
+
+ ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
+ if (sFontAlias.GetLength() <= 0 || fFontSize <= 0)
+ return ByteString();
+
+ std::ostringstream sRet;
+ sRet << "/" << sFontAlias << " " << fFontSize << " "
+ << kSetTextFontAndSizeOperator << "\n";
+ return ByteString(sRet);
+}
+
+ByteString GetWordRenderString(const ByteString& strWords) {
+ if (strWords.GetLength() > 0) {
+ return PDF_EncodeString(strWords, false) + " " + kShowTextOperator + "\n";
+ }
+ return ByteString();
+}
+
+ByteString GetEditAppStream(CPWL_EditImpl* pEdit,
+ const CFX_PointF& ptOffset,
+ bool bContinuous,
+ uint16_t SubWord) {
+ CPWL_EditImpl_Iterator* pIterator = pEdit->GetIterator();
+ pIterator->SetAt(0);
+
+ std::ostringstream sEditStream;
+ std::ostringstream sWords;
+ int32_t nCurFontIndex = -1;
+ CFX_PointF ptOld;
+ CFX_PointF ptNew;
+ CPVT_WordPlace oldplace;
+
+ while (pIterator->NextWord()) {
+ CPVT_WordPlace place = pIterator->GetAt();
+ if (bContinuous) {
+ if (place.LineCmp(oldplace) != 0) {
+ if (sWords.tellp() > 0) {
+ sEditStream << GetWordRenderString(ByteString(sWords));
+ sWords.str("");
+ }
+
+ CPVT_Word word;
+ if (pIterator->GetWord(word)) {
+ ptNew = CFX_PointF(word.ptWord.x + ptOffset.x,
+ word.ptWord.y + ptOffset.y);
+ } else {
+ CPVT_Line line;
+ pIterator->GetLine(line);
+ ptNew = CFX_PointF(line.ptLine.x + ptOffset.x,
+ line.ptLine.y + ptOffset.y);
+ }
+
+ if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
+ sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " "
+ << kMoveTextPositionOperator << "\n";
+
+ ptOld = ptNew;
+ }
+ }
+
+ CPVT_Word word;
+ if (pIterator->GetWord(word)) {
+ if (word.nFontIndex != nCurFontIndex) {
+ if (sWords.tellp() > 0) {
+ sEditStream << GetWordRenderString(ByteString(sWords));
+ sWords.str("");
+ }
+ sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex,
+ word.fFontSize);
+ nCurFontIndex = word.nFontIndex;
+ }
+
+ sWords << pEdit->GetPDFWordString(nCurFontIndex, word.Word, SubWord);
+ }
+
+ oldplace = place;
+ } else {
+ CPVT_Word word;
+ if (pIterator->GetWord(word)) {
+ ptNew =
+ CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
+
+ if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
+ sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " "
+ << kMoveTextPositionOperator << "\n";
+ ptOld = ptNew;
+ }
+
+ if (word.nFontIndex != nCurFontIndex) {
+ sEditStream << GetFontSetString(pEdit->GetFontMap(), word.nFontIndex,
+ word.fFontSize);
+ nCurFontIndex = word.nFontIndex;
+ }
+
+ sEditStream << GetWordRenderString(
+ pEdit->GetPDFWordString(nCurFontIndex, word.Word, SubWord));
+ }
+ }
+ }
+
+ if (sWords.tellp() > 0) {
+ sEditStream << GetWordRenderString(ByteString(sWords));
+ sWords.str("");
+ }
+
+ std::ostringstream sAppStream;
+ if (sEditStream.tellp() > 0) {
+ int32_t nHorzScale = pEdit->GetHorzScale();
+ if (nHorzScale != 100) {
+ sAppStream << nHorzScale << " " << kSetTextScaleHorizontalOperator
+ << "\n";
+ }
+
+ float fCharSpace = pEdit->GetCharSpace();
+ if (!IsFloatZero(fCharSpace)) {
+ sAppStream << fCharSpace << " " << kSetCharacterSpacingOperator << "\n";
+ }
+
+ sAppStream << sEditStream.str();
+ }
+
+ return ByteString(sAppStream);
+}
+
+ByteString GenerateIconAppStream(CPDF_IconFit& fit,
+ CPDF_Stream* pIconStream,
+ const CFX_FloatRect& rcIcon) {
+ if (rcIcon.IsEmpty() || !pIconStream)
+ return ByteString();
+
+ CPWL_Icon icon;
+ CPWL_Wnd::CreateParams cp;
+ cp.dwFlags = PWS_VISIBLE;
+ icon.Create(cp);
+ icon.SetIconFit(&fit);
+ icon.SetPDFStream(pIconStream);
+ if (!icon.Move(rcIcon, false, false))
+ return ByteString();
+
+ ByteString sAlias = icon.GetImageAlias();
+ if (sAlias.GetLength() <= 0)
+ return ByteString();
+
+ CFX_FloatRect rcPlate = icon.GetClientRect();
+ CFX_Matrix mt = icon.GetImageMatrix().GetInverse();
+
+ float fHScale;
+ float fVScale;
+ std::tie(fHScale, fVScale) = icon.GetScale();
+
+ float fx;
+ float fy;
+ std::tie(fx, fy) = icon.GetImageOffset();
+
+ std::ostringstream str;
+ {
+ AutoClosedQCommand q(&str);
+ str << rcPlate.left << " " << rcPlate.bottom << " "
+ << rcPlate.right - rcPlate.left << " " << rcPlate.top - rcPlate.bottom
+ << " " << kAppendRectOperator << " " << kSetNonZeroWindingClipOperator
+ << " " << kEndPathNoFillOrStrokeOperator << "\n";
+
+ str << fHScale << " 0 0 " << fVScale << " " << rcPlate.left + fx << " "
+ << rcPlate.bottom + fy << " " << kConcatMatrixOperator << "\n";
+ str << mt.a << " " << mt.b << " " << mt.c << " " << mt.d << " " << mt.e
+ << " " << mt.f << " " << kConcatMatrixOperator << "\n";
+
+ str << "0 " << kSetGrayOperator << " 0 " << kSetGrayStrokedOperator << " 1 "
+ << kSetLineWidthOperator << " /" << sAlias << " "
+ << kInvokeNamedXObjectOperator << "\n";
+ }
+ icon.Destroy();
+
+ return ByteString(str);
+}
+
+ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox,
+ IPVT_FontMap* pFontMap,
+ CPDF_Stream* pIconStream,
+ CPDF_IconFit& IconFit,
+ const WideString& sLabel,
+ const CFX_Color& crText,
+ float fFontSize,
+ ButtonStyle nLayOut) {
+ const float fAutoFontScale = 1.0f / 3.0f;
+
+ auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
+ 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();
+ CFX_FloatRect rcLabel;
+ CFX_FloatRect rcIcon;
+ float fWidth = 0.0f;
+ float fHeight = 0.0f;
+
+ switch (nLayOut) {
+ case ButtonStyle::kLabel:
+ rcLabel = rcBBox;
+ break;
+ case ButtonStyle::kIcon:
+ rcIcon = rcBBox;
+ break;
+ case ButtonStyle::kIconTopLabelBottom:
+ 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 ButtonStyle::kIconBottomLabelTop:
+ 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 ButtonStyle::kIconLeftLabelRight:
+ 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 ButtonStyle::kIconRightLabelLeft:
+ 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 ButtonStyle::kLabelOverIcon:
+ rcLabel = rcBBox;
+ rcIcon = rcBBox;
+ break;
+ }
+
+ std::ostringstream sTemp;
+ sTemp << GenerateIconAppStream(IconFit, pIconStream, rcIcon);
+
+ if (!rcLabel.IsEmpty()) {
+ pEdit->SetPlateRect(rcLabel);
+ ByteString sEdit =
+ GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f), true, 0);
+ if (sEdit.GetLength() > 0) {
+ AutoClosedCommand bt(&sTemp, kTextBeginOperator, kTextEndOperator);
+ sTemp << GetColorAppStream(crText, true) << sEdit;
+ }
+ }
+
+ if (sTemp.tellp() <= 0)
+ return ByteString();
+
+ std::ostringstream sAppStream;
+ {
+ AutoClosedQCommand q(&sAppStream);
+ sAppStream << rcBBox.left << " " << rcBBox.bottom << " "
+ << rcBBox.right - rcBBox.left << " "
+ << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator
+ << " " << kSetNonZeroWindingClipOperator << " "
+ << kEndPathNoFillOrStrokeOperator << "\n";
+ sAppStream << sTemp.str().c_str();
+ }
+ return ByteString(sAppStream);
+}
+
+ByteString GetBorderAppStreamInternal(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;
+ ByteString sColor;
+
+ float fLeft = rect.left;
+ float fRight = rect.right;
+ float fTop = rect.top;
+ float fBottom = rect.bottom;
+
+ if (fWidth > 0.0f) {
+ float fHalfWidth = fWidth / 2.0f;
+ AutoClosedQCommand q(&sAppStream);
+
+ switch (nStyle) {
+ default:
+ case BorderStyle::SOLID:
+ sColor = GetColorAppStream(color, true);
+ if (sColor.GetLength() > 0) {
+ sAppStream << sColor;
+ sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
+ << fTop - fBottom << " " << kAppendRectOperator << "\n";
+ sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " "
+ << fRight - fLeft - fWidth * 2 << " "
+ << fTop - fBottom - fWidth * 2 << " "
+ << kAppendRectOperator << "\n";
+ sAppStream << kFillEvenOddOperator << "\n";
+ }
+ break;
+ case BorderStyle::DASH:
+ sColor = GetColorAppStream(color, false);
+ if (sColor.GetLength() > 0) {
+ sAppStream << sColor;
+ sAppStream << fWidth << " " << kSetLineWidthOperator << " ["
+ << dash.nDash << " " << dash.nGap << "] " << dash.nPhase
+ << " " << kSetDashOperator << "\n";
+ sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " "
+ << kMoveToOperator << "\n";
+ sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 << " "
+ << kLineToOperator << "\n";
+ sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 << " "
+ << kLineToOperator << "\n";
+ sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2
+ << " " << kLineToOperator << "\n";
+ sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 << " "
+ << kLineToOperator << " " << kStrokeOperator << "\n";
+ }
+ break;
+ case BorderStyle::BEVELED:
+ case BorderStyle::INSET:
+ sColor = GetColorAppStream(crLeftTop, true);
+ if (sColor.GetLength() > 0) {
+ sAppStream << sColor;
+ sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
+ << kMoveToOperator << "\n";
+ sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth << " "
+ << kLineToOperator << "\n";
+ sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " "
+ << kLineToOperator << "\n";
+ sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
+ << " " << kLineToOperator << "\n";
+ sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
+ << " " << kLineToOperator << "\n";
+ sAppStream << fLeft + fHalfWidth * 2 << " "
+ << fBottom + fHalfWidth * 2 << " " << kLineToOperator
+ << " " << kFillOperator << "\n";
+ }
+
+ sColor = GetColorAppStream(crRightBottom, true);
+ if (sColor.GetLength() > 0) {
+ sAppStream << sColor;
+ sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth << " "
+ << kMoveToOperator << "\n";
+ sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth
+ << " " << kLineToOperator << "\n";
+ sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
+ << kLineToOperator << "\n";
+ sAppStream << fLeft + fHalfWidth * 2 << " "
+ << fBottom + fHalfWidth * 2 << " " << kLineToOperator
+ << "\n";
+ sAppStream << fRight - fHalfWidth * 2 << " "
+ << fBottom + fHalfWidth * 2 << " " << kLineToOperator
+ << "\n";
+ sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2
+ << " " << kLineToOperator << " " << kFillOperator << "\n";
+ }
+
+ sColor = GetColorAppStream(color, true);
+ if (sColor.GetLength() > 0) {
+ sAppStream << sColor;
+ sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " "
+ << fTop - fBottom << " " << kAppendRectOperator << "\n";
+ sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " "
+ << fRight - fLeft - fHalfWidth * 2 << " "
+ << fTop - fBottom - fHalfWidth * 2 << " "
+ << kAppendRectOperator << " " << kFillEvenOddOperator
+ << "\n";
+ }
+ break;
+ case BorderStyle::UNDERLINE:
+ sColor = GetColorAppStream(color, false);
+ if (sColor.GetLength() > 0) {
+ sAppStream << sColor;
+ sAppStream << fWidth << " " << kSetLineWidthOperator << "\n";
+ sAppStream << fLeft << " " << fBottom + fWidth / 2 << " "
+ << kMoveToOperator << "\n";
+ sAppStream << fRight << " " << fBottom + fWidth / 2 << " "
+ << kLineToOperator << " " << kStrokeOperator << "\n";
+ }
+ break;
+ }
+ }
+
+ return ByteString(sAppStream);
+}
+
+ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox) {
+ if (rcBBox.IsEmpty())
+ return ByteString();
+
+ std::ostringstream sAppStream;
+ {
+ AutoClosedQCommand q(&sAppStream);
+ sAppStream << GetColorAppStream(CFX_Color(CFX_Color::kRGB, 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 << " " << kAppendRectOperator
+ << " " << kFillOperator << "\n";
+ }
+
+ {
+ AutoClosedQCommand q(&sAppStream);
+ sAppStream << GetBorderAppStreamInternal(
+ rcBBox, 2, CFX_Color(CFX_Color::kGray, 0),
+ CFX_Color(CFX_Color::kGray, 1), CFX_Color(CFX_Color::kGray, 0.5),
+ BorderStyle::BEVELED, CPWL_Dash(3, 0, 0));
+ }
+
+ 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)) {
+ AutoClosedQCommand q(&sAppStream);
+ sAppStream << " 0 " << kSetGrayOperator << "\n"
+ << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " "
+ << kMoveToOperator << "\n"
+ << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " "
+ << kLineToOperator << "\n"
+ << ptCenter.x << " " << ptCenter.y - 1.5f << " "
+ << kLineToOperator << "\n"
+ << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " "
+ << kLineToOperator << " " << kFillOperator << "\n";
+ }
+
+ return ByteString(sAppStream);
+}
+
+ByteString GetRectFillAppStream(const CFX_FloatRect& rect,
+ const CFX_Color& color) {
+ std::ostringstream sAppStream;
+ ByteString sColor = GetColorAppStream(color, true);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q(&sAppStream);
+ sAppStream << sColor << rect.left << " " << rect.bottom << " "
+ << rect.right - rect.left << " " << rect.top - rect.bottom << " "
+ << kAppendRectOperator << " " << kFillOperator << "\n";
+ }
+
+ return 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();
+ ButtonStyle nLayout = ButtonStyle::kLabel;
+ switch (pControl->GetTextPosition()) {
+ case TEXTPOS_ICON:
+ nLayout = ButtonStyle::kIcon;
+ break;
+ case TEXTPOS_BELOW:
+ nLayout = ButtonStyle::kIconTopLabelBottom;
+ break;
+ case TEXTPOS_ABOVE:
+ nLayout = ButtonStyle::kIconBottomLabelTop;
+ break;
+ case TEXTPOS_RIGHT:
+ nLayout = ButtonStyle::kIconLeftLabelRight;
+ break;
+ case TEXTPOS_LEFT:
+ nLayout = ButtonStyle::kIconRightLabelLeft;
+ break;
+ case TEXTPOS_OVERLAID:
+ nLayout = ButtonStyle::kLabelOverIcon;
+ break;
+ default:
+ nLayout = ButtonStyle::kLabel;
+ 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<float>(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(CFX_Color::kGray, 1);
+ crRightBottom = crBackground / 2.0f;
+ break;
+ case BorderStyle::INSET:
+ fBorderWidth *= 2;
+ crLeftTop = CFX_Color(CFX_Color::kGray, 0.5);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 0.75);
+ break;
+ default:
+ break;
+ }
+
+ CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth);
+ CFX_Color crText(CFX_Color::kGray, 0);
+ 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);
+
+ WideString csWCaption;
+ WideString csNormalCaption;
+ WideString csRolloverCaption;
+ 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<CPDF_String>("Name", "ImgA", false);
+ }
+ }
+
+ if (pRolloverIcon) {
+ if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) {
+ if (pImageDict->GetStringFor("Name").IsEmpty())
+ pImageDict->SetNewFor<CPDF_String>("Name", "ImgB", false);
+ }
+ }
+
+ if (pDownIcon) {
+ if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) {
+ if (pImageDict->GetStringFor("Name").IsEmpty())
+ pImageDict->SetNewFor<CPDF_String>("Name", "ImgC", false);
+ }
+ }
+
+ CPDF_IconFit iconFit = pControl->GetIconFit();
+
+ CBA_FontMap font_map(
+ widget_.Get(),
+ widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler());
+ font_map.SetAPType("N");
+
+ ByteString csAP =
+ GetRectFillAppStream(rcWindow, crBackground) +
+ GetBorderAppStreamInternal(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 =
+ GetRectFillAppStream(rcWindow, crBackground) +
+ GetBorderAppStreamInternal(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(CFX_Color::kGray, 0);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 1);
+ break;
+ }
+ default:
+ break;
+ }
+
+ font_map.SetAPType("D");
+
+ csAP =
+ GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
+ GetBorderAppStreamInternal(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<float>(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(CFX_Color::kGray, 1);
+ crRightBottom = crBackground / 2.0f;
+ break;
+ case BorderStyle::INSET:
+ fBorderWidth *= 2;
+ crLeftTop = CFX_Color(CFX_Color::kGray, 0.5);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 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]);
+ }
+
+ CheckStyle nStyle = CheckStyle::kCheck;
+ WideString csWCaption = pControl->GetNormalCaption();
+ if (csWCaption.GetLength() > 0) {
+ switch (csWCaption[0]) {
+ case L'l':
+ nStyle = CheckStyle::kCircle;
+ break;
+ case L'8':
+ nStyle = CheckStyle::kCross;
+ break;
+ case L'u':
+ nStyle = CheckStyle::kDiamond;
+ break;
+ case L'n':
+ nStyle = CheckStyle::kSquare;
+ break;
+ case L'H':
+ nStyle = CheckStyle::kStar;
+ break;
+ case L'4':
+ default:
+ nStyle = CheckStyle::kCheck;
+ }
+ }
+
+ ByteString csAP_N_ON =
+ GetRectFillAppStream(rcWindow, crBackground) +
+ GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
+ crRightBottom, nBorderStyle, dsBorder);
+
+ 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(CFX_Color::kGray, 0);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 1);
+ break;
+ }
+ default:
+ break;
+ }
+
+ ByteString csAP_D_ON =
+ GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
+ GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
+ crRightBottom, nBorderStyle, dsBorder);
+
+ 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");
+
+ 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<float>(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(CFX_Color::kGray, 1);
+ crRightBottom = crBackground / 2.0f;
+ break;
+ case BorderStyle::INSET:
+ fBorderWidth *= 2;
+ crLeftTop = CFX_Color(CFX_Color::kGray, 0.5);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 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]);
+ }
+
+ CheckStyle nStyle = CheckStyle::kCircle;
+ WideString csWCaption = pControl->GetNormalCaption();
+ if (csWCaption.GetLength() > 0) {
+ switch (csWCaption[0]) {
+ case L'8':
+ nStyle = CheckStyle::kCross;
+ break;
+ case L'u':
+ nStyle = CheckStyle::kDiamond;
+ break;
+ case L'n':
+ nStyle = CheckStyle::kSquare;
+ break;
+ case L'H':
+ nStyle = CheckStyle::kStar;
+ break;
+ case L'4':
+ nStyle = CheckStyle::kCheck;
+ break;
+ case L'l':
+ default:
+ nStyle = CheckStyle::kCircle;
+ }
+ }
+
+ ByteString csAP_N_ON;
+ CFX_FloatRect rcCenter = rcWindow.GetCenterSquare().GetDeflated(1.0f, 1.0f);
+ if (nStyle == CheckStyle::kCircle) {
+ if (nBorderStyle == BorderStyle::BEVELED) {
+ crLeftTop = CFX_Color(CFX_Color::kGray, 1);
+ crRightBottom = crBackground - 0.25f;
+ } else if (nBorderStyle == BorderStyle::INSET) {
+ crLeftTop = CFX_Color(CFX_Color::kGray, 0.5f);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 0.75f);
+ }
+
+ csAP_N_ON =
+ GetCircleFillAppStream(rcCenter, crBackground) +
+ GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop,
+ crRightBottom, nBorderStyle, dsBorder);
+ } else {
+ csAP_N_ON =
+ GetRectFillAppStream(rcWindow, crBackground) +
+ GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
+ crRightBottom, nBorderStyle, dsBorder);
+ }
+
+ 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(CFX_Color::kGray, 0);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 1);
+ break;
+ }
+ default:
+ break;
+ }
+
+ ByteString csAP_D_ON;
+
+ if (nStyle == CheckStyle::kCircle) {
+ CFX_Color crBK = crBackground - 0.25f;
+ if (nBorderStyle == BorderStyle::BEVELED) {
+ crLeftTop = crBackground - 0.25f;
+ crRightBottom = CFX_Color(CFX_Color::kGray, 1);
+ crBK = crBackground;
+ } else if (nBorderStyle == BorderStyle::INSET) {
+ crLeftTop = CFX_Color(CFX_Color::kGray, 0);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 1);
+ }
+
+ csAP_D_ON =
+ GetCircleFillAppStream(rcCenter, crBK) +
+ GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop,
+ crRightBottom, nBorderStyle, dsBorder);
+ } else {
+ csAP_D_ON =
+ GetRectFillAppStream(rcWindow, crBackground - 0.25f) +
+ GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
+ crRightBottom, nBorderStyle, dsBorder);
+ }
+
+ 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");
+
+ ByteString csAS = widget_->GetAppState();
+ if (csAS.IsEmpty())
+ widget_->SetAppState("Off");
+}
+
+void CPWL_AppStream::SetAsComboBox(const 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<CPWL_EditImpl>();
+ 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();
+ ByteString sEdit = GetEditAppStream(pEdit.get(), CFX_PointF(), true, 0);
+ if (sEdit.GetLength() > 0) {
+ sBody << "/Tx ";
+ AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
+ kMarkedSequenceEndOperator);
+ AutoClosedQCommand q(&sBody);
+
+ if (rcContent.Width() > rcEdit.Width() ||
+ rcContent.Height() > rcEdit.Height()) {
+ sBody << rcEdit.left << " " << rcEdit.bottom << " " << rcEdit.Width()
+ << " " << rcEdit.Height() << " " << kAppendRectOperator << "\n"
+ << kSetNonZeroWindingClipOperator << "\n"
+ << kEndPathNoFillOrStrokeOperator << "\n";
+ }
+
+ CFX_Color crText = widget_->GetTextPWLColor();
+ AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator);
+ sBody << GetColorAppStream(crText, true) << sEdit;
+ }
+
+ sBody << GetDropButtonAppStream(rcButton);
+ Write("N",
+ GetBackgroundAppStream() + GetBorderAppStream() + 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<CPWL_EditImpl>();
+ 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);
+ {
+ AutoClosedQCommand q(&sList);
+ sList << GetColorAppStream(CFX_Color(CFX_Color::kRGB, 0, 51.0f / 255.0f,
+ 113.0f / 255.0f),
+ true)
+ << rcItem.left << " " << rcItem.bottom << " " << rcItem.Width()
+ << " " << rcItem.Height() << " " << kAppendRectOperator << " "
+ << kFillOperator << "\n";
+ }
+
+ AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator);
+ sList << GetColorAppStream(CFX_Color(CFX_Color::kGray, 1), true)
+ << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0);
+ } else {
+ CFX_Color crText = widget_->GetTextPWLColor();
+
+ AutoClosedCommand bt(&sList, kTextBeginOperator, kTextEndOperator);
+ sList << GetColorAppStream(crText, true)
+ << GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, fy), true, 0);
+ }
+
+ fy -= fItemHeight;
+ }
+
+ if (sList.tellp() > 0) {
+ sBody << "/Tx ";
+ AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
+ kMarkedSequenceEndOperator);
+ AutoClosedQCommand q(&sBody);
+
+ sBody << rcClient.left << " " << rcClient.bottom << " " << rcClient.Width()
+ << " " << rcClient.Height() << " " << kAppendRectOperator << "\n"
+ << kSetNonZeroWindingClipOperator << "\n"
+ << kEndPathNoFillOrStrokeOperator << "\n"
+ << sList.str();
+ }
+ Write("N",
+ GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sBody),
+ "");
+}
+
+void CPWL_AppStream::SetAsTextField(const WideString* sValue) {
+ CPDF_FormControl* pControl = widget_->GetFormControl();
+ CPDF_FormField* pField = pControl->GetField();
+ std::ostringstream sBody;
+ std::ostringstream sLines;
+
+ auto pEdit = pdfium::MakeUnique<CPWL_EditImpl>();
+ 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
+ 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();
+ ByteString sEdit =
+ GetEditAppStream(pEdit.get(), CFX_PointF(), !bCharArray, subWord);
+
+ if (sEdit.GetLength() > 0) {
+ sBody << "/Tx ";
+ AutoClosedCommand bmc(&sBody, kMarkedSequenceBeginOperator,
+ kMarkedSequenceEndOperator);
+ AutoClosedQCommand q(&sBody);
+
+ if (rcContent.Width() > rcClient.Width() ||
+ rcContent.Height() > rcClient.Height()) {
+ sBody << rcClient.left << " " << rcClient.bottom << " "
+ << rcClient.Width() << " " << rcClient.Height() << " "
+ << kAppendRectOperator << "\n"
+ << kSetNonZeroWindingClipOperator << "\n"
+ << kEndPathNoFillOrStrokeOperator << "\n";
+ }
+ CFX_Color crText = widget_->GetTextPWLColor();
+
+ AutoClosedCommand bt(&sBody, kTextBeginOperator, kTextEndOperator);
+ sBody << GetColorAppStream(crText, true) << sEdit;
+ }
+
+ if (bCharArray) {
+ switch (widget_->GetBorderStyle()) {
+ case BorderStyle::SOLID: {
+ ByteString sColor =
+ GetColorAppStream(widget_->GetBorderPWLColor(), false);
+ if (sColor.GetLength() > 0) {
+ AutoClosedQCommand q(&sLines);
+ sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator
+ << "\n"
+ << GetColorAppStream(widget_->GetBorderPWLColor(), false)
+ << " 2 " << kSetLineCapStyleOperator << " 0 "
+ << kSetLineJoinStyleOperator << "\n";
+
+ for (int32_t i = 1; i < nMaxLen; ++i) {
+ sLines << rcClient.left +
+ ((rcClient.right - rcClient.left) / nMaxLen) * i
+ << " " << rcClient.bottom << " " << kMoveToOperator << "\n"
+ << rcClient.left +
+ ((rcClient.right - rcClient.left) / nMaxLen) * i
+ << " " << rcClient.top << " " << kLineToOperator << " "
+ << kStrokeOperator << "\n";
+ }
+ }
+ break;
+ }
+ case BorderStyle::DASH: {
+ ByteString sColor =
+ GetColorAppStream(widget_->GetBorderPWLColor(), false);
+ if (sColor.GetLength() > 0) {
+ CPWL_Dash dsBorder = CPWL_Dash(3, 3, 0);
+ AutoClosedQCommand q(&sLines);
+ sLines << widget_->GetBorderWidth() << " " << kSetLineWidthOperator
+ << "\n"
+ << GetColorAppStream(widget_->GetBorderPWLColor(), false)
+ << "[" << dsBorder.nDash << " " << dsBorder.nGap << "] "
+ << dsBorder.nPhase << " " << kSetDashOperator << "\n";
+
+ for (int32_t i = 1; i < nMaxLen; ++i) {
+ sLines << rcClient.left +
+ ((rcClient.right - rcClient.left) / nMaxLen) * i
+ << " " << rcClient.bottom << " " << kMoveToOperator << "\n"
+ << rcClient.left +
+ ((rcClient.right - rcClient.left) / nMaxLen) * i
+ << " " << rcClient.top << " " << kLineToOperator << " "
+ << kStrokeOperator << "\n";
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ Write("N",
+ GetBackgroundAppStream() + GetBorderAppStream() + ByteString(sLines) +
+ ByteString(sBody),
+ "");
+}
+
+void CPWL_AppStream::AddImage(const ByteString& sAPType, CPDF_Stream* pImage) {
+ CPDF_Stream* pStream = dict_->GetStreamFor(sAPType);
+ CPDF_Dictionary* pStreamDict = pStream->GetDict();
+ 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<CPDF_Dictionary>("Resources");
+
+ CPDF_Dictionary* pXObject =
+ pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
+ pXObject->SetNewFor<CPDF_Reference>(sImageAlias,
+ widget_->GetPageView()->GetPDFDocument(),
+ pImage->GetObjNum());
+}
+
+void CPWL_AppStream::Write(const ByteString& sAPType,
+ const ByteString& sContents,
+ const 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<CPDF_Dictionary>(sAPType);
+
+ pParentDict = pAPTypeDict;
+ pStream = pAPTypeDict->GetStreamFor(sAPState);
+ }
+
+ if (!pStream) {
+ CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument();
+ pStream = doc->NewIndirect<CPDF_Stream>();
+ pParentDict->SetNewFor<CPDF_Reference>(sAPType, doc, pStream->GetObjNum());
+ }
+
+ CPDF_Dictionary* pStreamDict = pStream->GetDict();
+ if (!pStreamDict) {
+ auto pNewDict = pdfium::MakeUnique<CPDF_Dictionary>(
+ widget_->GetPDFAnnot()->GetDocument()->GetByteStringPool());
+ pStreamDict = pNewDict.get();
+ pStreamDict->SetNewFor<CPDF_Name>("Type", "XObject");
+ pStreamDict->SetNewFor<CPDF_Name>("Subtype", "Form");
+ pStreamDict->SetNewFor<CPDF_Number>("FormType", 1);
+ pStream->InitStream(nullptr, 0, std::move(pNewDict));
+ }
+ pStreamDict->SetMatrixFor("Matrix", widget_->GetMatrix());
+ pStreamDict->SetRectFor("BBox", widget_->GetRotatedRect());
+ pStream->SetDataAndRemoveFilter((uint8_t*)(sContents.c_str()),
+ sContents.GetLength());
+}
+
+void CPWL_AppStream::Remove(const ByteString& sAPType) {
+ dict_->RemoveFor(sAPType);
+}
+
+ByteString CPWL_AppStream::GetBackgroundAppStream() const {
+ CFX_Color crBackground = widget_->GetFillPWLColor();
+ if (crBackground.nColorType != CFX_Color::kTransparent)
+ return GetRectFillAppStream(widget_->GetRotatedRect(), crBackground);
+
+ return ByteString();
+}
+
+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<float>(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(CFX_Color::kGray, 1);
+ crRightBottom = crBackground / 2.0f;
+ break;
+ case BorderStyle::INSET:
+ fBorderWidth *= 2;
+ crLeftTop = CFX_Color(CFX_Color::kGray, 0.5);
+ crRightBottom = CFX_Color(CFX_Color::kGray, 0.75);
+ break;
+ default:
+ break;
+ }
+
+ return GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop,
+ crRightBottom, nBorderStyle, dsBorder);
+}
diff --git a/fpdfsdk/pwl/cpwl_appstream.h b/fpdfsdk/pwl/cpwl_appstream.h
new file mode 100644
index 0000000..810e79c
--- /dev/null
+++ b/fpdfsdk/pwl/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_PWL_CPWL_APPSTREAM_H_
+#define FPDFSDK_PWL_CPWL_APPSTREAM_H_
+
+#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/unowned_ptr.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 WideString* sValue);
+ void SetAsListBox();
+ void SetAsTextField(const WideString* sValue);
+
+ private:
+ void AddImage(const ByteString& sAPType, CPDF_Stream* pImage);
+ void Write(const ByteString& sAPType,
+ const ByteString& sContents,
+ const ByteString& sAPState);
+ void Remove(const ByteString& sAPType);
+
+ ByteString GetBackgroundAppStream() const;
+ ByteString GetBorderAppStream() const;
+
+ UnownedPtr<CPDFSDK_Widget> widget_;
+ UnownedPtr<CPDF_Dictionary> dict_;
+};
+
+#endif // FPDFSDK_PWL_CPWL_APPSTREAM_H_
diff --git a/fpdfsdk/pdfwindow/PWL_Button.cpp b/fpdfsdk/pwl/cpwl_button.cpp
similarity index 72%
rename from fpdfsdk/pdfwindow/PWL_Button.cpp
rename to fpdfsdk/pwl/cpwl_button.cpp
index 96be469..5c06a98 100644
--- a/fpdfsdk/pdfwindow/PWL_Button.cpp
+++ b/fpdfsdk/pwl/cpwl_button.cpp
@@ -4,36 +4,31 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#include "fpdfsdk/pdfwindow/PWL_Button.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
+#include "fpdfsdk/pwl/cpwl_button.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
CPWL_Button::CPWL_Button() : m_bMouseDown(false) {}
CPWL_Button::~CPWL_Button() {}
-CFX_ByteString CPWL_Button::GetClassName() const {
+ByteString CPWL_Button::GetClassName() const {
return "CPWL_Button";
}
-void CPWL_Button::OnCreate(PWL_CREATEPARAM& cp) {
- cp.eCursorType = FXCT_HAND;
+void CPWL_Button::OnCreate(CreateParams* pParamsToAdjust) {
+ pParamsToAdjust->eCursorType = FXCT_HAND;
}
bool CPWL_Button::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
CPWL_Wnd::OnLButtonDown(point, nFlag);
-
m_bMouseDown = true;
SetCapture();
-
return true;
}
bool CPWL_Button::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
CPWL_Wnd::OnLButtonUp(point, nFlag);
-
ReleaseCapture();
m_bMouseDown = false;
-
return true;
}
diff --git a/fpdfsdk/pdfwindow/PWL_Button.h b/fpdfsdk/pwl/cpwl_button.h
similarity index 67%
rename from fpdfsdk/pdfwindow/PWL_Button.h
rename to fpdfsdk/pwl/cpwl_button.h
index 2d1193f..70f5ef1 100644
--- a/fpdfsdk/pdfwindow/PWL_Button.h
+++ b/fpdfsdk/pwl/cpwl_button.h
@@ -4,10 +4,10 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#ifndef FPDFSDK_PDFWINDOW_PWL_BUTTON_H_
-#define FPDFSDK_PDFWINDOW_PWL_BUTTON_H_
+#ifndef FPDFSDK_PWL_CPWL_BUTTON_H_
+#define FPDFSDK_PWL_CPWL_BUTTON_H_
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
class CPWL_Button : public CPWL_Wnd {
public:
@@ -15,8 +15,8 @@
~CPWL_Button() override;
// CPWL_Wnd
- CFX_ByteString GetClassName() const override;
- void OnCreate(PWL_CREATEPARAM& cp) override;
+ ByteString GetClassName() const override;
+ void OnCreate(CreateParams* pParamsToAdjust) override;
bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
@@ -24,4 +24,4 @@
bool m_bMouseDown;
};
-#endif // FPDFSDK_PDFWINDOW_PWL_BUTTON_H_
+#endif // FPDFSDK_PWL_CPWL_BUTTON_H_
diff --git a/fpdfsdk/pwl/cpwl_caret.cpp b/fpdfsdk/pwl/cpwl_caret.cpp
new file mode 100644
index 0000000..77a768a
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_caret.cpp
@@ -0,0 +1,134 @@
+// Copyright 2014 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/pwl/cpwl_caret.h"
+
+#include <sstream>
+
+#include "core/fxge/cfx_graphstatedata.h"
+#include "core/fxge/cfx_pathdata.h"
+#include "core/fxge/cfx_renderdevice.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+#define PWL_CARET_FLASHINTERVAL 500
+
+CPWL_Caret::CPWL_Caret() : m_bFlash(false), m_fWidth(0.4f), m_nDelay(0) {}
+
+CPWL_Caret::~CPWL_Caret() {}
+
+ByteString CPWL_Caret::GetClassName() const {
+ return "CPWL_Caret";
+}
+
+void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ if (!IsVisible() || !m_bFlash)
+ return;
+
+ CFX_FloatRect rcRect = GetCaretRect();
+ CFX_FloatRect rcClip = GetClipRect();
+ CFX_PathData path;
+
+ float fCaretX = rcRect.left + m_fWidth * 0.5f;
+ float fCaretTop = rcRect.top;
+ float fCaretBottom = rcRect.bottom;
+ if (!rcClip.IsEmpty()) {
+ rcRect.Intersect(rcClip);
+ if (rcRect.IsEmpty())
+ return;
+
+ fCaretTop = rcRect.top;
+ fCaretBottom = rcRect.bottom;
+ }
+
+ path.AppendPoint(CFX_PointF(fCaretX, fCaretBottom), FXPT_TYPE::MoveTo, false);
+ path.AppendPoint(CFX_PointF(fCaretX, fCaretTop), FXPT_TYPE::LineTo, false);
+
+ CFX_GraphStateData gsd;
+ gsd.m_LineWidth = m_fWidth;
+ pDevice->DrawPath(&path, &mtUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0),
+ FXFILL_ALTERNATE);
+}
+
+void CPWL_Caret::TimerProc() {
+ if (m_nDelay > 0) {
+ --m_nDelay;
+ return;
+ }
+
+ m_bFlash = !m_bFlash;
+ InvalidateRect(nullptr);
+ // Note, |this| may no longer be viable at this point. If more work needs
+ // to be done, add an observer.
+}
+
+CFX_FloatRect CPWL_Caret::GetCaretRect() const {
+ return CFX_FloatRect(m_ptFoot.x, m_ptFoot.y, m_ptHead.x + m_fWidth,
+ m_ptHead.y);
+}
+
+void CPWL_Caret::SetCaret(bool bVisible,
+ const CFX_PointF& ptHead,
+ const CFX_PointF& ptFoot) {
+ if (!bVisible) {
+ m_ptHead = CFX_PointF();
+ m_ptFoot = CFX_PointF();
+ m_bFlash = false;
+ if (!IsVisible())
+ return;
+
+ EndTimer();
+ CPWL_Wnd::SetVisible(false);
+ // Note, |this| may no longer be viable at this point. If more work needs
+ // to be done, check the return value of SetVisible().
+ return;
+ }
+
+ if (!IsVisible()) {
+ m_ptHead = ptHead;
+ m_ptFoot = ptFoot;
+ EndTimer();
+ BeginTimer(PWL_CARET_FLASHINTERVAL);
+
+ if (!CPWL_Wnd::SetVisible(true))
+ return;
+
+ m_bFlash = true;
+ Move(m_rcInvalid, false, true);
+ // Note, |this| may no longer be viable at this point. If more work needs
+ // to be done, check the return value of Move().
+ return;
+ }
+
+ if (m_ptHead == ptHead && m_ptFoot == ptFoot)
+ return;
+
+ m_ptHead = ptHead;
+ m_ptFoot = ptFoot;
+ m_bFlash = true;
+ Move(m_rcInvalid, false, true);
+ // Note, |this| may no longer be viable at this point. If more work
+ // needs to be done, check the return value of Move().
+}
+
+bool CPWL_Caret::InvalidateRect(CFX_FloatRect* pRect) {
+ if (!pRect) {
+ return CPWL_Wnd::InvalidateRect(nullptr);
+ }
+
+ CFX_FloatRect rcRefresh = *pRect;
+ if (!rcRefresh.IsEmpty()) {
+ rcRefresh.Inflate(0.5f, 0.5f);
+ rcRefresh.Normalize();
+ }
+ rcRefresh.top += 1;
+ rcRefresh.bottom -= 1;
+ return CPWL_Wnd::InvalidateRect(&rcRefresh);
+}
+
+bool CPWL_Caret::SetVisible(bool bVisible) {
+ return true;
+}
diff --git a/fpdfsdk/pwl/cpwl_caret.h b/fpdfsdk/pwl/cpwl_caret.h
new file mode 100644
index 0000000..d60a964
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_caret.h
@@ -0,0 +1,41 @@
+// Copyright 2014 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_PWL_CPWL_CARET_H_
+#define FPDFSDK_PWL_CPWL_CARET_H_
+
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+class CPWL_Caret : public CPWL_Wnd {
+ public:
+ CPWL_Caret();
+ ~CPWL_Caret() override;
+
+ // CPWL_Wnd
+ ByteString GetClassName() const override;
+ void DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) override;
+ bool InvalidateRect(CFX_FloatRect* pRect) override;
+ bool SetVisible(bool bVisible) override;
+ void TimerProc() override;
+
+ void SetCaret(bool bVisible,
+ const CFX_PointF& ptHead,
+ const CFX_PointF& ptFoot);
+ void SetInvalidRect(CFX_FloatRect rc) { m_rcInvalid = rc; }
+
+ private:
+ CFX_FloatRect GetCaretRect() const;
+
+ bool m_bFlash;
+ CFX_PointF m_ptHead;
+ CFX_PointF m_ptFoot;
+ float m_fWidth;
+ int32_t m_nDelay;
+ CFX_FloatRect m_rcInvalid;
+};
+
+#endif // FPDFSDK_PWL_CPWL_CARET_H_
diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp
new file mode 100644
index 0000000..3adbebc
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_combo_box.cpp
@@ -0,0 +1,584 @@
+// Copyright 2014 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/pwl/cpwl_combo_box.h"
+
+#include <algorithm>
+#include <sstream>
+
+#include "core/fxge/cfx_pathdata.h"
+#include "core/fxge/cfx_renderdevice.h"
+#include "fpdfsdk/pwl/cpwl_edit.h"
+#include "fpdfsdk/pwl/cpwl_edit_ctrl.h"
+#include "fpdfsdk/pwl/cpwl_list_box.h"
+#include "fpdfsdk/pwl/cpwl_list_impl.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "public/fpdf_fwlevent.h"
+
+namespace {
+
+constexpr float kComboBoxDefaultFontSize = 12.0f;
+constexpr float kComboBoxTriangleHalfLength = 3.0f;
+constexpr int kDefaultButtonWidth = 13;
+
+} // namespace
+
+bool CPWL_CBListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonUp(point, nFlag);
+
+ if (!m_bMouseDown)
+ return true;
+
+ ReleaseCapture();
+ m_bMouseDown = false;
+
+ if (!ClientHitTest(point))
+ return true;
+ if (CPWL_Wnd* pParent = GetParentWindow())
+ pParent->NotifyLButtonUp(this, point);
+
+ return !OnNotifySelectionChanged(false, nFlag);
+}
+
+bool CPWL_CBListBox::IsMovementKey(uint16_t nChar) const {
+ switch (nChar) {
+ case FWL_VKEY_Up:
+ case FWL_VKEY_Down:
+ case FWL_VKEY_Home:
+ case FWL_VKEY_Left:
+ case FWL_VKEY_End:
+ case FWL_VKEY_Right:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool CPWL_CBListBox::OnMovementKeyDown(uint16_t nChar, uint32_t nFlag) {
+ ASSERT(IsMovementKey(nChar));
+
+ switch (nChar) {
+ case FWL_VKEY_Up:
+ m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Down:
+ m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Home:
+ m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Left:
+ m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_End:
+ m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Right:
+ m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ }
+ return OnNotifySelectionChanged(true, nFlag);
+}
+
+bool CPWL_CBListBox::IsChar(uint16_t nChar, uint32_t nFlag) const {
+ return m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+}
+
+bool CPWL_CBListBox::OnCharNotify(uint16_t nChar, uint32_t nFlag) {
+ if (CPWL_ComboBox* pComboBox = (CPWL_ComboBox*)GetParentWindow())
+ pComboBox->SetSelectText();
+
+ return OnNotifySelectionChanged(true, nFlag);
+}
+
+void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device);
+
+ CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect();
+
+ if (!IsVisible() || rectWnd.IsEmpty())
+ return;
+
+ CFX_PointF ptCenter = GetCenterPoint();
+
+ static constexpr float kComboBoxTriangleQuarterLength =
+ kComboBoxTriangleHalfLength * 0.5;
+ CFX_PointF pt1(ptCenter.x - kComboBoxTriangleHalfLength,
+ ptCenter.y + kComboBoxTriangleQuarterLength);
+ CFX_PointF pt2(ptCenter.x + kComboBoxTriangleHalfLength,
+ ptCenter.y + kComboBoxTriangleQuarterLength);
+ CFX_PointF pt3(ptCenter.x, ptCenter.y - kComboBoxTriangleQuarterLength);
+
+ if (IsFloatBigger(rectWnd.right - rectWnd.left,
+ kComboBoxTriangleHalfLength * 2) &&
+ IsFloatBigger(rectWnd.top - rectWnd.bottom,
+ kComboBoxTriangleHalfLength)) {
+ CFX_PathData path;
+ path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
+ path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
+ path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
+ path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
+
+ pDevice->DrawPath(&path, &mtUser2Device, nullptr,
+ PWL_DEFAULT_BLACKCOLOR.ToFXColor(GetTransparency()), 0,
+ FXFILL_ALTERNATE);
+ }
+}
+
+bool CPWL_CBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonDown(point, nFlag);
+
+ SetCapture();
+
+ if (CPWL_Wnd* pParent = GetParentWindow())
+ pParent->NotifyLButtonDown(this, point);
+
+ return true;
+}
+
+bool CPWL_CBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonUp(point, nFlag);
+
+ ReleaseCapture();
+
+ return true;
+}
+
+CPWL_ComboBox::CPWL_ComboBox() {}
+
+CPWL_ComboBox::~CPWL_ComboBox() {}
+
+ByteString CPWL_ComboBox::GetClassName() const {
+ return "CPWL_ComboBox";
+}
+
+void CPWL_ComboBox::OnCreate(CreateParams* pParamsToAdjust) {
+ pParamsToAdjust->dwFlags &= ~PWS_HSCROLL;
+ pParamsToAdjust->dwFlags &= ~PWS_VSCROLL;
+}
+
+void CPWL_ComboBox::OnDestroy() {
+ // Until cleanup takes place in the virtual destructor for CPWL_Wnd
+ // subclasses, implement the virtual OnDestroy method that does the
+ // cleanup first, then invokes the superclass OnDestroy ... gee,
+ // like a dtor would.
+ m_pList.Release();
+ m_pButton.Release();
+ m_pEdit.Release();
+ CPWL_Wnd::OnDestroy();
+}
+
+void CPWL_ComboBox::SetFocus() {
+ if (m_pEdit)
+ m_pEdit->SetFocus();
+}
+
+void CPWL_ComboBox::KillFocus() {
+ if (!SetPopup(false))
+ return;
+
+ CPWL_Wnd::KillFocus();
+}
+
+WideString CPWL_ComboBox::GetSelectedText() {
+ if (m_pEdit)
+ return m_pEdit->GetSelectedText();
+
+ return WideString();
+}
+
+void CPWL_ComboBox::ReplaceSelection(const WideString& text) {
+ if (m_pEdit)
+ m_pEdit->ReplaceSelection(text);
+}
+
+WideString CPWL_ComboBox::GetText() const {
+ if (m_pEdit) {
+ return m_pEdit->GetText();
+ }
+ return WideString();
+}
+
+void CPWL_ComboBox::SetText(const WideString& text) {
+ if (m_pEdit)
+ m_pEdit->SetText(text);
+}
+
+void CPWL_ComboBox::AddString(const WideString& str) {
+ if (m_pList)
+ m_pList->AddString(str);
+}
+
+int32_t CPWL_ComboBox::GetSelect() const {
+ return m_nSelectItem;
+}
+
+void CPWL_ComboBox::SetSelect(int32_t nItemIndex) {
+ if (m_pList)
+ m_pList->Select(nItemIndex);
+
+ m_pEdit->SetText(m_pList->GetText());
+ m_nSelectItem = nItemIndex;
+}
+
+void CPWL_ComboBox::SetEditSelection(int32_t nStartChar, int32_t nEndChar) {
+ if (m_pEdit)
+ m_pEdit->SetSelection(nStartChar, nEndChar);
+}
+
+void CPWL_ComboBox::GetEditSelection(int32_t& nStartChar,
+ int32_t& nEndChar) const {
+ nStartChar = -1;
+ nEndChar = -1;
+
+ if (m_pEdit)
+ m_pEdit->GetSelection(nStartChar, nEndChar);
+}
+
+void CPWL_ComboBox::ClearSelection() {
+ if (m_pEdit)
+ m_pEdit->ClearSelection();
+}
+
+void CPWL_ComboBox::CreateChildWnd(const CreateParams& cp) {
+ CreateEdit(cp);
+ CreateButton(cp);
+ CreateListBox(cp);
+}
+
+void CPWL_ComboBox::CreateEdit(const CreateParams& cp) {
+ if (m_pEdit)
+ return;
+
+ m_pEdit = new CPWL_Edit();
+ m_pEdit->AttachFFLData(m_pFormFiller.Get());
+
+ CreateParams ecp = cp;
+ ecp.pParentWnd = this;
+ ecp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PES_CENTER |
+ PES_AUTOSCROLL | PES_UNDO;
+
+ if (HasFlag(PWS_AUTOFONTSIZE))
+ ecp.dwFlags |= PWS_AUTOFONTSIZE;
+
+ if (!HasFlag(PCBS_ALLOWCUSTOMTEXT))
+ ecp.dwFlags |= PWS_READONLY;
+
+ ecp.rcRectWnd = CFX_FloatRect();
+ ecp.dwBorderWidth = 0;
+ ecp.nBorderStyle = BorderStyle::SOLID;
+ m_pEdit->Create(ecp);
+}
+
+void CPWL_ComboBox::CreateButton(const CreateParams& cp) {
+ if (m_pButton)
+ return;
+
+ m_pButton = new CPWL_CBButton;
+
+ CreateParams bcp = cp;
+ bcp.pParentWnd = this;
+ bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND;
+ bcp.sBackgroundColor = CFX_Color(CFX_Color::kRGB, 220.0f / 255.0f,
+ 220.0f / 255.0f, 220.0f / 255.0f);
+ bcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
+ bcp.dwBorderWidth = 2;
+ bcp.nBorderStyle = BorderStyle::BEVELED;
+ bcp.eCursorType = FXCT_ARROW;
+ m_pButton->Create(bcp);
+}
+
+void CPWL_ComboBox::CreateListBox(const CreateParams& cp) {
+ if (m_pList)
+ return;
+
+ m_pList = new CPWL_CBListBox();
+ m_pList->AttachFFLData(m_pFormFiller.Get());
+
+ CreateParams lcp = cp;
+ lcp.pParentWnd = this;
+ lcp.dwFlags =
+ PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PLBS_HOVERSEL | PWS_VSCROLL;
+ lcp.nBorderStyle = BorderStyle::SOLID;
+ lcp.dwBorderWidth = 1;
+ lcp.eCursorType = FXCT_ARROW;
+ lcp.rcRectWnd = CFX_FloatRect();
+
+ lcp.fFontSize =
+ (cp.dwFlags & PWS_AUTOFONTSIZE) ? kComboBoxDefaultFontSize : cp.fFontSize;
+
+ if (cp.sBorderColor.nColorType == CFX_Color::kTransparent)
+ lcp.sBorderColor = PWL_DEFAULT_BLACKCOLOR;
+
+ if (cp.sBackgroundColor.nColorType == CFX_Color::kTransparent)
+ lcp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
+
+ m_pList->Create(lcp);
+}
+
+bool CPWL_ComboBox::RePosChildWnd() {
+ ObservedPtr thisObserved(this);
+
+ const CFX_FloatRect rcClient = GetClientRect();
+ if (m_bPopup) {
+ const float fOldWindowHeight = m_rcOldWindow.Height();
+ const float fOldClientHeight = fOldWindowHeight - GetBorderWidth() * 2;
+
+ CFX_FloatRect rcList = CPWL_Wnd::GetWindowRect();
+ CFX_FloatRect rcButton = rcClient;
+ rcButton.left =
+ std::max(rcButton.right - kDefaultButtonWidth, rcClient.left);
+ CFX_FloatRect rcEdit = rcClient;
+ rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left);
+ if (m_bBottom) {
+ rcButton.bottom = rcButton.top - fOldClientHeight;
+ rcEdit.bottom = rcEdit.top - fOldClientHeight;
+ rcList.top -= fOldWindowHeight;
+ } else {
+ rcButton.top = rcButton.bottom + fOldClientHeight;
+ rcEdit.top = rcEdit.bottom + fOldClientHeight;
+ rcList.bottom += fOldWindowHeight;
+ }
+
+ if (m_pButton) {
+ m_pButton->Move(rcButton, true, false);
+ if (!thisObserved)
+ return false;
+ }
+
+ if (m_pEdit) {
+ m_pEdit->Move(rcEdit, true, false);
+ if (!thisObserved)
+ return false;
+ }
+
+ if (m_pList) {
+ if (!m_pList->SetVisible(true) || !thisObserved)
+ return false;
+
+ if (!m_pList->Move(rcList, true, false) || !thisObserved)
+ return false;
+
+ m_pList->ScrollToListItem(m_nSelectItem);
+ if (!thisObserved)
+ return false;
+ }
+ return true;
+ }
+
+ CFX_FloatRect rcButton = rcClient;
+ rcButton.left = std::max(rcButton.right - kDefaultButtonWidth, rcClient.left);
+
+ if (m_pButton) {
+ m_pButton->Move(rcButton, true, false);
+ if (!thisObserved)
+ return false;
+ }
+
+ CFX_FloatRect rcEdit = rcClient;
+ rcEdit.right = std::max(rcButton.left - 1.0f, rcEdit.left);
+
+ if (m_pEdit) {
+ m_pEdit->Move(rcEdit, true, false);
+ if (!thisObserved)
+ return false;
+ }
+
+ if (m_pList) {
+ m_pList->SetVisible(false);
+ if (!thisObserved)
+ return false;
+ }
+
+ return true;
+}
+
+void CPWL_ComboBox::SelectAll() {
+ if (m_pEdit && HasFlag(PCBS_ALLOWCUSTOMTEXT))
+ m_pEdit->SelectAll();
+}
+
+CFX_FloatRect CPWL_ComboBox::GetFocusRect() const {
+ return CFX_FloatRect();
+}
+
+bool CPWL_ComboBox::SetPopup(bool bPopup) {
+ if (!m_pList)
+ return true;
+ if (bPopup == m_bPopup)
+ return true;
+ float fListHeight = m_pList->GetContentRect().Height();
+ if (!IsFloatBigger(fListHeight, 0.0f))
+ return true;
+
+ if (!bPopup) {
+ m_bPopup = bPopup;
+ return Move(m_rcOldWindow, true, true);
+ }
+
+ if (!m_pFillerNotify)
+ return true;
+
+ ObservedPtr thisObserved(this);
+
+#ifdef PDF_ENABLE_XFA
+ if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), 0))
+ return !!thisObserved;
+ if (!thisObserved)
+ return false;
+#endif // PDF_ENABLE_XFA
+
+ float fBorderWidth = m_pList->GetBorderWidth() * 2;
+ float fPopupMin = 0.0f;
+ if (m_pList->GetCount() > 3)
+ fPopupMin = m_pList->GetFirstHeight() * 3 + fBorderWidth;
+ float fPopupMax = fListHeight + fBorderWidth;
+
+ bool bBottom;
+ float fPopupRet;
+ m_pFillerNotify->QueryWherePopup(GetAttachedData(), fPopupMin, fPopupMax,
+ &bBottom, &fPopupRet);
+ if (!IsFloatBigger(fPopupRet, 0.0f))
+ return true;
+
+ m_rcOldWindow = CPWL_Wnd::GetWindowRect();
+ m_bPopup = bPopup;
+ m_bBottom = bBottom;
+
+ CFX_FloatRect rcWindow = m_rcOldWindow;
+ if (bBottom)
+ rcWindow.bottom -= fPopupRet;
+ else
+ rcWindow.top += fPopupRet;
+
+ if (!Move(rcWindow, true, true))
+ return false;
+
+#ifdef PDF_ENABLE_XFA
+ m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), 0);
+ if (!thisObserved)
+ return false;
+#endif // PDF_ENABLE_XFA
+
+ return !!thisObserved;
+}
+
+bool CPWL_ComboBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
+ if (!m_pList)
+ return false;
+ if (!m_pEdit)
+ return false;
+
+ m_nSelectItem = -1;
+
+ switch (nChar) {
+ case FWL_VKEY_Up:
+ if (m_pList->GetCurSel() > 0) {
+#ifdef PDF_ENABLE_XFA
+ if (m_pFillerNotify) {
+ if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
+ return false;
+ if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
+ return false;
+ }
+#endif // PDF_ENABLE_XFA
+ if (m_pList->IsMovementKey(nChar)) {
+ if (m_pList->OnMovementKeyDown(nChar, nFlag))
+ return false;
+ SetSelectText();
+ }
+ }
+ return true;
+ case FWL_VKEY_Down:
+ if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
+#ifdef PDF_ENABLE_XFA
+ if (m_pFillerNotify) {
+ if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
+ return false;
+ if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
+ return false;
+ }
+#endif // PDF_ENABLE_XFA
+ if (m_pList->IsMovementKey(nChar)) {
+ if (m_pList->OnMovementKeyDown(nChar, nFlag))
+ return false;
+ SetSelectText();
+ }
+ }
+ return true;
+ }
+
+ if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
+ return m_pEdit->OnKeyDown(nChar, nFlag);
+
+ return false;
+}
+
+bool CPWL_ComboBox::OnChar(uint16_t nChar, uint32_t nFlag) {
+ if (!m_pList)
+ return false;
+
+ if (!m_pEdit)
+ return false;
+
+ m_nSelectItem = -1;
+ if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
+ return m_pEdit->OnChar(nChar, nFlag);
+
+#ifdef PDF_ENABLE_XFA
+ if (m_pFillerNotify) {
+ if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), nFlag))
+ return false;
+ if (m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), nFlag))
+ return false;
+ }
+#endif // PDF_ENABLE_XFA
+ if (!m_pList->IsChar(nChar, nFlag))
+ return false;
+ return m_pList->OnCharNotify(nChar, nFlag);
+}
+
+void CPWL_ComboBox::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
+ if (child == m_pButton) {
+ SetPopup(!m_bPopup);
+ // Note, |this| may no longer be viable at this point. If more work needs to
+ // be done, check the return value of SetPopup().
+ }
+}
+
+void CPWL_ComboBox::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
+ if (!m_pEdit || !m_pList || child != m_pList)
+ return;
+
+ SetSelectText();
+ SelectAll();
+ m_pEdit->SetFocus();
+ SetPopup(false);
+ // Note, |this| may no longer be viable at this point. If more work needs to
+ // be done, check the return value of SetPopup().
+}
+
+bool CPWL_ComboBox::IsPopup() const {
+ return m_bPopup;
+}
+
+void CPWL_ComboBox::SetSelectText() {
+ m_pEdit->SelectAll();
+ m_pEdit->ReplaceSel(m_pList->GetText());
+ m_pEdit->SelectAll();
+ m_nSelectItem = m_pList->GetCurSel();
+}
+
+void CPWL_ComboBox::SetFillerNotify(IPWL_Filler_Notify* pNotify) {
+ m_pFillerNotify = pNotify;
+
+ if (m_pEdit)
+ m_pEdit->SetFillerNotify(pNotify);
+
+ if (m_pList)
+ m_pList->SetFillerNotify(pNotify);
+}
diff --git a/fpdfsdk/pwl/cpwl_combo_box.h b/fpdfsdk/pwl/cpwl_combo_box.h
new file mode 100644
index 0000000..6db7213
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_combo_box.h
@@ -0,0 +1,103 @@
+// Copyright 2014 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_PWL_CPWL_COMBO_BOX_H_
+#define FPDFSDK_PWL_CPWL_COMBO_BOX_H_
+
+#include <memory>
+
+#include "core/fxcrt/unowned_ptr.h"
+#include "fpdfsdk/pwl/cpwl_edit.h"
+#include "fpdfsdk/pwl/cpwl_list_box.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+class CPWL_CBListBox : public CPWL_ListBox {
+ public:
+ CPWL_CBListBox() {}
+ ~CPWL_CBListBox() override {}
+
+ // CPWL_ListBox
+ bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
+
+ bool IsMovementKey(uint16_t nChar) const;
+ bool OnMovementKeyDown(uint16_t nChar, uint32_t nFlag);
+ bool IsChar(uint16_t nChar, uint32_t nFlag) const;
+ bool OnCharNotify(uint16_t nChar, uint32_t nFlag);
+};
+
+class CPWL_CBButton : public CPWL_Wnd {
+ public:
+ CPWL_CBButton() {}
+ ~CPWL_CBButton() override {}
+
+ // CPWL_Wnd
+ void DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) override;
+ bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
+};
+
+class CPWL_ComboBox : public CPWL_Wnd {
+ public:
+ CPWL_ComboBox();
+ ~CPWL_ComboBox() override;
+
+ CPWL_Edit* GetEdit() const { return m_pEdit.Get(); }
+
+ // CPWL_Wnd:
+ ByteString GetClassName() const override;
+ void OnCreate(CreateParams* pParamsToAdjust) override;
+ void OnDestroy() override;
+ bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override;
+ bool OnChar(uint16_t nChar, uint32_t nFlag) override;
+ void NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) override;
+ void NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) override;
+ void CreateChildWnd(const CreateParams& cp) override;
+ bool RePosChildWnd() override;
+ CFX_FloatRect GetFocusRect() const override;
+ void SetFocus() override;
+ void KillFocus() override;
+ WideString GetSelectedText() override;
+ void ReplaceSelection(const WideString& text) override;
+
+ void SetFillerNotify(IPWL_Filler_Notify* pNotify);
+
+ WideString GetText() const;
+ void SetText(const WideString& text);
+ void AddString(const WideString& str);
+ int32_t GetSelect() const;
+ void SetSelect(int32_t nItemIndex);
+
+ void SetEditSelection(int32_t nStartChar, int32_t nEndChar);
+ void GetEditSelection(int32_t& nStartChar, int32_t& nEndChar) const;
+ void ClearSelection();
+ void SelectAll();
+ bool IsPopup() const;
+
+ void SetSelectText();
+
+ void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; }
+
+ private:
+ void CreateEdit(const CreateParams& cp);
+ void CreateButton(const CreateParams& cp);
+ void CreateListBox(const CreateParams& cp);
+
+ // Returns |true| iff this instance is still allocated.
+ bool SetPopup(bool bPopup);
+
+ UnownedPtr<CPWL_Edit> m_pEdit;
+ UnownedPtr<CPWL_CBButton> m_pButton;
+ UnownedPtr<CPWL_CBListBox> m_pList;
+ CFX_FloatRect m_rcOldWindow;
+ bool m_bPopup = false;
+ bool m_bBottom = true;
+ int32_t m_nSelectItem = -1;
+ UnownedPtr<IPWL_Filler_Notify> m_pFillerNotify;
+ UnownedPtr<CFFL_FormFiller> m_pFormFiller;
+};
+
+#endif // FPDFSDK_PWL_CPWL_COMBO_BOX_H_
diff --git a/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp b/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp
new file mode 100644
index 0000000..9fd8eec
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp
@@ -0,0 +1,348 @@
+// 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.
+
+#include "fpdfsdk/cba_annotiterator.h"
+#include "fpdfsdk/cpdfsdk_annot.h"
+#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
+#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
+#include "fpdfsdk/pwl/cpwl_combo_box.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "testing/embedder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class CPWLComboBoxEditEmbeddertest : public EmbedderTest {
+ protected:
+ void SetUp() override {
+ EmbedderTest::SetUp();
+ CreateAndInitializeFormComboboxPDF();
+ }
+
+ void TearDown() override {
+ UnloadPage(GetPage());
+ EmbedderTest::TearDown();
+ }
+
+ void CreateAndInitializeFormComboboxPDF() {
+ EXPECT_TRUE(OpenDocument("combobox_form.pdf"));
+ m_page = LoadPage(0);
+ ASSERT_TRUE(m_page);
+
+ m_pFormFillEnv = static_cast<CPDFSDK_FormFillEnvironment*>(form_handle());
+ CBA_AnnotIterator iter(m_pFormFillEnv->GetPageView(0),
+ CPDF_Annot::Subtype::WIDGET);
+
+ // User editable combobox.
+ m_pAnnotEditable = iter.GetFirstAnnot();
+ ASSERT_TRUE(m_pAnnotEditable);
+ ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnotEditable->GetAnnotSubtype());
+
+ // Normal combobox with pre-selected value.
+ m_pAnnotNormal = iter.GetNextAnnot(m_pAnnotEditable);
+ ASSERT_TRUE(m_pAnnotNormal);
+ ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnotNormal->GetAnnotSubtype());
+
+ // Read-only combobox.
+ CPDFSDK_Annot* pAnnotReadOnly = iter.GetNextAnnot(m_pAnnotNormal);
+ CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot();
+ ASSERT_EQ(pAnnotReadOnly, pLastAnnot);
+ }
+
+ void FormFillerAndWindowSetup(CPDFSDK_Annot* pAnnotCombobox) {
+ CFFL_InteractiveFormFiller* pInteractiveFormFiller =
+ m_pFormFillEnv->GetInteractiveFormFiller();
+ {
+ CPDFSDK_Annot::ObservedPtr pObserved(pAnnotCombobox);
+ EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0));
+ }
+
+ m_pFormFiller =
+ pInteractiveFormFiller->GetFormFiller(pAnnotCombobox, false);
+ ASSERT_TRUE(m_pFormFiller);
+
+ CPWL_Wnd* pWindow =
+ m_pFormFiller->GetPDFWindow(m_pFormFillEnv->GetPageView(0), false);
+ ASSERT_TRUE(pWindow);
+ ASSERT_EQ("CPWL_ComboBox", pWindow->GetClassName());
+ m_pComboBox = static_cast<CPWL_ComboBox*>(pWindow);
+ }
+
+ void TypeTextIntoTextField(int num_chars) {
+ // Type text starting with 'A' to as many chars as specified by |num_chars|.
+ for (int i = 0; i < num_chars; ++i) {
+ EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(),
+ i + 'A', 0));
+ }
+ }
+
+ FPDF_PAGE GetPage() const { return m_page; }
+ CPWL_ComboBox* GetCPWLComboBox() const { return m_pComboBox; }
+ CFFL_FormFiller* GetCFFLFormFiller() const { return m_pFormFiller; }
+ CPDFSDK_Annot* GetCPDFSDKAnnotNormal() const { return m_pAnnotNormal; }
+ CPDFSDK_Annot* GetCPDFSDKAnnotUserEditable() const {
+ return m_pAnnotEditable;
+ }
+ CPDFSDK_FormFillEnvironment* GetCPDFSDKFormFillEnv() const {
+ return m_pFormFillEnv;
+ }
+
+ private:
+ FPDF_PAGE m_page;
+ CPWL_ComboBox* m_pComboBox;
+ CFFL_FormFiller* m_pFormFiller;
+ CPDFSDK_Annot* m_pAnnotNormal;
+ CPDFSDK_Annot* m_pAnnotEditable;
+ CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
+};
+
+TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextEmptyAndBasicNormal) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotNormal());
+
+ // Automatically pre-filled with "Banana".
+ EXPECT_FALSE(GetCPWLComboBox()->GetText().IsEmpty());
+ EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetText().c_str());
+
+ // Check that selection is intially empty, then select entire word.
+ EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
+ GetCPWLComboBox()->SetSelectText();
+ EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ // Select other options.
+ GetCPWLComboBox()->SetSelect(0);
+ EXPECT_STREQ(L"Apple", GetCPWLComboBox()->GetSelectedText().c_str());
+ GetCPWLComboBox()->SetSelect(2);
+ EXPECT_STREQ(L"Cherry", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ // Verify that combobox text cannot be edited.
+ EXPECT_FALSE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotNormal(), 'a', 0));
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextFragmentsNormal) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotNormal());
+ EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(0, 0);
+ EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
+
+ GetCPWLComboBox()->SetEditSelection(0, 1);
+ EXPECT_STREQ(L"B", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(0, -1);
+ EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(-8, -1);
+ EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
+
+ GetCPWLComboBox()->SetEditSelection(4, 1);
+ EXPECT_STREQ(L"ana", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(1, 4);
+ EXPECT_STREQ(L"ana", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(5, 6);
+ EXPECT_STREQ(L"a", GetCPWLComboBox()->GetSelectedText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextEmptyAndBasicEditable) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty());
+
+ // Check selection is intially empty, then select a provided option.
+ EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
+ GetCPWLComboBox()->SetSelect(0);
+ GetCPWLComboBox()->SetSelectText();
+ EXPECT_STREQ(L"Foo", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ // Select another option and then select last char of that option.
+ GetCPWLComboBox()->SetSelect(1);
+ EXPECT_STREQ(L"Bar", GetCPWLComboBox()->GetSelectedText().c_str());
+ GetCPWLComboBox()->SetEditSelection(2, 3);
+ EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ // Type into editable combobox text field and select new text.
+ EXPECT_TRUE(
+ GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'a', 0));
+ EXPECT_TRUE(
+ GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'b', 0));
+ EXPECT_TRUE(
+ GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'c', 0));
+
+ EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
+ GetCPWLComboBox()->SetEditSelection(0, 5);
+ EXPECT_STREQ(L"Baabc", GetCPWLComboBox()->GetSelectedText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextFragmentsEditable) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(50);
+
+ GetCPWLComboBox()->SetEditSelection(0, 0);
+ EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
+
+ GetCPWLComboBox()->SetEditSelection(0, 1);
+ EXPECT_STREQ(L"A", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(0, -1);
+ EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(-8, -1);
+ EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
+
+ GetCPWLComboBox()->SetEditSelection(23, 12);
+ EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(12, 23);
+ EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(49, 50);
+ EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->SetEditSelection(49, 55);
+ EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEntireTextSelection) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(50);
+
+ GetCPWLComboBox()->SetEditSelection(0, -1);
+ EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->ReplaceSelection(L"");
+ EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionMiddle) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(50);
+
+ GetCPWLComboBox()->SetEditSelection(12, 23);
+ EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->ReplaceSelection(L"");
+ EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionLeft) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(50);
+
+ GetCPWLComboBox()->SetEditSelection(0, 5);
+ EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->ReplaceSelection(L"");
+ EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionRight) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(50);
+
+ GetCPWLComboBox()->SetEditSelection(45, 50);
+ EXPECT_STREQ(L"nopqr", GetCPWLComboBox()->GetSelectedText().c_str());
+
+ GetCPWLComboBox()->ReplaceSelection(L"");
+ EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm",
+ GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEmptyTextSelection) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(50);
+
+ GetCPWLComboBox()->ReplaceSelection(L"");
+ EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest, InsertTextInEmptyEditableComboBox) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ GetCPWLComboBox()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest,
+ InsertTextInPopulatedEditableComboBoxLeft) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(10);
+
+ // Move cursor to beginning of user-editable combobox text field.
+ EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotUserEditable(),
+ FWL_VKEY_Home, 0));
+
+ GetCPWLComboBox()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest,
+ InsertTextInPopulatedEditableComboBoxMiddle) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(10);
+
+ // Move cursor to middle of user-editable combobox text field.
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotUserEditable(),
+ FWL_VKEY_Left, 0));
+ }
+
+ GetCPWLComboBox()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest,
+ InsertTextInPopulatedEditableComboBoxRight) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(10);
+
+ GetCPWLComboBox()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(10);
+
+ GetCPWLComboBox()->SetEditSelection(0, -1);
+ EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLComboBox()->GetSelectedText().c_str());
+ GetCPWLComboBox()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(10);
+
+ GetCPWLComboBox()->SetEditSelection(0, 5);
+ EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str());
+ GetCPWLComboBox()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"HelloFGHIJ", GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(10);
+
+ GetCPWLComboBox()->SetEditSelection(2, 7);
+ EXPECT_STREQ(L"CDEFG", GetCPWLComboBox()->GetSelectedText().c_str());
+ GetCPWLComboBox()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"ABHelloHIJ", GetCPWLComboBox()->GetText().c_str());
+}
+
+TEST_F(CPWLComboBoxEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
+ TypeTextIntoTextField(10);
+
+ GetCPWLComboBox()->SetEditSelection(5, 10);
+ EXPECT_STREQ(L"FGHIJ", GetCPWLComboBox()->GetSelectedText().c_str());
+ GetCPWLComboBox()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"ABCDEHello", GetCPWLComboBox()->GetText().c_str());
+}
diff --git a/fpdfsdk/pwl/cpwl_edit.cpp b/fpdfsdk/pwl/cpwl_edit.cpp
new file mode 100644
index 0000000..6c867ca
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_edit.cpp
@@ -0,0 +1,726 @@
+// Copyright 2014 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/pwl/cpwl_edit.h"
+
+#include <algorithm>
+#include <memory>
+#include <sstream>
+#include <vector>
+
+#include "core/fpdfapi/font/cpdf_font.h"
+#include "core/fpdfdoc/cpvt_word.h"
+#include "core/fxcrt/fx_safe_types.h"
+#include "core/fxcrt/xml/cxml_content.h"
+#include "core/fxcrt/xml/cxml_element.h"
+#include "core/fxge/cfx_graphstatedata.h"
+#include "core/fxge/cfx_pathdata.h"
+#include "core/fxge/cfx_renderdevice.h"
+#include "core/fxge/fx_font.h"
+#include "fpdfsdk/pwl/cpwl_caret.h"
+#include "fpdfsdk/pwl/cpwl_edit_ctrl.h"
+#include "fpdfsdk/pwl/cpwl_edit_impl.h"
+#include "fpdfsdk/pwl/cpwl_font_map.h"
+#include "fpdfsdk/pwl/cpwl_scroll_bar.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "public/fpdf_fwlevent.h"
+#include "third_party/base/stl_util.h"
+
+CPWL_Edit::CPWL_Edit() : m_bFocus(false) {}
+
+CPWL_Edit::~CPWL_Edit() {
+ ASSERT(!m_bFocus);
+}
+
+ByteString CPWL_Edit::GetClassName() const {
+ return PWL_CLASSNAME_EDIT;
+}
+
+void CPWL_Edit::SetText(const WideString& csText) {
+ WideString swText = csText;
+ if (!HasFlag(PES_RICH)) {
+ m_pEdit->SetText(swText);
+ return;
+ }
+
+ ByteString sValue = ByteString::FromUnicode(swText);
+ std::unique_ptr<CXML_Element> pXML(
+ CXML_Element::Parse(sValue.c_str(), sValue.GetLength()));
+ if (!pXML) {
+ m_pEdit->SetText(swText);
+ return;
+ }
+ swText.clear();
+
+ bool bFirst = true;
+ size_t nCount = pXML->CountChildren();
+ for (size_t i = 0; i < nCount; ++i) {
+ CXML_Element* pSubElement = ToElement(pXML->GetChild(i));
+ if (!pSubElement || !pSubElement->GetTagName().EqualNoCase("p"))
+ continue;
+
+ WideString swSection;
+ size_t nSubChild = pSubElement->CountChildren();
+ for (size_t j = 0; j < nSubChild; ++j) {
+ CXML_Content* pSubContent = ToContent(pSubElement->GetChild(j));
+ if (pSubContent)
+ swSection += pSubContent->m_Content;
+ }
+ if (bFirst)
+ bFirst = false;
+ else
+ swText += FWL_VKEY_Return;
+ swText += swSection;
+ }
+
+ m_pEdit->SetText(swText);
+}
+
+bool CPWL_Edit::RePosChildWnd() {
+ if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
+ CFX_FloatRect rcWindow = m_rcOldWindow;
+ CFX_FloatRect rcVScroll =
+ CFX_FloatRect(rcWindow.right, rcWindow.bottom,
+ rcWindow.right + PWL_SCROLLBAR_WIDTH, rcWindow.top);
+
+ ObservedPtr thisObserved(this);
+
+ pVSB->Move(rcVScroll, true, false);
+ if (!thisObserved)
+ return false;
+ }
+
+ if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW)) {
+ CFX_FloatRect rect = GetClientRect();
+ if (!rect.IsEmpty()) {
+ // +1 for caret beside border
+ rect.Inflate(1.0f, 1.0f);
+ rect.Normalize();
+ }
+ m_pEditCaret->SetClipRect(rect);
+ }
+
+ return CPWL_EditCtrl::RePosChildWnd();
+}
+
+CFX_FloatRect CPWL_Edit::GetClientRect() const {
+ float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth());
+ CFX_FloatRect rcClient = GetWindowRect().GetDeflated(width, width);
+ if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
+ if (pVSB->IsVisible()) {
+ rcClient.right -= PWL_SCROLLBAR_WIDTH;
+ }
+ }
+
+ return rcClient;
+}
+
+void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, bool bPaint) {
+ m_pEdit->SetAlignmentV((int32_t)nFormat, bPaint);
+}
+
+bool CPWL_Edit::CanSelectAll() const {
+ return GetSelectWordRange() != m_pEdit->GetWholeWordRange();
+}
+
+bool CPWL_Edit::CanCopy() const {
+ return !HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) &&
+ m_pEdit->IsSelected();
+}
+
+bool CPWL_Edit::CanCut() const {
+ return CanCopy() && !IsReadOnly();
+}
+void CPWL_Edit::CutText() {
+ if (!CanCut())
+ return;
+ m_pEdit->ClearSelection();
+}
+
+void CPWL_Edit::OnCreated() {
+ CPWL_EditCtrl::OnCreated();
+
+ if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
+ pScroll->RemoveFlag(PWS_AUTOTRANSPARENT);
+ pScroll->SetTransparency(255);
+ }
+
+ SetParamByFlag();
+
+ m_rcOldWindow = GetWindowRect();
+
+ m_pEdit->SetOperationNotify(this);
+}
+
+void CPWL_Edit::SetParamByFlag() {
+ if (HasFlag(PES_RIGHT)) {
+ m_pEdit->SetAlignmentH(2, false);
+ } else if (HasFlag(PES_MIDDLE)) {
+ m_pEdit->SetAlignmentH(1, false);
+ } else {
+ m_pEdit->SetAlignmentH(0, false);
+ }
+
+ if (HasFlag(PES_BOTTOM)) {
+ m_pEdit->SetAlignmentV(2, false);
+ } else if (HasFlag(PES_CENTER)) {
+ m_pEdit->SetAlignmentV(1, false);
+ } else {
+ m_pEdit->SetAlignmentV(0, false);
+ }
+
+ if (HasFlag(PES_PASSWORD)) {
+ m_pEdit->SetPasswordChar('*', false);
+ }
+
+ m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), false);
+ m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), false);
+ m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), false);
+ m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), false);
+ m_pEdit->EnableUndo(HasFlag(PES_UNDO));
+
+ if (HasFlag(PES_TEXTOVERFLOW)) {
+ SetClipRect(CFX_FloatRect());
+ m_pEdit->SetTextOverflow(true, false);
+ } else {
+ if (m_pEditCaret) {
+ CFX_FloatRect rect = GetClientRect();
+ if (!rect.IsEmpty()) {
+ // +1 for caret beside border
+ rect.Inflate(1.0f, 1.0f);
+ rect.Normalize();
+ }
+ m_pEditCaret->SetClipRect(rect);
+ }
+ }
+}
+
+void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device);
+
+ CFX_FloatRect rcClient = GetClientRect();
+
+ int32_t nCharArray = m_pEdit->GetCharArray();
+ FX_SAFE_INT32 nCharArraySafe = nCharArray;
+ nCharArraySafe -= 1;
+ nCharArraySafe *= 2;
+
+ if (nCharArray > 0 && nCharArraySafe.IsValid()) {
+ switch (GetBorderStyle()) {
+ case BorderStyle::SOLID: {
+ CFX_GraphStateData gsd;
+ gsd.m_LineWidth = (float)GetBorderWidth();
+
+ CFX_PathData path;
+
+ for (int32_t i = 0; i < nCharArray - 1; i++) {
+ path.AppendPoint(
+ CFX_PointF(
+ rcClient.left +
+ ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
+ rcClient.bottom),
+ FXPT_TYPE::MoveTo, false);
+ path.AppendPoint(
+ CFX_PointF(
+ rcClient.left +
+ ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
+ rcClient.top),
+ FXPT_TYPE::LineTo, false);
+ }
+ if (!path.GetPoints().empty()) {
+ pDevice->DrawPath(&path, &mtUser2Device, &gsd, 0,
+ GetBorderColor().ToFXColor(255), FXFILL_ALTERNATE);
+ }
+ break;
+ }
+ case BorderStyle::DASH: {
+ CFX_GraphStateData gsd;
+ gsd.m_LineWidth = (float)GetBorderWidth();
+
+ gsd.SetDashCount(2);
+ gsd.m_DashArray[0] = (float)GetBorderDash().nDash;
+ gsd.m_DashArray[1] = (float)GetBorderDash().nGap;
+ gsd.m_DashPhase = (float)GetBorderDash().nPhase;
+
+ CFX_PathData path;
+ for (int32_t i = 0; i < nCharArray - 1; i++) {
+ path.AppendPoint(
+ CFX_PointF(
+ rcClient.left +
+ ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
+ rcClient.bottom),
+ FXPT_TYPE::MoveTo, false);
+ path.AppendPoint(
+ CFX_PointF(
+ rcClient.left +
+ ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
+ rcClient.top),
+ FXPT_TYPE::LineTo, false);
+ }
+ if (!path.GetPoints().empty()) {
+ pDevice->DrawPath(&path, &mtUser2Device, &gsd, 0,
+ GetBorderColor().ToFXColor(255), FXFILL_ALTERNATE);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ CFX_FloatRect rcClip;
+ CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange();
+ CPVT_WordRange* pRange = nullptr;
+ if (!HasFlag(PES_TEXTOVERFLOW)) {
+ rcClip = GetClientRect();
+ pRange = &wrRange;
+ }
+
+ CFX_SystemHandler* pSysHandler = GetSystemHandler();
+ CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device, m_pEdit.get(),
+ GetTextColor().ToFXColor(GetTransparency()), rcClip,
+ CFX_PointF(), pRange, pSysHandler,
+ m_pFormFiller.Get());
+}
+
+bool CPWL_Edit::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonDown(point, nFlag);
+
+ if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) {
+ if (m_bMouseDown && !InvalidateRect(nullptr))
+ return true;
+
+ m_bMouseDown = true;
+ SetCapture();
+
+ m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ }
+
+ return true;
+}
+
+bool CPWL_Edit::OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonDblClk(point, nFlag);
+
+ if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) {
+ m_pEdit->SelectAll();
+ }
+
+ return true;
+}
+
+bool CPWL_Edit::OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) {
+ if (m_bMouseDown)
+ return false;
+
+ CPWL_Wnd::OnRButtonUp(point, nFlag);
+
+ if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point))
+ return true;
+
+ CFX_SystemHandler* pSH = GetSystemHandler();
+ if (!pSH)
+ return false;
+
+ SetFocus();
+
+ return false;
+}
+
+void CPWL_Edit::OnSetFocus() {
+ ObservedPtr observed_ptr(this);
+ SetEditCaret(true);
+ if (!observed_ptr)
+ return;
+
+ if (!IsReadOnly()) {
+ if (CPWL_Wnd::FocusHandlerIface* pFocusHandler = GetFocusHandler()) {
+ pFocusHandler->OnSetFocus(this);
+ if (!observed_ptr)
+ return;
+ }
+ }
+ m_bFocus = true;
+}
+
+void CPWL_Edit::OnKillFocus() {
+ ObservedPtr observed_ptr(this);
+
+ CPWL_ScrollBar* pScroll = GetVScrollBar();
+ if (pScroll && pScroll->IsVisible()) {
+ pScroll->SetVisible(false);
+ if (!observed_ptr)
+ return;
+
+ if (!Move(m_rcOldWindow, true, true))
+ return;
+ }
+
+ m_pEdit->SelectNone();
+ if (!observed_ptr)
+ return;
+
+ if (!SetCaret(false, CFX_PointF(), CFX_PointF()))
+ return;
+
+ SetCharSet(FX_CHARSET_ANSI);
+ m_bFocus = false;
+}
+
+void CPWL_Edit::SetCharSpace(float fCharSpace) {
+ m_pEdit->SetCharSpace(fCharSpace);
+}
+
+CPVT_WordRange CPWL_Edit::GetSelectWordRange() const {
+ if (!m_pEdit->IsSelected())
+ return CPVT_WordRange();
+
+ int32_t nStart = -1;
+ int32_t nEnd = -1;
+
+ m_pEdit->GetSelection(nStart, nEnd);
+
+ CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart);
+ CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd);
+
+ return CPVT_WordRange(wpStart, wpEnd);
+}
+
+CFX_PointF CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord) {
+ CPWL_EditImpl_Iterator* pIterator = m_pEdit->GetIterator();
+ CPVT_WordPlace wpOld = pIterator->GetAt();
+ pIterator->SetAt(wpWord);
+
+ CFX_PointF pt;
+ CPVT_Word word;
+ if (pIterator->GetWord(word))
+ pt = CFX_PointF(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent);
+ pIterator->SetAt(wpOld);
+ return pt;
+}
+
+bool CPWL_Edit::IsTextFull() const {
+ return m_pEdit->IsTextFull();
+}
+
+float CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont,
+ const CFX_FloatRect& rcPlate,
+ int32_t nCharArray) {
+ if (!pFont || pFont->IsStandardFont())
+ return 0.0f;
+
+ FX_RECT rcBBox;
+ pFont->GetFontBBox(rcBBox);
+
+ CFX_FloatRect rcCell = rcPlate;
+ float xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width();
+ float ydiv = -rcCell.Height() * 1000.0f / rcBBox.Height();
+
+ return xdiv < ydiv ? xdiv : ydiv;
+}
+
+void CPWL_Edit::SetCharArray(int32_t nCharArray) {
+ if (!HasFlag(PES_CHARARRAY) || nCharArray <= 0)
+ return;
+
+ m_pEdit->SetCharArray(nCharArray);
+ m_pEdit->SetTextOverflow(true, true);
+
+ if (!HasFlag(PWS_AUTOFONTSIZE))
+ return;
+
+ IPVT_FontMap* pFontMap = GetFontMap();
+ if (!pFontMap)
+ return;
+
+ float fFontSize = GetCharArrayAutoFontSize(pFontMap->GetPDFFont(0),
+ GetClientRect(), nCharArray);
+ if (fFontSize <= 0.0f)
+ return;
+
+ m_pEdit->SetAutoFontSize(false, true);
+ m_pEdit->SetFontSize(fFontSize);
+}
+
+void CPWL_Edit::SetLimitChar(int32_t nLimitChar) {
+ m_pEdit->SetLimitChar(nLimitChar);
+}
+
+void CPWL_Edit::ReplaceSel(const WideString& wsText) {
+ m_pEdit->ClearSelection();
+ m_pEdit->InsertText(wsText, FX_CHARSET_Default);
+}
+
+CFX_FloatRect CPWL_Edit::GetFocusRect() const {
+ return CFX_FloatRect();
+}
+
+bool CPWL_Edit::IsVScrollBarVisible() const {
+ CPWL_ScrollBar* pScroll = GetVScrollBar();
+ return pScroll && pScroll->IsVisible();
+}
+
+bool CPWL_Edit::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
+ if (m_bMouseDown)
+ return true;
+
+ if (nChar == FWL_VKEY_Delete) {
+ if (m_pFillerNotify) {
+ WideString strChange;
+ WideString strChangeEx;
+
+ int nSelStart = 0;
+ int nSelEnd = 0;
+ GetSelection(nSelStart, nSelEnd);
+
+ if (nSelStart == nSelEnd)
+ nSelEnd = nSelStart + 1;
+
+ CPWL_Wnd::ObservedPtr thisObserved(this);
+
+ bool bRC;
+ bool bExit;
+ std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke(
+ GetAttachedData(), strChange, strChangeEx, nSelStart, nSelEnd, true,
+ nFlag);
+
+ if (!thisObserved)
+ return false;
+
+ if (!bRC)
+ return false;
+ if (bExit)
+ return false;
+ }
+ }
+
+ bool bRet = CPWL_EditCtrl::OnKeyDown(nChar, nFlag);
+
+ // In case of implementation swallow the OnKeyDown event.
+ if (IsProceedtoOnChar(nChar, nFlag))
+ return true;
+
+ return bRet;
+}
+
+// static
+bool CPWL_Edit::IsProceedtoOnChar(uint16_t nKeyCode, uint32_t nFlag) {
+ bool bCtrl = IsCTRLpressed(nFlag);
+ bool bAlt = IsALTpressed(nFlag);
+ if (bCtrl && !bAlt) {
+ // hot keys for edit control.
+ switch (nKeyCode) {
+ case 'C':
+ case 'V':
+ case 'X':
+ case 'A':
+ case 'Z':
+ return true;
+ default:
+ break;
+ }
+ }
+ // control characters.
+ switch (nKeyCode) {
+ case FWL_VKEY_Escape:
+ case FWL_VKEY_Back:
+ case FWL_VKEY_Return:
+ case FWL_VKEY_Space:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool CPWL_Edit::OnChar(uint16_t nChar, uint32_t nFlag) {
+ if (m_bMouseDown)
+ return true;
+
+ bool bRC = true;
+ bool bExit = false;
+
+ if (!IsCTRLpressed(nFlag)) {
+ if (m_pFillerNotify) {
+ WideString swChange;
+
+ int nSelStart = 0;
+ int nSelEnd = 0;
+ GetSelection(nSelStart, nSelEnd);
+
+ switch (nChar) {
+ case FWL_VKEY_Back:
+ if (nSelStart == nSelEnd)
+ nSelStart = nSelEnd - 1;
+ break;
+ case FWL_VKEY_Return:
+ break;
+ default:
+ swChange += nChar;
+ break;
+ }
+
+ CPWL_Wnd::ObservedPtr thisObserved(this);
+
+ WideString strChangeEx;
+ std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke(
+ GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, true,
+ nFlag);
+
+ if (!thisObserved)
+ return false;
+ }
+ }
+
+ if (!bRC)
+ return true;
+ if (bExit)
+ return false;
+
+ if (IPVT_FontMap* pFontMap = GetFontMap()) {
+ int32_t nOldCharSet = GetCharSet();
+ int32_t nNewCharSet =
+ pFontMap->CharSetFromUnicode(nChar, FX_CHARSET_Default);
+ if (nOldCharSet != nNewCharSet) {
+ SetCharSet(nNewCharSet);
+ }
+ }
+
+ return CPWL_EditCtrl::OnChar(nChar, nFlag);
+}
+
+bool CPWL_Edit::OnMouseWheel(short zDelta,
+ const CFX_PointF& point,
+ uint32_t nFlag) {
+ if (!HasFlag(PES_MULTILINE))
+ return false;
+
+ CFX_PointF ptScroll = GetScrollPos();
+ if (zDelta > 0)
+ ptScroll.y += GetFontSize();
+ else
+ ptScroll.y -= GetFontSize();
+ SetScrollPos(ptScroll);
+ return true;
+}
+
+void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace) {
+ if (HasFlag(PES_SPELLCHECK)) {
+ m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+ GetLatinWordsRange(place)));
+ }
+}
+
+void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace) {
+ if (HasFlag(PES_SPELLCHECK)) {
+ m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+ GetLatinWordsRange(place)));
+ }
+}
+
+void CPWL_Edit::OnDelete(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace) {
+ if (HasFlag(PES_SPELLCHECK)) {
+ m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+ GetLatinWordsRange(place)));
+ }
+}
+
+void CPWL_Edit::OnClear(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace) {
+ if (HasFlag(PES_SPELLCHECK)) {
+ m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+ GetLatinWordsRange(place)));
+ }
+}
+
+void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace) {
+ if (HasFlag(PES_SPELLCHECK)) {
+ m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+ GetLatinWordsRange(place)));
+ }
+}
+
+void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace) {
+ if (HasFlag(PES_SPELLCHECK)) {
+ m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+ GetLatinWordsRange(place)));
+ }
+}
+
+CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1,
+ const CPVT_WordRange& wr2) {
+ return CPVT_WordRange(std::min(wr1.BeginPos, wr2.BeginPos),
+ std::max(wr1.EndPos, wr2.EndPos));
+}
+
+CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CFX_PointF& point) const {
+ return GetSameWordsRange(m_pEdit->SearchWordPlace(point), true, false);
+}
+
+CPVT_WordRange CPWL_Edit::GetLatinWordsRange(
+ const CPVT_WordPlace& place) const {
+ return GetSameWordsRange(place, true, false);
+}
+
+#define PWL_ISARABICWORD(word) \
+ ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
+
+CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace& place,
+ bool bLatin,
+ bool bArabic) const {
+ CPVT_WordRange range;
+
+ CPWL_EditImpl_Iterator* pIterator = m_pEdit->GetIterator();
+ CPVT_Word wordinfo;
+ CPVT_WordPlace wpStart(place), wpEnd(place);
+ pIterator->SetAt(place);
+
+ if (bLatin) {
+ while (pIterator->NextWord()) {
+ if (!pIterator->GetWord(wordinfo) ||
+ !FX_EDIT_ISLATINWORD(wordinfo.Word)) {
+ break;
+ }
+
+ wpEnd = pIterator->GetAt();
+ }
+ } else if (bArabic) {
+ while (pIterator->NextWord()) {
+ if (!pIterator->GetWord(wordinfo) || !PWL_ISARABICWORD(wordinfo.Word))
+ break;
+
+ wpEnd = pIterator->GetAt();
+ }
+ }
+
+ pIterator->SetAt(place);
+
+ if (bLatin) {
+ do {
+ if (!pIterator->GetWord(wordinfo) ||
+ !FX_EDIT_ISLATINWORD(wordinfo.Word)) {
+ break;
+ }
+
+ wpStart = pIterator->GetAt();
+ } while (pIterator->PrevWord());
+ } else if (bArabic) {
+ do {
+ if (!pIterator->GetWord(wordinfo) || !PWL_ISARABICWORD(wordinfo.Word))
+ break;
+
+ wpStart = pIterator->GetAt();
+ } while (pIterator->PrevWord());
+ }
+
+ range.Set(wpStart, wpEnd);
+ return range;
+}
diff --git a/fpdfsdk/pwl/cpwl_edit.h b/fpdfsdk/pwl/cpwl_edit.h
new file mode 100644
index 0000000..3f9cd43
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_edit.h
@@ -0,0 +1,134 @@
+// Copyright 2014 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_PWL_CPWL_EDIT_H_
+#define FPDFSDK_PWL_CPWL_EDIT_H_
+
+#include <utility>
+
+#include "core/fpdfdoc/cpvt_wordrange.h"
+#include "core/fxcrt/unowned_ptr.h"
+#include "fpdfsdk/pwl/cpwl_edit_ctrl.h"
+
+#define PWL_CLASSNAME_EDIT "CPWL_Edit"
+
+class IPWL_Filler_Notify {
+ public:
+ virtual ~IPWL_Filler_Notify() {}
+
+ // Must write to |bBottom| and |fPopupRet|.
+ virtual void QueryWherePopup(CPWL_Wnd::PrivateData* pAttached,
+ float fPopupMin,
+ float fPopupMax,
+ bool* bBottom,
+ float* fPopupRet) = 0;
+ virtual std::pair<bool, bool> OnBeforeKeyStroke(
+ CPWL_Wnd::PrivateData* pAttached,
+ WideString& strChange,
+ const WideString& strChangeEx,
+ int nSelStart,
+ int nSelEnd,
+ bool bKeyDown,
+ uint32_t nFlag) = 0;
+#ifdef PDF_ENABLE_XFA
+ virtual bool OnPopupPreOpen(CPWL_Wnd::PrivateData* pAttached,
+ uint32_t nFlag) = 0;
+ virtual bool OnPopupPostOpen(CPWL_Wnd::PrivateData* pAttached,
+ uint32_t nFlag) = 0;
+#endif // PDF_ENABLE_XFA
+};
+
+class CPWL_Edit : public CPWL_EditCtrl {
+ public:
+ CPWL_Edit();
+ ~CPWL_Edit() override;
+
+ // CPWL_EditCtrl
+ ByteString GetClassName() const override;
+ void OnCreated() override;
+ bool RePosChildWnd() override;
+ CFX_FloatRect GetClientRect() const override;
+ void DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) override;
+ bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnRButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnMouseWheel(short zDelta,
+ const CFX_PointF& point,
+ uint32_t nFlag) override;
+ bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override;
+ bool OnChar(uint16_t nChar, uint32_t nFlag) override;
+ CFX_FloatRect GetFocusRect() const override;
+ void OnSetFocus() override;
+ void OnKillFocus() override;
+
+ void SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat = PEAV_TOP,
+ bool bPaint = true); // 0:top 1:bottom 2:center
+
+ void SetCharArray(int32_t nCharArray);
+ void SetLimitChar(int32_t nLimitChar);
+
+ void SetCharSpace(float fCharSpace);
+
+ bool CanSelectAll() const;
+ bool CanCopy() const;
+ bool CanCut() const;
+
+ void CutText();
+
+ void SetText(const WideString& csText);
+ void ReplaceSel(const WideString& csText);
+
+ bool IsTextFull() const;
+
+ static float GetCharArrayAutoFontSize(CPDF_Font* pFont,
+ const CFX_FloatRect& rcPlate,
+ int32_t nCharArray);
+
+ void SetFillerNotify(IPWL_Filler_Notify* pNotify) {
+ m_pFillerNotify = pNotify;
+ }
+
+ void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; }
+
+ void OnInsertWord(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace);
+ void OnInsertReturn(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace);
+ void OnBackSpace(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
+ void OnDelete(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
+ void OnClear(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace);
+ void OnInsertText(const CPVT_WordPlace& place,
+ const CPVT_WordPlace& oldplace);
+
+ private:
+ // In case of implementation swallow the OnKeyDown event. If the event is
+ // swallowed, implementation may do other unexpected things, which is not the
+ // control means to do.
+ static bool IsProceedtoOnChar(uint16_t nKeyCode, uint32_t nFlag);
+
+ CPVT_WordRange GetSelectWordRange() const;
+ bool IsVScrollBarVisible() const;
+ void SetParamByFlag();
+
+ float GetCharArrayAutoFontSize(int32_t nCharArray);
+ CFX_PointF GetWordRightBottomPoint(const CPVT_WordPlace& wpWord);
+
+ CPVT_WordRange CombineWordRange(const CPVT_WordRange& wr1,
+ const CPVT_WordRange& wr2);
+ CPVT_WordRange GetLatinWordsRange(const CFX_PointF& point) const;
+ CPVT_WordRange GetLatinWordsRange(const CPVT_WordPlace& place) const;
+ CPVT_WordRange GetSameWordsRange(const CPVT_WordPlace& place,
+ bool bLatin,
+ bool bArabic) const;
+
+ bool m_bFocus;
+ CFX_FloatRect m_rcOldWindow;
+ UnownedPtr<IPWL_Filler_Notify> m_pFillerNotify;
+ UnownedPtr<CFFL_FormFiller> m_pFormFiller;
+};
+
+#endif // FPDFSDK_PWL_CPWL_EDIT_H_
diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.cpp b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp
new file mode 100644
index 0000000..06b5ded
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp
@@ -0,0 +1,431 @@
+// Copyright 2014 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/pwl/cpwl_edit_ctrl.h"
+
+#include "core/fpdfdoc/cpvt_word.h"
+#include "core/fxge/fx_font.h"
+#include "fpdfsdk/pwl/cpwl_caret.h"
+#include "fpdfsdk/pwl/cpwl_edit_impl.h"
+#include "fpdfsdk/pwl/cpwl_font_map.h"
+#include "fpdfsdk/pwl/cpwl_scroll_bar.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "public/fpdf_fwlevent.h"
+
+CPWL_EditCtrl::CPWL_EditCtrl()
+ : m_pEdit(new CPWL_EditImpl),
+ m_pEditCaret(nullptr),
+ m_bMouseDown(false),
+ m_nCharSet(FX_CHARSET_Default) {}
+
+CPWL_EditCtrl::~CPWL_EditCtrl() {}
+
+void CPWL_EditCtrl::OnCreate(CreateParams* pParamsToAdjust) {
+ pParamsToAdjust->eCursorType = FXCT_VBEAM;
+}
+
+void CPWL_EditCtrl::OnCreated() {
+ SetFontSize(GetCreationParams().fFontSize);
+
+ m_pEdit->SetFontMap(GetFontMap());
+ m_pEdit->SetNotify(this);
+ m_pEdit->Initialize();
+}
+
+bool CPWL_EditCtrl::IsWndHorV() {
+ CFX_Matrix mt = GetWindowMatrix();
+ return mt.Transform(CFX_PointF(1, 1)).y == mt.Transform(CFX_PointF(0, 1)).y;
+}
+
+void CPWL_EditCtrl::SetCursor() {
+ if (IsValid()) {
+ if (CFX_SystemHandler* pSH = GetSystemHandler()) {
+ if (IsWndHorV())
+ pSH->SetCursor(FXCT_VBEAM);
+ else
+ pSH->SetCursor(FXCT_HBEAM);
+ }
+ }
+}
+
+WideString CPWL_EditCtrl::GetSelectedText() {
+ if (m_pEdit)
+ return m_pEdit->GetSelectedText();
+
+ return WideString();
+}
+
+void CPWL_EditCtrl::ReplaceSelection(const WideString& text) {
+ if (!m_pEdit)
+ return;
+
+ m_pEdit->ClearSelection();
+ m_pEdit->InsertText(text, FX_CHARSET_Default);
+}
+
+bool CPWL_EditCtrl::RePosChildWnd() {
+ m_pEdit->SetPlateRect(GetClientRect());
+ return true;
+}
+
+void CPWL_EditCtrl::SetScrollInfo(const PWL_SCROLL_INFO& info) {
+ if (CPWL_Wnd* pChild = GetVScrollBar())
+ pChild->SetScrollInfo(info);
+}
+
+void CPWL_EditCtrl::SetScrollPosition(float pos) {
+ if (CPWL_Wnd* pChild = GetVScrollBar())
+ pChild->SetScrollPosition(pos);
+}
+
+void CPWL_EditCtrl::ScrollWindowVertically(float pos) {
+ m_pEdit->SetScrollPos(CFX_PointF(m_pEdit->GetScrollPos().x, pos));
+}
+
+void CPWL_EditCtrl::CreateChildWnd(const CreateParams& cp) {
+ if (!IsReadOnly())
+ CreateEditCaret(cp);
+}
+
+void CPWL_EditCtrl::CreateEditCaret(const CreateParams& cp) {
+ if (m_pEditCaret)
+ return;
+
+ m_pEditCaret = new CPWL_Caret;
+ m_pEditCaret->SetInvalidRect(GetClientRect());
+
+ CreateParams ecp = cp;
+ ecp.pParentWnd = this;
+ ecp.dwFlags = PWS_CHILD | PWS_NOREFRESHCLIP;
+ ecp.dwBorderWidth = 0;
+ ecp.nBorderStyle = BorderStyle::SOLID;
+ ecp.rcRectWnd = CFX_FloatRect();
+
+ m_pEditCaret->Create(ecp);
+}
+
+void CPWL_EditCtrl::SetFontSize(float fFontSize) {
+ m_pEdit->SetFontSize(fFontSize);
+}
+
+float CPWL_EditCtrl::GetFontSize() const {
+ return m_pEdit->GetFontSize();
+}
+
+bool CPWL_EditCtrl::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
+ if (m_bMouseDown)
+ return true;
+
+ bool bRet = CPWL_Wnd::OnKeyDown(nChar, nFlag);
+
+ // FILTER
+ switch (nChar) {
+ default:
+ return false;
+ case FWL_VKEY_Delete:
+ case FWL_VKEY_Up:
+ case FWL_VKEY_Down:
+ case FWL_VKEY_Left:
+ case FWL_VKEY_Right:
+ case FWL_VKEY_Home:
+ case FWL_VKEY_End:
+ case FWL_VKEY_Insert:
+ case 'C':
+ case 'V':
+ case 'X':
+ case 'A':
+ case 'Z':
+ case 'c':
+ case 'v':
+ case 'x':
+ case 'a':
+ case 'z':
+ break;
+ }
+
+ if (nChar == FWL_VKEY_Delete && m_pEdit->IsSelected())
+ nChar = FWL_VKEY_Unknown;
+
+ switch (nChar) {
+ case FWL_VKEY_Delete:
+ Delete();
+ return true;
+ case FWL_VKEY_Insert:
+ if (IsSHIFTpressed(nFlag))
+ PasteText();
+ return true;
+ case FWL_VKEY_Up:
+ m_pEdit->OnVK_UP(IsSHIFTpressed(nFlag), false);
+ return true;
+ case FWL_VKEY_Down:
+ m_pEdit->OnVK_DOWN(IsSHIFTpressed(nFlag), false);
+ return true;
+ case FWL_VKEY_Left:
+ m_pEdit->OnVK_LEFT(IsSHIFTpressed(nFlag), false);
+ return true;
+ case FWL_VKEY_Right:
+ m_pEdit->OnVK_RIGHT(IsSHIFTpressed(nFlag), false);
+ return true;
+ case FWL_VKEY_Home:
+ m_pEdit->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ return true;
+ case FWL_VKEY_End:
+ m_pEdit->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ return true;
+ case FWL_VKEY_Unknown:
+ if (!IsSHIFTpressed(nFlag))
+ ClearSelection();
+ else
+ CutText();
+ return true;
+ default:
+ break;
+ }
+
+ return bRet;
+}
+
+bool CPWL_EditCtrl::OnChar(uint16_t nChar, uint32_t nFlag) {
+ if (m_bMouseDown)
+ return true;
+
+ CPWL_Wnd::OnChar(nChar, nFlag);
+
+ // FILTER
+ switch (nChar) {
+ case 0x0A:
+ case 0x1B:
+ return false;
+ default:
+ break;
+ }
+
+ bool bCtrl = IsCTRLpressed(nFlag);
+ bool bAlt = IsALTpressed(nFlag);
+ bool bShift = IsSHIFTpressed(nFlag);
+
+ uint16_t word = nChar;
+
+ if (bCtrl && !bAlt) {
+ switch (nChar) {
+ case 'C' - 'A' + 1:
+ CopyText();
+ return true;
+ case 'V' - 'A' + 1:
+ PasteText();
+ return true;
+ case 'X' - 'A' + 1:
+ CutText();
+ return true;
+ case 'A' - 'A' + 1:
+ SelectAll();
+ return true;
+ case 'Z' - 'A' + 1:
+ if (bShift)
+ Redo();
+ else
+ Undo();
+ return true;
+ default:
+ if (nChar < 32)
+ return false;
+ }
+ }
+
+ if (IsReadOnly())
+ return true;
+
+ if (m_pEdit->IsSelected() && word == FWL_VKEY_Back)
+ word = FWL_VKEY_Unknown;
+
+ ClearSelection();
+
+ switch (word) {
+ case FWL_VKEY_Back:
+ Backspace();
+ break;
+ case FWL_VKEY_Return:
+ InsertReturn();
+ break;
+ case FWL_VKEY_Unknown:
+ break;
+ default:
+ InsertWord(word, GetCharSet());
+ break;
+ }
+
+ return true;
+}
+
+bool CPWL_EditCtrl::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonDown(point, nFlag);
+
+ if (ClientHitTest(point)) {
+ if (m_bMouseDown && !InvalidateRect(nullptr))
+ return true;
+
+ m_bMouseDown = true;
+ SetCapture();
+
+ m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ }
+
+ return true;
+}
+
+bool CPWL_EditCtrl::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonUp(point, nFlag);
+
+ if (m_bMouseDown) {
+ // can receive keybord message
+ if (ClientHitTest(point) && !IsFocused())
+ SetFocus();
+
+ ReleaseCapture();
+ m_bMouseDown = false;
+ }
+
+ return true;
+}
+
+bool CPWL_EditCtrl::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnMouseMove(point, nFlag);
+
+ if (m_bMouseDown)
+ m_pEdit->OnMouseMove(point, false, false);
+
+ return true;
+}
+
+void CPWL_EditCtrl::SetEditCaret(bool bVisible) {
+ CFX_PointF ptHead;
+ CFX_PointF ptFoot;
+ if (bVisible)
+ GetCaretInfo(&ptHead, &ptFoot);
+
+ SetCaret(bVisible, ptHead, ptFoot);
+ // Note, |this| may no longer be viable at this point. If more work needs to
+ // be done, check the return value of SetCaret().
+}
+
+void CPWL_EditCtrl::GetCaretInfo(CFX_PointF* ptHead, CFX_PointF* ptFoot) const {
+ CPWL_EditImpl_Iterator* pIterator = m_pEdit->GetIterator();
+ pIterator->SetAt(m_pEdit->GetCaret());
+ CPVT_Word word;
+ CPVT_Line line;
+ if (pIterator->GetWord(word)) {
+ ptHead->x = word.ptWord.x + word.fWidth;
+ ptHead->y = word.ptWord.y + word.fAscent;
+ ptFoot->x = word.ptWord.x + word.fWidth;
+ ptFoot->y = word.ptWord.y + word.fDescent;
+ } else if (pIterator->GetLine(line)) {
+ ptHead->x = line.ptLine.x;
+ ptHead->y = line.ptLine.y + line.fLineAscent;
+ ptFoot->x = line.ptLine.x;
+ ptFoot->y = line.ptLine.y + line.fLineDescent;
+ }
+}
+
+bool CPWL_EditCtrl::SetCaret(bool bVisible,
+ const CFX_PointF& ptHead,
+ const CFX_PointF& ptFoot) {
+ if (!m_pEditCaret)
+ return true;
+
+ if (!IsFocused() || m_pEdit->IsSelected())
+ bVisible = false;
+
+ ObservedPtr thisObserved(this);
+ m_pEditCaret->SetCaret(bVisible, ptHead, ptFoot);
+ if (!thisObserved)
+ return false;
+
+ return true;
+}
+
+WideString CPWL_EditCtrl::GetText() const {
+ return m_pEdit->GetText();
+}
+
+void CPWL_EditCtrl::SetSelection(int32_t nStartChar, int32_t nEndChar) {
+ m_pEdit->SetSelection(nStartChar, nEndChar);
+}
+
+void CPWL_EditCtrl::GetSelection(int32_t& nStartChar, int32_t& nEndChar) const {
+ m_pEdit->GetSelection(nStartChar, nEndChar);
+}
+
+void CPWL_EditCtrl::ClearSelection() {
+ if (!IsReadOnly())
+ m_pEdit->ClearSelection();
+}
+
+void CPWL_EditCtrl::SelectAll() {
+ m_pEdit->SelectAll();
+}
+
+void CPWL_EditCtrl::SetScrollPos(const CFX_PointF& point) {
+ m_pEdit->SetScrollPos(point);
+}
+
+CFX_PointF CPWL_EditCtrl::GetScrollPos() const {
+ return m_pEdit->GetScrollPos();
+}
+
+void CPWL_EditCtrl::CopyText() {}
+
+void CPWL_EditCtrl::PasteText() {}
+
+void CPWL_EditCtrl::CutText() {}
+
+void CPWL_EditCtrl::InsertWord(uint16_t word, int32_t nCharset) {
+ if (!IsReadOnly())
+ m_pEdit->InsertWord(word, nCharset);
+}
+
+void CPWL_EditCtrl::InsertReturn() {
+ if (!IsReadOnly())
+ m_pEdit->InsertReturn();
+}
+
+void CPWL_EditCtrl::Delete() {
+ if (!IsReadOnly())
+ m_pEdit->Delete();
+}
+
+void CPWL_EditCtrl::Backspace() {
+ if (!IsReadOnly())
+ m_pEdit->Backspace();
+}
+
+bool CPWL_EditCtrl::CanUndo() const {
+ return !IsReadOnly() && m_pEdit->CanUndo();
+}
+
+bool CPWL_EditCtrl::CanRedo() const {
+ return !IsReadOnly() && m_pEdit->CanRedo();
+}
+
+void CPWL_EditCtrl::Redo() {
+ if (CanRedo())
+ m_pEdit->Redo();
+}
+
+void CPWL_EditCtrl::Undo() {
+ if (CanUndo())
+ m_pEdit->Undo();
+}
+
+int32_t CPWL_EditCtrl::GetCharSet() const {
+ return m_nCharSet < 0 ? FX_CHARSET_Default : m_nCharSet;
+}
+
+void CPWL_EditCtrl::SetReadyToInput() {
+ if (m_bMouseDown) {
+ ReleaseCapture();
+ m_bMouseDown = false;
+ }
+}
diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.h b/fpdfsdk/pwl/cpwl_edit_ctrl.h
new file mode 100644
index 0000000..31140e3
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_edit_ctrl.h
@@ -0,0 +1,96 @@
+// Copyright 2014 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_PWL_CPWL_EDIT_CTRL_H_
+#define FPDFSDK_PWL_CPWL_EDIT_CTRL_H_
+
+#include <memory>
+
+#include "core/fxcrt/fx_string.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+class CPWL_EditImpl;
+class CPWL_Caret;
+struct CPVT_WordPlace;
+
+enum PWL_EDIT_ALIGNFORMAT_H { PEAH_LEFT = 0, PEAH_MIDDLE, PEAH_RIGHT };
+
+enum PWL_EDIT_ALIGNFORMAT_V { PEAV_TOP = 0, PEAV_CENTER, PEAV_BOTTOM };
+
+class CPWL_EditCtrl : public CPWL_Wnd {
+ public:
+ CPWL_EditCtrl();
+ ~CPWL_EditCtrl() override;
+
+ WideString GetText() const;
+ void SetSelection(int32_t nStartChar, int32_t nEndChar);
+ void GetSelection(int32_t& nStartChar, int32_t& nEndChar) const;
+ void ClearSelection();
+ void SelectAll();
+
+ CFX_PointF GetScrollPos() const;
+ void SetScrollPos(const CFX_PointF& point);
+
+ void SetCharSet(uint8_t nCharSet) { m_nCharSet = nCharSet; }
+ int32_t GetCharSet() const;
+
+ bool CanUndo() const;
+ bool CanRedo() const;
+ void Redo();
+ void Undo();
+
+ void SetReadyToInput();
+
+ // CPWL_Wnd:
+ void OnCreate(CreateParams* pParamsToAdjust) override;
+ void OnCreated() override;
+ bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override;
+ bool OnChar(uint16_t nChar, uint32_t nFlag) override;
+ bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override;
+ void SetScrollInfo(const PWL_SCROLL_INFO& info) override;
+ void SetScrollPosition(float pos) override;
+ void ScrollWindowVertically(float pos) override;
+ void CreateChildWnd(const CreateParams& cp) override;
+ bool RePosChildWnd() override;
+ void SetFontSize(float fFontSize) override;
+ float GetFontSize() const override;
+ void SetCursor() override;
+ WideString GetSelectedText() override;
+ void ReplaceSelection(const WideString& text) override;
+
+ bool SetCaret(bool bVisible,
+ const CFX_PointF& ptHead,
+ const CFX_PointF& ptFoot);
+
+ protected:
+ void CopyText();
+ void PasteText();
+ void CutText();
+ void InsertWord(uint16_t word, int32_t nCharset);
+ void InsertReturn();
+
+ bool IsWndHorV();
+
+ void Delete();
+ void Backspace();
+
+ void GetCaretInfo(CFX_PointF* ptHead, CFX_PointF* ptFoot) const;
+
+ void SetEditCaret(bool bVisible);
+
+ std::unique_ptr<CPWL_EditImpl> m_pEdit;
+ CPWL_Caret* m_pEditCaret;
+ bool m_bMouseDown;
+
+ private:
+ void CreateEditCaret(const CreateParams& cp);
+
+ int32_t m_nCharSet;
+};
+
+#endif // FPDFSDK_PWL_CPWL_EDIT_CTRL_H_
diff --git a/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp b/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp
new file mode 100644
index 0000000..b3f0d5d
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp
@@ -0,0 +1,421 @@
+// 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.
+
+#include "fpdfsdk/cba_annotiterator.h"
+#include "fpdfsdk/cpdfsdk_annot.h"
+#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
+#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "testing/embedder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class CPWLEditEmbeddertest : public EmbedderTest {
+ protected:
+ void SetUp() override {
+ EmbedderTest::SetUp();
+ CreateAndInitializeFormPDF();
+ }
+
+ void TearDown() override {
+ UnloadPage(GetPage());
+ EmbedderTest::TearDown();
+ }
+
+ void CreateAndInitializeFormPDF() {
+ EXPECT_TRUE(OpenDocument("text_form_multiple.pdf"));
+ m_page = LoadPage(0);
+ ASSERT_TRUE(m_page);
+
+ m_pFormFillEnv = static_cast<CPDFSDK_FormFillEnvironment*>(form_handle());
+ CBA_AnnotIterator iter(m_pFormFillEnv->GetPageView(0),
+ CPDF_Annot::Subtype::WIDGET);
+ // Normal text field.
+ m_pAnnot = iter.GetFirstAnnot();
+ ASSERT_TRUE(m_pAnnot);
+ ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnot->GetAnnotSubtype());
+
+ // Read-only text field.
+ CPDFSDK_Annot* pAnnotReadOnly = iter.GetNextAnnot(m_pAnnot);
+
+ // Pre-filled text field with char limit of 10.
+ m_pAnnotCharLimit = iter.GetNextAnnot(pAnnotReadOnly);
+ ASSERT_TRUE(m_pAnnotCharLimit);
+ ASSERT_EQ(CPDF_Annot::Subtype::WIDGET,
+ m_pAnnotCharLimit->GetAnnotSubtype());
+ CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot();
+ ASSERT_EQ(m_pAnnotCharLimit, pLastAnnot);
+ }
+
+ void FormFillerAndWindowSetup(CPDFSDK_Annot* pAnnotTextField) {
+ CFFL_InteractiveFormFiller* pInteractiveFormFiller =
+ m_pFormFillEnv->GetInteractiveFormFiller();
+ {
+ CPDFSDK_Annot::ObservedPtr pObserved(pAnnotTextField);
+ EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0));
+ }
+
+ m_pFormFiller =
+ pInteractiveFormFiller->GetFormFiller(pAnnotTextField, false);
+ ASSERT_TRUE(m_pFormFiller);
+
+ CPWL_Wnd* pWindow =
+ m_pFormFiller->GetPDFWindow(m_pFormFillEnv->GetPageView(0), false);
+ ASSERT_TRUE(pWindow);
+ ASSERT_EQ(PWL_CLASSNAME_EDIT, pWindow->GetClassName());
+
+ m_pEdit = static_cast<CPWL_Edit*>(pWindow);
+ }
+
+ void TypeTextIntoTextField(int num_chars) {
+ // Type text starting with 'A' to as many chars as specified by |num_chars|.
+ for (int i = 0; i < num_chars; ++i) {
+ EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0));
+ }
+ }
+
+ FPDF_PAGE GetPage() { return m_page; }
+ CPWL_Edit* GetCPWLEdit() { return m_pEdit; }
+ CFFL_FormFiller* GetCFFLFormFiller() { return m_pFormFiller; }
+ CPDFSDK_Annot* GetCPDFSDKAnnot() { return m_pAnnot; }
+ CPDFSDK_Annot* GetCPDFSDKAnnotCharLimit() { return m_pAnnotCharLimit; }
+
+ private:
+ FPDF_PAGE m_page;
+ CPWL_Edit* m_pEdit;
+ CFFL_FormFiller* m_pFormFiller;
+ CPDFSDK_Annot* m_pAnnot;
+ CPDFSDK_Annot* m_pAnnotCharLimit;
+ CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
+};
+
+TEST_F(CPWLEditEmbeddertest, TypeText) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty());
+ EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'a', 0));
+ EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'b', 0));
+ EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'c', 0));
+
+ EXPECT_STREQ(L"abc", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, GetSelectedTextEmptyAndBasic) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ // Attempt to set selection before text has been typed to test that
+ // selection is identified as empty.
+ //
+ // Select from character index [0, 3) within form text field.
+ GetCPWLEdit()->SetSelection(0, 3);
+ EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty());
+
+ EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'a', 0));
+ EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'b', 0));
+ EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'c', 0));
+ GetCPWLEdit()->SetSelection(0, 2);
+
+ EXPECT_STREQ(L"ab", GetCPWLEdit()->GetSelectedText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, GetSelectedTextFragments) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(50);
+
+ GetCPWLEdit()->SetSelection(0, 0);
+ EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty());
+
+ GetCPWLEdit()->SetSelection(0, 1);
+ EXPECT_STREQ(L"A", GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->SetSelection(0, -1);
+ EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->SetSelection(-8, -1);
+ EXPECT_TRUE(GetCPWLEdit()->GetSelectedText().IsEmpty());
+
+ GetCPWLEdit()->SetSelection(23, 12);
+ EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->SetSelection(12, 23);
+ EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->SetSelection(49, 50);
+ EXPECT_STREQ(L"r", GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->SetSelection(49, 55);
+ EXPECT_STREQ(L"r", GetCPWLEdit()->GetSelectedText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, DeleteEntireTextSelection) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(50);
+
+ GetCPWLEdit()->SetSelection(0, -1);
+ EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->ReplaceSelection(L"");
+ EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty());
+}
+
+TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionMiddle) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(50);
+
+ GetCPWLEdit()->SetSelection(12, 23);
+ EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->ReplaceSelection(L"");
+ EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionLeft) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(50);
+
+ GetCPWLEdit()->SetSelection(0, 5);
+ EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->ReplaceSelection(L"");
+ EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionRight) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(50);
+
+ GetCPWLEdit()->SetSelection(45, 50);
+ EXPECT_STREQ(L"nopqr", GetCPWLEdit()->GetSelectedText().c_str());
+
+ GetCPWLEdit()->ReplaceSelection(L"");
+ EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm",
+ GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, DeleteEmptyTextSelection) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(50);
+
+ GetCPWLEdit()->ReplaceSelection(L"");
+ EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
+ GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyTextField) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"Hello", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldLeft) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(10);
+
+ // Move cursor to beginning of text field.
+ EXPECT_TRUE(
+ GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnot(), FWL_VKEY_Home, 0));
+
+ GetCPWLEdit()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldMiddle) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(10);
+
+ // Move cursor to middle of text field.
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_TRUE(
+ GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnot(), FWL_VKEY_Left, 0));
+ }
+
+ GetCPWLEdit()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldRight) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(10);
+
+ GetCPWLEdit()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedTextFieldWhole) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(10);
+
+ GetCPWLEdit()->SetSelection(0, -1);
+ EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"Hello", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedTextFieldLeft) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(10);
+
+ GetCPWLEdit()->SetSelection(0, 5);
+ EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"HelloFGHIJ", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedTextFieldMiddle) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(10);
+
+ GetCPWLEdit()->SetSelection(2, 7);
+ EXPECT_STREQ(L"CDEFG", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"ABHelloHIJ", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedTextFieldRight) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ TypeTextIntoTextField(10);
+
+ GetCPWLEdit()->SetSelection(5, 10);
+ EXPECT_STREQ(L"FGHIJ", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"Hello");
+ EXPECT_STREQ(L"ABCDEHello", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyCharLimitTextFieldOverflow) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ GetCPWLEdit()->SetSelection(0, -1);
+ EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"");
+
+ GetCPWLEdit()->ReplaceSelection(L"Hippopotamus");
+ EXPECT_STREQ(L"Hippopotam", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyCharLimitTextFieldFit) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ GetCPWLEdit()->SetSelection(0, -1);
+ EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"");
+
+ GetCPWLEdit()->ReplaceSelection(L"Zebra");
+ EXPECT_STREQ(L"Zebra", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldLeft) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ GetCPWLEdit()->ReplaceSelection(L"Hippopotamus");
+ EXPECT_STREQ(L"HiElephant", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldMiddle) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ // Move cursor to middle of text field.
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotCharLimit(),
+ FWL_VKEY_Right, 0));
+ }
+
+ GetCPWLEdit()->ReplaceSelection(L"Hippopotamus");
+ EXPECT_STREQ(L"ElephHiant", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldRight) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ // Move cursor to end of text field.
+ EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotCharLimit(),
+ FWL_VKEY_End, 0));
+
+ GetCPWLEdit()->ReplaceSelection(L"Hippopotamus");
+ EXPECT_STREQ(L"ElephantHi", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldWhole) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ GetCPWLEdit()->SetSelection(0, -1);
+ EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"Hippopotamus");
+ EXPECT_STREQ(L"Hippopotam", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldLeft) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ GetCPWLEdit()->SetSelection(0, 4);
+ EXPECT_STREQ(L"Elep", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"Hippopotamus");
+ EXPECT_STREQ(L"Hippophant", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldMiddle) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ GetCPWLEdit()->SetSelection(2, 6);
+ EXPECT_STREQ(L"epha", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"Hippopotamus");
+ EXPECT_STREQ(L"ElHippopnt", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest,
+ InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldRight) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit());
+ GetCPWLEdit()->SetSelection(4, 8);
+ EXPECT_STREQ(L"hant", GetCPWLEdit()->GetSelectedText().c_str());
+ GetCPWLEdit()->ReplaceSelection(L"Hippopotamus");
+ EXPECT_STREQ(L"ElepHippop", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, SetTextWithEndCarriageFeed) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->SetText(L"Foo\r");
+ EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, SetTextWithEndNewline) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->SetText(L"Foo\n");
+ EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, SetTextWithEndCarriageFeedAndNewLine) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->SetText(L"Foo\r\n");
+ EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, SetTextWithEndNewLineAndCarriageFeed) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->SetText(L"Foo\n\r");
+ EXPECT_STREQ(L"Foo", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, SetTextWithBodyCarriageFeed) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->SetText(L"Foo\rBar");
+ EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, SetTextWithBodyNewline) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->SetText(L"Foo\nBar");
+ EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, SetTextWithBodyCarriageFeedAndNewLine) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->SetText(L"Foo\r\nBar");
+ EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str());
+}
+
+TEST_F(CPWLEditEmbeddertest, SetTextWithBodyNewLineAndCarriageFeed) {
+ FormFillerAndWindowSetup(GetCPDFSDKAnnot());
+ GetCPWLEdit()->SetText(L"Foo\n\rBar");
+ EXPECT_STREQ(L"FooBar", GetCPWLEdit()->GetText().c_str());
+}
diff --git a/fpdfsdk/pwl/cpwl_edit_impl.cpp b/fpdfsdk/pwl/cpwl_edit_impl.cpp
new file mode 100644
index 0000000..a2a7b1d
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_edit_impl.cpp
@@ -0,0 +1,1899 @@
+// Copyright 2014 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/pwl/cpwl_edit_impl.h"
+
+#include <algorithm>
+#include <memory>
+#include <sstream>
+#include <utility>
+
+#include "core/fpdfapi/font/cpdf_font.h"
+#include "core/fpdfapi/page/cpdf_pageobject.h"
+#include "core/fpdfapi/page/cpdf_pageobjectholder.h"
+#include "core/fpdfapi/page/cpdf_pathobject.h"
+#include "core/fpdfapi/page/cpdf_textobject.h"
+#include "core/fpdfapi/parser/fpdf_parser_decode.h"
+#include "core/fpdfapi/render/cpdf_renderoptions.h"
+#include "core/fpdfapi/render/cpdf_textrenderer.h"
+#include "core/fpdfdoc/cpvt_word.h"
+#include "core/fpdfdoc/ipvt_fontmap.h"
+#include "core/fxcrt/autorestorer.h"
+#include "core/fxcrt/fx_codepage.h"
+#include "core/fxge/cfx_graphstatedata.h"
+#include "core/fxge/cfx_pathdata.h"
+#include "core/fxge/cfx_renderdevice.h"
+#include "fpdfsdk/cfx_systemhandler.h"
+#include "fpdfsdk/pwl/cpwl_edit.h"
+#include "fpdfsdk/pwl/cpwl_edit_ctrl.h"
+#include "fpdfsdk/pwl/cpwl_scroll_bar.h"
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+
+namespace {
+
+const int kEditUndoMaxItems = 10000;
+
+void DrawTextString(CFX_RenderDevice* pDevice,
+ const CFX_PointF& pt,
+ CPDF_Font* pFont,
+ float fFontSize,
+ const CFX_Matrix& mtUser2Device,
+ const ByteString& str,
+ FX_ARGB crTextFill,
+ int32_t nHorzScale) {
+ if (!pFont)
+ return;
+
+ CFX_PointF pos = mtUser2Device.Transform(pt);
+ CFX_Matrix mt;
+ if (nHorzScale == 100) {
+ mt = mtUser2Device;
+ } else {
+ mt = CFX_Matrix(nHorzScale / 100.0f, 0, 0, 1, 0, 0);
+ mt.Concat(mtUser2Device);
+ }
+
+ CPDF_RenderOptions ro;
+ ro.SetFlags(RENDER_CLEARTYPE);
+
+ ro.SetColorMode(CPDF_RenderOptions::kNormal);
+ CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize,
+ &mt, str, crTextFill, nullptr, &ro);
+}
+
+} // namespace
+
+CPWL_EditImpl_Iterator::CPWL_EditImpl_Iterator(
+ CPWL_EditImpl* pEdit,
+ CPDF_VariableText::Iterator* pVTIterator)
+ : m_pEdit(pEdit), m_pVTIterator(pVTIterator) {}
+
+CPWL_EditImpl_Iterator::~CPWL_EditImpl_Iterator() {}
+
+bool CPWL_EditImpl_Iterator::NextWord() {
+ return m_pVTIterator->NextWord();
+}
+
+bool CPWL_EditImpl_Iterator::PrevWord() {
+ return m_pVTIterator->PrevWord();
+}
+
+bool CPWL_EditImpl_Iterator::GetWord(CPVT_Word& word) const {
+ ASSERT(m_pEdit);
+
+ if (m_pVTIterator->GetWord(word)) {
+ word.ptWord = m_pEdit->VTToEdit(word.ptWord);
+ return true;
+ }
+ return false;
+}
+
+bool CPWL_EditImpl_Iterator::GetLine(CPVT_Line& line) const {
+ ASSERT(m_pEdit);
+
+ if (m_pVTIterator->GetLine(line)) {
+ line.ptLine = m_pEdit->VTToEdit(line.ptLine);
+ return true;
+ }
+ return false;
+}
+
+void CPWL_EditImpl_Iterator::SetAt(int32_t nWordIndex) {
+ m_pVTIterator->SetAt(nWordIndex);
+}
+
+void CPWL_EditImpl_Iterator::SetAt(const CPVT_WordPlace& place) {
+ m_pVTIterator->SetAt(place);
+}
+
+const CPVT_WordPlace& CPWL_EditImpl_Iterator::GetAt() const {
+ return m_pVTIterator->GetWordPlace();
+}
+
+CPWL_EditImpl_Provider::CPWL_EditImpl_Provider(IPVT_FontMap* pFontMap)
+ : CPDF_VariableText::Provider(pFontMap), m_pFontMap(pFontMap) {
+ ASSERT(m_pFontMap);
+}
+
+CPWL_EditImpl_Provider::~CPWL_EditImpl_Provider() {}
+
+IPVT_FontMap* CPWL_EditImpl_Provider::GetFontMap() const {
+ return m_pFontMap;
+}
+
+int32_t CPWL_EditImpl_Provider::GetCharWidth(int32_t nFontIndex,
+ uint16_t word) {
+ if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
+ uint32_t charcode = word;
+
+ if (pPDFFont->IsUnicodeCompatible())
+ charcode = pPDFFont->CharCodeFromUnicode(word);
+ else
+ charcode = m_pFontMap->CharCodeFromUnicode(nFontIndex, word);
+
+ if (charcode != CPDF_Font::kInvalidCharCode)
+ return pPDFFont->GetCharWidthF(charcode);
+ }
+
+ return 0;
+}
+
+int32_t CPWL_EditImpl_Provider::GetTypeAscent(int32_t nFontIndex) {
+ if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
+ return pPDFFont->GetTypeAscent();
+
+ return 0;
+}
+
+int32_t CPWL_EditImpl_Provider::GetTypeDescent(int32_t nFontIndex) {
+ if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex))
+ return pPDFFont->GetTypeDescent();
+
+ return 0;
+}
+
+int32_t CPWL_EditImpl_Provider::GetWordFontIndex(uint16_t word,
+ int32_t charset,
+ int32_t nFontIndex) {
+ return m_pFontMap->GetWordFontIndex(word, charset, nFontIndex);
+}
+
+int32_t CPWL_EditImpl_Provider::GetDefaultFontIndex() {
+ return 0;
+}
+
+bool CPWL_EditImpl_Provider::IsLatinWord(uint16_t word) {
+ return FX_EDIT_ISLATINWORD(word);
+}
+
+CPWL_EditImpl_Refresh::CPWL_EditImpl_Refresh() {}
+
+CPWL_EditImpl_Refresh::~CPWL_EditImpl_Refresh() {}
+
+void CPWL_EditImpl_Refresh::BeginRefresh() {
+ m_RefreshRects.clear();
+ m_OldLineRects = std::move(m_NewLineRects);
+}
+
+void CPWL_EditImpl_Refresh::Push(const CPVT_WordRange& linerange,
+ const CFX_FloatRect& rect) {
+ m_NewLineRects.emplace_back(CPWL_EditImpl_LineRect(linerange, rect));
+}
+
+void CPWL_EditImpl_Refresh::NoAnalyse() {
+ for (const auto& lineRect : m_OldLineRects)
+ Add(lineRect.m_rcLine);
+
+ for (const auto& lineRect : m_NewLineRects)
+ Add(lineRect.m_rcLine);
+}
+
+std::vector<CFX_FloatRect>* CPWL_EditImpl_Refresh::GetRefreshRects() {
+ return &m_RefreshRects;
+}
+
+void CPWL_EditImpl_Refresh::EndRefresh() {
+ m_RefreshRects.clear();
+}
+
+void CPWL_EditImpl_Refresh::Add(const CFX_FloatRect& new_rect) {
+ // Check for overlapped area.
+ for (const auto& rect : m_RefreshRects) {
+ if (rect.Contains(new_rect))
+ return;
+ }
+ m_RefreshRects.emplace_back(CFX_FloatRect(new_rect));
+}
+
+CPWL_EditImpl_Undo::CPWL_EditImpl_Undo()
+ : m_nCurUndoPos(0), m_bWorking(false) {}
+
+CPWL_EditImpl_Undo::~CPWL_EditImpl_Undo() {}
+
+bool CPWL_EditImpl_Undo::CanUndo() const {
+ return m_nCurUndoPos > 0;
+}
+
+void CPWL_EditImpl_Undo::Undo() {
+ m_bWorking = true;
+ if (CanUndo()) {
+ m_UndoItemStack[m_nCurUndoPos - 1]->Undo();
+ m_nCurUndoPos--;
+ }
+ m_bWorking = false;
+}
+
+bool CPWL_EditImpl_Undo::CanRedo() const {
+ return m_nCurUndoPos < m_UndoItemStack.size();
+}
+
+void CPWL_EditImpl_Undo::Redo() {
+ m_bWorking = true;
+ if (CanRedo()) {
+ m_UndoItemStack[m_nCurUndoPos]->Redo();
+ m_nCurUndoPos++;
+ }
+ m_bWorking = false;
+}
+
+void CPWL_EditImpl_Undo::AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem) {
+ ASSERT(!m_bWorking);
+ ASSERT(pItem);
+ if (CanRedo())
+ RemoveTails();
+
+ if (m_UndoItemStack.size() >= kEditUndoMaxItems)
+ RemoveHeads();
+
+ m_UndoItemStack.push_back(std::move(pItem));
+ m_nCurUndoPos = m_UndoItemStack.size();
+}
+
+void CPWL_EditImpl_Undo::RemoveHeads() {
+ ASSERT(m_UndoItemStack.size() > 1);
+ m_UndoItemStack.pop_front();
+}
+
+void CPWL_EditImpl_Undo::RemoveTails() {
+ while (CanRedo())
+ m_UndoItemStack.pop_back();
+}
+
+CFXEU_InsertWord::CFXEU_InsertWord(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace,
+ uint16_t word,
+ int32_t charset)
+ : m_pEdit(pEdit),
+ m_wpOld(wpOldPlace),
+ m_wpNew(wpNewPlace),
+ m_Word(word),
+ m_nCharset(charset) {
+ ASSERT(m_pEdit);
+}
+
+CFXEU_InsertWord::~CFXEU_InsertWord() {}
+
+void CFXEU_InsertWord::Redo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpOld);
+ m_pEdit->InsertWord(m_Word, m_nCharset, false, true);
+}
+
+void CFXEU_InsertWord::Undo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpNew);
+ m_pEdit->Backspace(false, true);
+}
+
+CFXEU_InsertReturn::CFXEU_InsertReturn(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace)
+ : m_pEdit(pEdit), m_wpOld(wpOldPlace), m_wpNew(wpNewPlace) {
+ ASSERT(m_pEdit);
+}
+
+CFXEU_InsertReturn::~CFXEU_InsertReturn() {}
+
+void CFXEU_InsertReturn::Redo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpOld);
+ m_pEdit->InsertReturn(false, true);
+}
+
+void CFXEU_InsertReturn::Undo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpNew);
+ m_pEdit->Backspace(false, true);
+}
+
+CFXEU_Backspace::CFXEU_Backspace(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace,
+ uint16_t word,
+ int32_t charset)
+ : m_pEdit(pEdit),
+ m_wpOld(wpOldPlace),
+ m_wpNew(wpNewPlace),
+ m_Word(word),
+ m_nCharset(charset) {
+ ASSERT(m_pEdit);
+}
+
+CFXEU_Backspace::~CFXEU_Backspace() {}
+
+void CFXEU_Backspace::Redo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpOld);
+ m_pEdit->Backspace(false, true);
+}
+
+void CFXEU_Backspace::Undo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpNew);
+ if (m_wpNew.nSecIndex != m_wpOld.nSecIndex)
+ m_pEdit->InsertReturn(false, true);
+ else
+ m_pEdit->InsertWord(m_Word, m_nCharset, false, true);
+}
+
+CFXEU_Delete::CFXEU_Delete(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace,
+ uint16_t word,
+ int32_t charset,
+ bool bSecEnd)
+ : m_pEdit(pEdit),
+ m_wpOld(wpOldPlace),
+ m_wpNew(wpNewPlace),
+ m_Word(word),
+ m_nCharset(charset),
+ m_bSecEnd(bSecEnd) {
+ ASSERT(m_pEdit);
+}
+
+CFXEU_Delete::~CFXEU_Delete() {}
+
+void CFXEU_Delete::Redo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpOld);
+ m_pEdit->Delete(false, true);
+}
+
+void CFXEU_Delete::Undo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpNew);
+ if (m_bSecEnd)
+ m_pEdit->InsertReturn(false, true);
+ else
+ m_pEdit->InsertWord(m_Word, m_nCharset, false, true);
+}
+
+CFXEU_Clear::CFXEU_Clear(CPWL_EditImpl* pEdit,
+ const CPVT_WordRange& wrSel,
+ const WideString& swText)
+ : m_pEdit(pEdit), m_wrSel(wrSel), m_swText(swText) {
+ ASSERT(m_pEdit);
+}
+
+CFXEU_Clear::~CFXEU_Clear() {}
+
+void CFXEU_Clear::Redo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetSelection(m_wrSel.BeginPos, m_wrSel.EndPos);
+ m_pEdit->Clear(false, true);
+}
+
+void CFXEU_Clear::Undo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wrSel.BeginPos);
+ m_pEdit->InsertText(m_swText, FX_CHARSET_Default, false, true);
+ m_pEdit->SetSelection(m_wrSel.BeginPos, m_wrSel.EndPos);
+}
+
+CFXEU_InsertText::CFXEU_InsertText(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace,
+ const WideString& swText,
+ int32_t charset)
+ : m_pEdit(pEdit),
+ m_wpOld(wpOldPlace),
+ m_wpNew(wpNewPlace),
+ m_swText(swText),
+ m_nCharset(charset) {
+ ASSERT(m_pEdit);
+}
+
+CFXEU_InsertText::~CFXEU_InsertText() {}
+
+void CFXEU_InsertText::Redo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetCaret(m_wpOld);
+ m_pEdit->InsertText(m_swText, m_nCharset, false, true);
+}
+
+void CFXEU_InsertText::Undo() {
+ m_pEdit->SelectNone();
+ m_pEdit->SetSelection(m_wpOld, m_wpNew);
+ m_pEdit->Clear(false, true);
+}
+
+// static
+void CPWL_EditImpl::DrawEdit(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device,
+ CPWL_EditImpl* pEdit,
+ FX_COLORREF crTextFill,
+ const CFX_FloatRect& rcClip,
+ const CFX_PointF& ptOffset,
+ const CPVT_WordRange* pRange,
+ CFX_SystemHandler* pSystemHandler,
+ CFFL_FormFiller* pFFLData) {
+ const bool bContinuous =
+ pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f;
+ uint16_t SubWord = pEdit->GetPasswordChar();
+ float fFontSize = pEdit->GetFontSize();
+ CPVT_WordRange wrSelect = pEdit->GetSelectWordRange();
+ int32_t nHorzScale = pEdit->GetHorzScale();
+
+ FX_COLORREF crCurFill = crTextFill;
+ FX_COLORREF crOldFill = crCurFill;
+
+ bool bSelect = false;
+ static const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255);
+ static const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113);
+
+ std::ostringstream sTextBuf;
+ int32_t nFontIndex = -1;
+ CFX_PointF ptBT;
+ CFX_RenderDevice::StateRestorer restorer(pDevice);
+ if (!rcClip.IsEmpty())
+ pDevice->SetClip_Rect(mtUser2Device.TransformRect(rcClip).ToFxRect());
+
+ CPWL_EditImpl_Iterator* pIterator = pEdit->GetIterator();
+ IPVT_FontMap* pFontMap = pEdit->GetFontMap();
+ if (!pFontMap)
+ return;
+
+ if (pRange)
+ pIterator->SetAt(pRange->BeginPos);
+ else
+ pIterator->SetAt(0);
+
+ CPVT_WordPlace oldplace;
+ while (pIterator->NextWord()) {
+ CPVT_WordPlace place = pIterator->GetAt();
+ if (pRange && place > pRange->EndPos)
+ break;
+
+ if (!wrSelect.IsEmpty()) {
+ bSelect = place > wrSelect.BeginPos && place <= wrSelect.EndPos;
+ crCurFill = bSelect ? crWhite : crTextFill;
+ }
+ if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) {
+ crCurFill = crTextFill;
+ crOldFill = crCurFill;
+ }
+ CPVT_Word word;
+ if (pIterator->GetWord(word)) {
+ if (bSelect) {
+ CPVT_Line line;
+ pIterator->GetLine(line);
+
+ if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) {
+ CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent,
+ word.ptWord.x + word.fWidth,
+ line.ptLine.y + line.fLineAscent);
+ rc.Intersect(rcClip);
+ pSystemHandler->OutputSelectedRect(pFFLData, rc);
+ } else {
+ CFX_PathData pathSelBK;
+ pathSelBK.AppendRect(word.ptWord.x, line.ptLine.y + line.fLineDescent,
+ word.ptWord.x + word.fWidth,
+ line.ptLine.y + line.fLineAscent);
+
+ pDevice->DrawPath(&pathSelBK, &mtUser2Device, nullptr, crSelBK, 0,
+ FXFILL_WINDING);
+ }
+ }
+
+ if (bContinuous) {
+ if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex ||
+ crOldFill != crCurFill) {
+ if (sTextBuf.tellp() > 0) {
+ DrawTextString(
+ pDevice, CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
+ pFontMap->GetPDFFont(nFontIndex), fFontSize, mtUser2Device,
+ ByteString(sTextBuf), crOldFill, nHorzScale);
+
+ sTextBuf.str("");
+ }
+ nFontIndex = word.nFontIndex;
+ ptBT = word.ptWord;
+ crOldFill = crCurFill;
+ }
+
+ sTextBuf << pEdit->GetPDFWordString(word.nFontIndex, word.Word,
+ SubWord);
+ } else {
+ DrawTextString(
+ pDevice,
+ CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y),
+ pFontMap->GetPDFFont(word.nFontIndex), fFontSize, mtUser2Device,
+ pEdit->GetPDFWordString(word.nFontIndex, word.Word, SubWord),
+ crCurFill, nHorzScale);
+ }
+ oldplace = place;
+ }
+ }
+
+ if (sTextBuf.tellp() > 0) {
+ DrawTextString(pDevice,
+ CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
+ pFontMap->GetPDFFont(nFontIndex), fFontSize, mtUser2Device,
+ ByteString(sTextBuf), crOldFill, nHorzScale);
+ }
+}
+
+CPWL_EditImpl::CPWL_EditImpl()
+ : m_pVT(pdfium::MakeUnique<CPDF_VariableText>()),
+ m_bEnableScroll(false),
+ m_nAlignment(0),
+ m_bNotifyFlag(false),
+ m_bEnableOverflow(false),
+ m_bEnableRefresh(true),
+ m_bEnableUndo(true) {}
+
+CPWL_EditImpl::~CPWL_EditImpl() {}
+
+void CPWL_EditImpl::Initialize() {
+ m_pVT->Initialize();
+ SetCaret(m_pVT->GetBeginWordPlace());
+ SetCaretOrigin();
+}
+
+void CPWL_EditImpl::SetFontMap(IPVT_FontMap* pFontMap) {
+ m_pVTProvider = pdfium::MakeUnique<CPWL_EditImpl_Provider>(pFontMap);
+ m_pVT->SetProvider(m_pVTProvider.get());
+}
+
+void CPWL_EditImpl::SetNotify(CPWL_EditCtrl* pNotify) {
+ m_pNotify = pNotify;
+}
+
+void CPWL_EditImpl::SetOperationNotify(CPWL_Edit* pOperationNotify) {
+ m_pOperationNotify = pOperationNotify;
+}
+
+CPWL_EditImpl_Iterator* CPWL_EditImpl::GetIterator() {
+ if (!m_pIterator) {
+ m_pIterator =
+ pdfium::MakeUnique<CPWL_EditImpl_Iterator>(this, m_pVT->GetIterator());
+ }
+ return m_pIterator.get();
+}
+
+IPVT_FontMap* CPWL_EditImpl::GetFontMap() {
+ return m_pVTProvider ? m_pVTProvider->GetFontMap() : nullptr;
+}
+
+void CPWL_EditImpl::SetPlateRect(const CFX_FloatRect& rect) {
+ m_pVT->SetPlateRect(rect);
+ m_ptScrollPos = CFX_PointF(rect.left, rect.top);
+ Paint();
+}
+
+void CPWL_EditImpl::SetAlignmentH(int32_t nFormat, bool bPaint) {
+ m_pVT->SetAlignment(nFormat);
+ if (bPaint)
+ Paint();
+}
+
+void CPWL_EditImpl::SetAlignmentV(int32_t nFormat, bool bPaint) {
+ m_nAlignment = nFormat;
+ if (bPaint)
+ Paint();
+}
+
+void CPWL_EditImpl::SetPasswordChar(uint16_t wSubWord, bool bPaint) {
+ m_pVT->SetPasswordChar(wSubWord);
+ if (bPaint)
+ Paint();
+}
+
+void CPWL_EditImpl::SetLimitChar(int32_t nLimitChar) {
+ m_pVT->SetLimitChar(nLimitChar);
+ Paint();
+}
+
+void CPWL_EditImpl::SetCharArray(int32_t nCharArray) {
+ m_pVT->SetCharArray(nCharArray);
+ Paint();
+}
+
+void CPWL_EditImpl::SetCharSpace(float fCharSpace) {
+ m_pVT->SetCharSpace(fCharSpace);
+ Paint();
+}
+
+void CPWL_EditImpl::SetMultiLine(bool bMultiLine, bool bPaint) {
+ m_pVT->SetMultiLine(bMultiLine);
+ if (bPaint)
+ Paint();
+}
+
+void CPWL_EditImpl::SetAutoReturn(bool bAuto, bool bPaint) {
+ m_pVT->SetAutoReturn(bAuto);
+ if (bPaint)
+ Paint();
+}
+
+void CPWL_EditImpl::SetAutoFontSize(bool bAuto, bool bPaint) {
+ m_pVT->SetAutoFontSize(bAuto);
+ if (bPaint)
+ Paint();
+}
+
+void CPWL_EditImpl::SetFontSize(float fFontSize) {
+ m_pVT->SetFontSize(fFontSize);
+ Paint();
+}
+
+void CPWL_EditImpl::SetAutoScroll(bool bAuto, bool bPaint) {
+ m_bEnableScroll = bAuto;
+ if (bPaint)
+ Paint();
+}
+
+void CPWL_EditImpl::SetTextOverflow(bool bAllowed, bool bPaint) {
+ m_bEnableOverflow = bAllowed;
+ if (bPaint)
+ Paint();
+}
+
+void CPWL_EditImpl::SetSelection(int32_t nStartChar, int32_t nEndChar) {
+ if (m_pVT->IsValid()) {
+ if (nStartChar == 0 && nEndChar < 0) {
+ SelectAll();
+ } else if (nStartChar < 0) {
+ SelectNone();
+ } else {
+ if (nStartChar < nEndChar) {
+ SetSelection(m_pVT->WordIndexToWordPlace(nStartChar),
+ m_pVT->WordIndexToWordPlace(nEndChar));
+ } else {
+ SetSelection(m_pVT->WordIndexToWordPlace(nEndChar),
+ m_pVT->WordIndexToWordPlace(nStartChar));
+ }
+ }
+ }
+}
+
+void CPWL_EditImpl::SetSelection(const CPVT_WordPlace& begin,
+ const CPVT_WordPlace& end) {
+ if (!m_pVT->IsValid())
+ return;
+
+ SelectNone();
+ m_SelState.Set(begin, end);
+ SetCaret(m_SelState.EndPos);
+ ScrollToCaret();
+ if (!m_SelState.IsEmpty())
+ Refresh();
+ SetCaretInfo();
+}
+
+void CPWL_EditImpl::GetSelection(int32_t& nStartChar, int32_t& nEndChar) const {
+ nStartChar = -1;
+ nEndChar = -1;
+ if (!m_pVT->IsValid())
+ return;
+
+ if (m_SelState.IsEmpty()) {
+ nStartChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
+ nEndChar = m_pVT->WordPlaceToWordIndex(m_wpCaret);
+ return;
+ }
+ if (m_SelState.BeginPos < m_SelState.EndPos) {
+ nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
+ nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
+ return;
+ }
+ nStartChar = m_pVT->WordPlaceToWordIndex(m_SelState.EndPos);
+ nEndChar = m_pVT->WordPlaceToWordIndex(m_SelState.BeginPos);
+}
+
+int32_t CPWL_EditImpl::GetCaret() const {
+ if (m_pVT->IsValid())
+ return m_pVT->WordPlaceToWordIndex(m_wpCaret);
+
+ return -1;
+}
+
+CPVT_WordPlace CPWL_EditImpl::GetCaretWordPlace() const {
+ return m_wpCaret;
+}
+
+WideString CPWL_EditImpl::GetText() const {
+ WideString swRet;
+ if (!m_pVT->IsValid())
+ return swRet;
+
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ pIterator->SetAt(0);
+
+ CPVT_Word wordinfo;
+ CPVT_WordPlace oldplace = pIterator->GetWordPlace();
+ while (pIterator->NextWord()) {
+ CPVT_WordPlace place = pIterator->GetWordPlace();
+ if (pIterator->GetWord(wordinfo))
+ swRet += wordinfo.Word;
+ if (oldplace.nSecIndex != place.nSecIndex)
+ swRet += L"\r\n";
+ oldplace = place;
+ }
+ return swRet;
+}
+
+WideString CPWL_EditImpl::GetRangeText(const CPVT_WordRange& range) const {
+ WideString swRet;
+ if (!m_pVT->IsValid())
+ return swRet;
+
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ CPVT_WordRange wrTemp = range;
+ m_pVT->UpdateWordPlace(wrTemp.BeginPos);
+ m_pVT->UpdateWordPlace(wrTemp.EndPos);
+ pIterator->SetAt(wrTemp.BeginPos);
+
+ CPVT_Word wordinfo;
+ CPVT_WordPlace oldplace = wrTemp.BeginPos;
+ while (pIterator->NextWord()) {
+ CPVT_WordPlace place = pIterator->GetWordPlace();
+ if (place > wrTemp.EndPos)
+ break;
+ if (pIterator->GetWord(wordinfo))
+ swRet += wordinfo.Word;
+ if (oldplace.nSecIndex != place.nSecIndex)
+ swRet += L"\r\n";
+ oldplace = place;
+ }
+ return swRet;
+}
+
+WideString CPWL_EditImpl::GetSelectedText() const {
+ return GetRangeText(m_SelState.ConvertToWordRange());
+}
+
+int32_t CPWL_EditImpl::GetTotalLines() const {
+ int32_t nLines = 1;
+
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ pIterator->SetAt(0);
+ while (pIterator->NextLine())
+ ++nLines;
+
+ return nLines;
+}
+
+CPVT_WordRange CPWL_EditImpl::GetSelectWordRange() const {
+ return m_SelState.ConvertToWordRange();
+}
+
+void CPWL_EditImpl::SetText(const WideString& sText) {
+ Empty();
+ DoInsertText(CPVT_WordPlace(0, 0, -1), sText, FX_CHARSET_Default);
+ Paint();
+}
+
+bool CPWL_EditImpl::InsertWord(uint16_t word, int32_t charset) {
+ return InsertWord(word, charset, true, true);
+}
+
+bool CPWL_EditImpl::InsertReturn() {
+ return InsertReturn(true, true);
+}
+
+bool CPWL_EditImpl::Backspace() {
+ return Backspace(true, true);
+}
+
+bool CPWL_EditImpl::Delete() {
+ return Delete(true, true);
+}
+
+bool CPWL_EditImpl::ClearSelection() {
+ return Clear(true, true);
+}
+
+bool CPWL_EditImpl::InsertText(const WideString& sText, int32_t charset) {
+ return InsertText(sText, charset, true, true);
+}
+
+float CPWL_EditImpl::GetFontSize() const {
+ return m_pVT->GetFontSize();
+}
+
+uint16_t CPWL_EditImpl::GetPasswordChar() const {
+ return m_pVT->GetPasswordChar();
+}
+
+int32_t CPWL_EditImpl::GetCharArray() const {
+ return m_pVT->GetCharArray();
+}
+
+CFX_FloatRect CPWL_EditImpl::GetContentRect() const {
+ return VTToEdit(m_pVT->GetContentRect());
+}
+
+int32_t CPWL_EditImpl::GetHorzScale() const {
+ return m_pVT->GetHorzScale();
+}
+
+float CPWL_EditImpl::GetCharSpace() const {
+ return m_pVT->GetCharSpace();
+}
+
+CPVT_WordRange CPWL_EditImpl::GetWholeWordRange() const {
+ if (m_pVT->IsValid())
+ return CPVT_WordRange(m_pVT->GetBeginWordPlace(), m_pVT->GetEndWordPlace());
+
+ return CPVT_WordRange();
+}
+
+CPVT_WordRange CPWL_EditImpl::GetVisibleWordRange() const {
+ if (m_bEnableOverflow)
+ return GetWholeWordRange();
+
+ if (m_pVT->IsValid()) {
+ CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
+
+ CPVT_WordPlace place1 =
+ m_pVT->SearchWordPlace(EditToVT(CFX_PointF(rcPlate.left, rcPlate.top)));
+ CPVT_WordPlace place2 = m_pVT->SearchWordPlace(
+ EditToVT(CFX_PointF(rcPlate.right, rcPlate.bottom)));
+
+ return CPVT_WordRange(place1, place2);
+ }
+
+ return CPVT_WordRange();
+}
+
+CPVT_WordPlace CPWL_EditImpl::SearchWordPlace(const CFX_PointF& point) const {
+ if (m_pVT->IsValid()) {
+ return m_pVT->SearchWordPlace(EditToVT(point));
+ }
+
+ return CPVT_WordPlace();
+}
+
+void CPWL_EditImpl::Paint() {
+ if (m_pVT->IsValid()) {
+ RearrangeAll();
+ ScrollToCaret();
+ Refresh();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+}
+
+void CPWL_EditImpl::RearrangeAll() {
+ if (m_pVT->IsValid()) {
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ m_pVT->RearrangeAll();
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ SetScrollInfo();
+ SetContentChanged();
+ }
+}
+
+void CPWL_EditImpl::RearrangePart(const CPVT_WordRange& range) {
+ if (m_pVT->IsValid()) {
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ m_pVT->RearrangePart(range);
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ SetScrollInfo();
+ SetContentChanged();
+ }
+}
+
+void CPWL_EditImpl::SetContentChanged() {
+ if (m_pNotify) {
+ CFX_FloatRect rcContent = m_pVT->GetContentRect();
+ if (rcContent.Width() != m_rcOldContent.Width() ||
+ rcContent.Height() != m_rcOldContent.Height()) {
+ m_rcOldContent = rcContent;
+ }
+ }
+}
+
+void CPWL_EditImpl::SelectAll() {
+ if (!m_pVT->IsValid())
+ return;
+ m_SelState = CPWL_EditImpl_Select(GetWholeWordRange());
+ SetCaret(m_SelState.EndPos);
+ ScrollToCaret();
+ Refresh();
+ SetCaretInfo();
+}
+
+void CPWL_EditImpl::SelectNone() {
+ if (!m_pVT->IsValid() || m_SelState.IsEmpty())
+ return;
+
+ m_SelState.Reset();
+ Refresh();
+}
+
+bool CPWL_EditImpl::IsSelected() const {
+ return !m_SelState.IsEmpty();
+}
+
+CFX_PointF CPWL_EditImpl::VTToEdit(const CFX_PointF& point) const {
+ CFX_FloatRect rcContent = m_pVT->GetContentRect();
+ CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
+
+ float fPadding = 0.0f;
+
+ switch (m_nAlignment) {
+ case 0:
+ fPadding = 0.0f;
+ break;
+ case 1:
+ fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
+ break;
+ case 2:
+ fPadding = rcPlate.Height() - rcContent.Height();
+ break;
+ }
+
+ return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left),
+ point.y - (m_ptScrollPos.y + fPadding - rcPlate.top));
+}
+
+CFX_PointF CPWL_EditImpl::EditToVT(const CFX_PointF& point) const {
+ CFX_FloatRect rcContent = m_pVT->GetContentRect();
+ CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
+
+ float fPadding = 0.0f;
+
+ switch (m_nAlignment) {
+ case 0:
+ fPadding = 0.0f;
+ break;
+ case 1:
+ fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
+ break;
+ case 2:
+ fPadding = rcPlate.Height() - rcContent.Height();
+ break;
+ }
+
+ return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left),
+ point.y + (m_ptScrollPos.y + fPadding - rcPlate.top));
+}
+
+CFX_FloatRect CPWL_EditImpl::VTToEdit(const CFX_FloatRect& rect) const {
+ CFX_PointF ptLeftBottom = VTToEdit(CFX_PointF(rect.left, rect.bottom));
+ CFX_PointF ptRightTop = VTToEdit(CFX_PointF(rect.right, rect.top));
+
+ return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
+ ptRightTop.y);
+}
+
+void CPWL_EditImpl::SetScrollInfo() {
+ if (!m_pNotify)
+ return;
+
+ CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
+ CFX_FloatRect rcContent = m_pVT->GetContentRect();
+ if (m_bNotifyFlag)
+ return;
+
+ AutoRestorer<bool> restorer(&m_bNotifyFlag);
+ m_bNotifyFlag = true;
+
+ PWL_SCROLL_INFO Info;
+ Info.fPlateWidth = rcPlate.top - rcPlate.bottom;
+ Info.fContentMin = rcContent.bottom;
+ Info.fContentMax = rcContent.top;
+ Info.fSmallStep = rcPlate.Height() / 3;
+ Info.fBigStep = rcPlate.Height();
+ m_pNotify->SetScrollInfo(Info);
+}
+
+void CPWL_EditImpl::SetScrollPosX(float fx) {
+ if (!m_bEnableScroll)
+ return;
+
+ if (m_pVT->IsValid()) {
+ if (!IsFloatEqual(m_ptScrollPos.x, fx)) {
+ m_ptScrollPos.x = fx;
+ Refresh();
+ }
+ }
+}
+
+void CPWL_EditImpl::SetScrollPosY(float fy) {
+ if (!m_bEnableScroll)
+ return;
+
+ if (m_pVT->IsValid()) {
+ if (!IsFloatEqual(m_ptScrollPos.y, fy)) {
+ m_ptScrollPos.y = fy;
+ Refresh();
+
+ if (m_pNotify) {
+ if (!m_bNotifyFlag) {
+ AutoRestorer<bool> restorer(&m_bNotifyFlag);
+ m_bNotifyFlag = true;
+ m_pNotify->SetScrollPosition(fy);
+ }
+ }
+ }
+ }
+}
+
+void CPWL_EditImpl::SetScrollPos(const CFX_PointF& point) {
+ SetScrollPosX(point.x);
+ SetScrollPosY(point.y);
+ SetScrollLimit();
+ SetCaretInfo();
+}
+
+CFX_PointF CPWL_EditImpl::GetScrollPos() const {
+ return m_ptScrollPos;
+}
+
+void CPWL_EditImpl::SetScrollLimit() {
+ if (m_pVT->IsValid()) {
+ CFX_FloatRect rcContent = m_pVT->GetContentRect();
+ CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
+
+ if (rcPlate.Width() > rcContent.Width()) {
+ SetScrollPosX(rcPlate.left);
+ } else {
+ if (IsFloatSmaller(m_ptScrollPos.x, rcContent.left)) {
+ SetScrollPosX(rcContent.left);
+ } else if (IsFloatBigger(m_ptScrollPos.x,
+ rcContent.right - rcPlate.Width())) {
+ SetScrollPosX(rcContent.right - rcPlate.Width());
+ }
+ }
+
+ if (rcPlate.Height() > rcContent.Height()) {
+ SetScrollPosY(rcPlate.top);
+ } else {
+ if (IsFloatSmaller(m_ptScrollPos.y,
+ rcContent.bottom + rcPlate.Height())) {
+ SetScrollPosY(rcContent.bottom + rcPlate.Height());
+ } else if (IsFloatBigger(m_ptScrollPos.y, rcContent.top)) {
+ SetScrollPosY(rcContent.top);
+ }
+ }
+ }
+}
+
+void CPWL_EditImpl::ScrollToCaret() {
+ SetScrollLimit();
+
+ if (!m_pVT->IsValid())
+ return;
+
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ pIterator->SetAt(m_wpCaret);
+
+ CFX_PointF ptHead;
+ CFX_PointF ptFoot;
+ CPVT_Word word;
+ CPVT_Line line;
+ if (pIterator->GetWord(word)) {
+ ptHead.x = word.ptWord.x + word.fWidth;
+ ptHead.y = word.ptWord.y + word.fAscent;
+ ptFoot.x = word.ptWord.x + word.fWidth;
+ ptFoot.y = word.ptWord.y + word.fDescent;
+ } else if (pIterator->GetLine(line)) {
+ ptHead.x = line.ptLine.x;
+ ptHead.y = line.ptLine.y + line.fLineAscent;
+ ptFoot.x = line.ptLine.x;
+ ptFoot.y = line.ptLine.y + line.fLineDescent;
+ }
+
+ CFX_PointF ptHeadEdit = VTToEdit(ptHead);
+ CFX_PointF ptFootEdit = VTToEdit(ptFoot);
+ CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
+ if (!IsFloatEqual(rcPlate.left, rcPlate.right)) {
+ if (IsFloatSmaller(ptHeadEdit.x, rcPlate.left) ||
+ IsFloatEqual(ptHeadEdit.x, rcPlate.left)) {
+ SetScrollPosX(ptHead.x);
+ } else if (IsFloatBigger(ptHeadEdit.x, rcPlate.right)) {
+ SetScrollPosX(ptHead.x - rcPlate.Width());
+ }
+ }
+
+ if (!IsFloatEqual(rcPlate.top, rcPlate.bottom)) {
+ if (IsFloatSmaller(ptFootEdit.y, rcPlate.bottom) ||
+ IsFloatEqual(ptFootEdit.y, rcPlate.bottom)) {
+ if (IsFloatSmaller(ptHeadEdit.y, rcPlate.top)) {
+ SetScrollPosY(ptFoot.y + rcPlate.Height());
+ }
+ } else if (IsFloatBigger(ptHeadEdit.y, rcPlate.top)) {
+ if (IsFloatBigger(ptFootEdit.y, rcPlate.bottom)) {
+ SetScrollPosY(ptHead.y);
+ }
+ }
+ }
+}
+
+void CPWL_EditImpl::Refresh() {
+ if (m_bEnableRefresh && m_pVT->IsValid()) {
+ m_Refresh.BeginRefresh();
+ RefreshPushLineRects(GetVisibleWordRange());
+
+ m_Refresh.NoAnalyse();
+ m_ptRefreshScrollPos = m_ptScrollPos;
+
+ if (m_pNotify) {
+ if (!m_bNotifyFlag) {
+ AutoRestorer<bool> restorer(&m_bNotifyFlag);
+ m_bNotifyFlag = true;
+ if (std::vector<CFX_FloatRect>* pRects = m_Refresh.GetRefreshRects()) {
+ for (auto& rect : *pRects)
+ m_pNotify->InvalidateRect(&rect);
+ }
+ }
+ }
+
+ m_Refresh.EndRefresh();
+ }
+}
+
+void CPWL_EditImpl::RefreshPushLineRects(const CPVT_WordRange& wr) {
+ if (!m_pVT->IsValid())
+ return;
+
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ CPVT_WordPlace wpBegin = wr.BeginPos;
+ m_pVT->UpdateWordPlace(wpBegin);
+ CPVT_WordPlace wpEnd = wr.EndPos;
+ m_pVT->UpdateWordPlace(wpEnd);
+ pIterator->SetAt(wpBegin);
+
+ CPVT_Line lineinfo;
+ do {
+ if (!pIterator->GetLine(lineinfo))
+ break;
+ if (lineinfo.lineplace.LineCmp(wpEnd) > 0)
+ break;
+
+ CFX_FloatRect rcLine(lineinfo.ptLine.x,
+ lineinfo.ptLine.y + lineinfo.fLineDescent,
+ lineinfo.ptLine.x + lineinfo.fLineWidth,
+ lineinfo.ptLine.y + lineinfo.fLineAscent);
+
+ m_Refresh.Push(CPVT_WordRange(lineinfo.lineplace, lineinfo.lineEnd),
+ VTToEdit(rcLine));
+ } while (pIterator->NextLine());
+}
+
+void CPWL_EditImpl::RefreshWordRange(const CPVT_WordRange& wr) {
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ CPVT_WordRange wrTemp = wr;
+
+ m_pVT->UpdateWordPlace(wrTemp.BeginPos);
+ m_pVT->UpdateWordPlace(wrTemp.EndPos);
+ pIterator->SetAt(wrTemp.BeginPos);
+
+ CPVT_Word wordinfo;
+ CPVT_Line lineinfo;
+ CPVT_WordPlace place;
+
+ while (pIterator->NextWord()) {
+ place = pIterator->GetWordPlace();
+ if (place > wrTemp.EndPos)
+ break;
+
+ pIterator->GetWord(wordinfo);
+ pIterator->GetLine(lineinfo);
+ if (place.LineCmp(wrTemp.BeginPos) == 0 ||
+ place.LineCmp(wrTemp.EndPos) == 0) {
+ CFX_FloatRect rcWord(wordinfo.ptWord.x,
+ lineinfo.ptLine.y + lineinfo.fLineDescent,
+ wordinfo.ptWord.x + wordinfo.fWidth,
+ lineinfo.ptLine.y + lineinfo.fLineAscent);
+
+ if (m_pNotify) {
+ if (!m_bNotifyFlag) {
+ AutoRestorer<bool> restorer(&m_bNotifyFlag);
+ m_bNotifyFlag = true;
+ CFX_FloatRect rcRefresh = VTToEdit(rcWord);
+ m_pNotify->InvalidateRect(&rcRefresh);
+ }
+ }
+ } else {
+ CFX_FloatRect rcLine(lineinfo.ptLine.x,
+ lineinfo.ptLine.y + lineinfo.fLineDescent,
+ lineinfo.ptLine.x + lineinfo.fLineWidth,
+ lineinfo.ptLine.y + lineinfo.fLineAscent);
+
+ if (m_pNotify) {
+ if (!m_bNotifyFlag) {
+ AutoRestorer<bool> restorer(&m_bNotifyFlag);
+ m_bNotifyFlag = true;
+ CFX_FloatRect rcRefresh = VTToEdit(rcLine);
+ m_pNotify->InvalidateRect(&rcRefresh);
+ }
+ }
+
+ pIterator->NextLine();
+ }
+ }
+}
+
+void CPWL_EditImpl::SetCaret(const CPVT_WordPlace& place) {
+ m_wpOldCaret = m_wpCaret;
+ m_wpCaret = place;
+}
+
+void CPWL_EditImpl::SetCaretInfo() {
+ if (m_pNotify) {
+ if (!m_bNotifyFlag) {
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ pIterator->SetAt(m_wpCaret);
+
+ CFX_PointF ptHead;
+ CFX_PointF ptFoot;
+ CPVT_Word word;
+ CPVT_Line line;
+ if (pIterator->GetWord(word)) {
+ ptHead.x = word.ptWord.x + word.fWidth;
+ ptHead.y = word.ptWord.y + word.fAscent;
+ ptFoot.x = word.ptWord.x + word.fWidth;
+ ptFoot.y = word.ptWord.y + word.fDescent;
+ } else if (pIterator->GetLine(line)) {
+ ptHead.x = line.ptLine.x;
+ ptHead.y = line.ptLine.y + line.fLineAscent;
+ ptFoot.x = line.ptLine.x;
+ ptFoot.y = line.ptLine.y + line.fLineDescent;
+ }
+
+ AutoRestorer<bool> restorer(&m_bNotifyFlag);
+ m_bNotifyFlag = true;
+ m_pNotify->SetCaret(m_SelState.IsEmpty(), VTToEdit(ptHead),
+ VTToEdit(ptFoot));
+ }
+ }
+}
+
+void CPWL_EditImpl::OnMouseDown(const CFX_PointF& point,
+ bool bShift,
+ bool bCtrl) {
+ if (!m_pVT->IsValid())
+ return;
+
+ SelectNone();
+ SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
+ m_SelState.Set(m_wpCaret, m_wpCaret);
+ ScrollToCaret();
+ SetCaretOrigin();
+ SetCaretInfo();
+}
+
+void CPWL_EditImpl::OnMouseMove(const CFX_PointF& point,
+ bool bShift,
+ bool bCtrl) {
+ if (!m_pVT->IsValid())
+ return;
+
+ SetCaret(m_pVT->SearchWordPlace(EditToVT(point)));
+ if (m_wpCaret == m_wpOldCaret)
+ return;
+
+ m_SelState.SetEndPos(m_wpCaret);
+ ScrollToCaret();
+ Refresh();
+ SetCaretOrigin();
+ SetCaretInfo();
+}
+
+void CPWL_EditImpl::OnVK_UP(bool bShift, bool bCtrl) {
+ if (!m_pVT->IsValid())
+ return;
+
+ SetCaret(m_pVT->GetUpWordPlace(m_wpCaret, m_ptCaret));
+ if (bShift) {
+ if (m_SelState.IsEmpty())
+ m_SelState.Set(m_wpOldCaret, m_wpCaret);
+ else
+ m_SelState.SetEndPos(m_wpCaret);
+
+ if (m_wpOldCaret != m_wpCaret) {
+ ScrollToCaret();
+ Refresh();
+ SetCaretInfo();
+ }
+ } else {
+ SelectNone();
+ ScrollToCaret();
+ SetCaretInfo();
+ }
+}
+
+void CPWL_EditImpl::OnVK_DOWN(bool bShift, bool bCtrl) {
+ if (!m_pVT->IsValid())
+ return;
+
+ SetCaret(m_pVT->GetDownWordPlace(m_wpCaret, m_ptCaret));
+ if (bShift) {
+ if (m_SelState.IsEmpty())
+ m_SelState.Set(m_wpOldCaret, m_wpCaret);
+ else
+ m_SelState.SetEndPos(m_wpCaret);
+
+ if (m_wpOldCaret != m_wpCaret) {
+ ScrollToCaret();
+ Refresh();
+ SetCaretInfo();
+ }
+ } else {
+ SelectNone();
+ ScrollToCaret();
+ SetCaretInfo();
+ }
+}
+
+void CPWL_EditImpl::OnVK_LEFT(bool bShift, bool bCtrl) {
+ if (!m_pVT->IsValid())
+ return;
+
+ if (bShift) {
+ if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
+ m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret)) {
+ SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
+ }
+ SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
+ if (m_SelState.IsEmpty())
+ m_SelState.Set(m_wpOldCaret, m_wpCaret);
+ else
+ m_SelState.SetEndPos(m_wpCaret);
+
+ if (m_wpOldCaret != m_wpCaret) {
+ ScrollToCaret();
+ Refresh();
+ SetCaretInfo();
+ }
+ } else {
+ if (!m_SelState.IsEmpty()) {
+ if (m_SelState.BeginPos < m_SelState.EndPos)
+ SetCaret(m_SelState.BeginPos);
+ else
+ SetCaret(m_SelState.EndPos);
+
+ SelectNone();
+ ScrollToCaret();
+ SetCaretInfo();
+ } else {
+ if (m_wpCaret == m_pVT->GetLineBeginPlace(m_wpCaret) &&
+ m_wpCaret != m_pVT->GetSectionBeginPlace(m_wpCaret)) {
+ SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
+ }
+ SetCaret(m_pVT->GetPrevWordPlace(m_wpCaret));
+ ScrollToCaret();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+ }
+}
+
+void CPWL_EditImpl::OnVK_RIGHT(bool bShift, bool bCtrl) {
+ if (!m_pVT->IsValid())
+ return;
+
+ if (bShift) {
+ SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
+ if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
+ m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret))
+ SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
+
+ if (m_SelState.IsEmpty())
+ m_SelState.Set(m_wpOldCaret, m_wpCaret);
+ else
+ m_SelState.SetEndPos(m_wpCaret);
+
+ if (m_wpOldCaret != m_wpCaret) {
+ ScrollToCaret();
+ Refresh();
+ SetCaretInfo();
+ }
+ } else {
+ if (!m_SelState.IsEmpty()) {
+ if (m_SelState.BeginPos > m_SelState.EndPos)
+ SetCaret(m_SelState.BeginPos);
+ else
+ SetCaret(m_SelState.EndPos);
+
+ SelectNone();
+ ScrollToCaret();
+ SetCaretInfo();
+ } else {
+ SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
+ if (m_wpCaret == m_pVT->GetLineEndPlace(m_wpCaret) &&
+ m_wpCaret != m_pVT->GetSectionEndPlace(m_wpCaret)) {
+ SetCaret(m_pVT->GetNextWordPlace(m_wpCaret));
+ }
+ ScrollToCaret();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+ }
+}
+
+void CPWL_EditImpl::OnVK_HOME(bool bShift, bool bCtrl) {
+ if (!m_pVT->IsValid())
+ return;
+
+ if (bShift) {
+ if (bCtrl)
+ SetCaret(m_pVT->GetBeginWordPlace());
+ else
+ SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
+
+ if (m_SelState.IsEmpty())
+ m_SelState.Set(m_wpOldCaret, m_wpCaret);
+ else
+ m_SelState.SetEndPos(m_wpCaret);
+
+ ScrollToCaret();
+ Refresh();
+ SetCaretInfo();
+ } else {
+ if (!m_SelState.IsEmpty()) {
+ SetCaret(std::min(m_SelState.BeginPos, m_SelState.EndPos));
+ SelectNone();
+ ScrollToCaret();
+ SetCaretInfo();
+ } else {
+ if (bCtrl)
+ SetCaret(m_pVT->GetBeginWordPlace());
+ else
+ SetCaret(m_pVT->GetLineBeginPlace(m_wpCaret));
+
+ ScrollToCaret();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+ }
+}
+
+void CPWL_EditImpl::OnVK_END(bool bShift, bool bCtrl) {
+ if (!m_pVT->IsValid())
+ return;
+
+ if (bShift) {
+ if (bCtrl)
+ SetCaret(m_pVT->GetEndWordPlace());
+ else
+ SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
+
+ if (m_SelState.IsEmpty())
+ m_SelState.Set(m_wpOldCaret, m_wpCaret);
+ else
+ m_SelState.SetEndPos(m_wpCaret);
+
+ ScrollToCaret();
+ Refresh();
+ SetCaretInfo();
+ } else {
+ if (!m_SelState.IsEmpty()) {
+ SetCaret(std::max(m_SelState.BeginPos, m_SelState.EndPos));
+ SelectNone();
+ ScrollToCaret();
+ SetCaretInfo();
+ } else {
+ if (bCtrl)
+ SetCaret(m_pVT->GetEndWordPlace());
+ else
+ SetCaret(m_pVT->GetLineEndPlace(m_wpCaret));
+
+ ScrollToCaret();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+ }
+}
+
+bool CPWL_EditImpl::InsertWord(uint16_t word,
+ int32_t charset,
+ bool bAddUndo,
+ bool bPaint) {
+ if (IsTextOverflow() || !m_pVT->IsValid())
+ return false;
+
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ SetCaret(
+ m_pVT->InsertWord(m_wpCaret, word, GetCharSetFromUnicode(word, charset)));
+ m_SelState.Set(m_wpCaret, m_wpCaret);
+ if (m_wpCaret == m_wpOldCaret)
+ return false;
+
+ if (bAddUndo && m_bEnableUndo) {
+ AddEditUndoItem(pdfium::MakeUnique<CFXEU_InsertWord>(
+ this, m_wpOldCaret, m_wpCaret, word, charset));
+ }
+ if (bPaint)
+ PaintInsertText(m_wpOldCaret, m_wpCaret);
+
+ if (m_pOperationNotify)
+ m_pOperationNotify->OnInsertWord(m_wpCaret, m_wpOldCaret);
+
+ return true;
+}
+
+bool CPWL_EditImpl::InsertReturn(bool bAddUndo, bool bPaint) {
+ if (IsTextOverflow() || !m_pVT->IsValid())
+ return false;
+
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ SetCaret(m_pVT->InsertSection(m_wpCaret));
+ m_SelState.Set(m_wpCaret, m_wpCaret);
+ if (m_wpCaret == m_wpOldCaret)
+ return false;
+
+ if (bAddUndo && m_bEnableUndo) {
+ AddEditUndoItem(
+ pdfium::MakeUnique<CFXEU_InsertReturn>(this, m_wpOldCaret, m_wpCaret));
+ }
+ if (bPaint) {
+ RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret));
+ ScrollToCaret();
+ Refresh();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+ if (m_pOperationNotify)
+ m_pOperationNotify->OnInsertReturn(m_wpCaret, m_wpOldCaret);
+
+ return true;
+}
+
+bool CPWL_EditImpl::Backspace(bool bAddUndo, bool bPaint) {
+ if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetBeginWordPlace())
+ return false;
+
+ CPVT_Word word;
+ if (bAddUndo) {
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ pIterator->SetAt(m_wpCaret);
+ pIterator->GetWord(word);
+ }
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ SetCaret(m_pVT->BackSpaceWord(m_wpCaret));
+ m_SelState.Set(m_wpCaret, m_wpCaret);
+ if (m_wpCaret == m_wpOldCaret)
+ return false;
+
+ if (bAddUndo && m_bEnableUndo) {
+ if (m_wpCaret.nSecIndex != m_wpOldCaret.nSecIndex) {
+ AddEditUndoItem(pdfium::MakeUnique<CFXEU_Backspace>(
+ this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset));
+ } else {
+ AddEditUndoItem(pdfium::MakeUnique<CFXEU_Backspace>(
+ this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset));
+ }
+ }
+ if (bPaint) {
+ RearrangePart(CPVT_WordRange(m_wpCaret, m_wpOldCaret));
+ ScrollToCaret();
+ Refresh();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+ if (m_pOperationNotify)
+ m_pOperationNotify->OnBackSpace(m_wpCaret, m_wpOldCaret);
+
+ return true;
+}
+
+bool CPWL_EditImpl::Delete(bool bAddUndo, bool bPaint) {
+ if (!m_pVT->IsValid() || m_wpCaret == m_pVT->GetEndWordPlace())
+ return false;
+
+ CPVT_Word word;
+ if (bAddUndo) {
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ pIterator->SetAt(m_pVT->GetNextWordPlace(m_wpCaret));
+ pIterator->GetWord(word);
+ }
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ bool bSecEnd = (m_wpCaret == m_pVT->GetSectionEndPlace(m_wpCaret));
+ SetCaret(m_pVT->DeleteWord(m_wpCaret));
+ m_SelState.Set(m_wpCaret, m_wpCaret);
+ if (bAddUndo && m_bEnableUndo) {
+ if (bSecEnd) {
+ AddEditUndoItem(pdfium::MakeUnique<CFXEU_Delete>(
+ this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, bSecEnd));
+ } else {
+ AddEditUndoItem(pdfium::MakeUnique<CFXEU_Delete>(
+ this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, bSecEnd));
+ }
+ }
+ if (bPaint) {
+ RearrangePart(CPVT_WordRange(m_wpOldCaret, m_wpCaret));
+ ScrollToCaret();
+ Refresh();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+ if (m_pOperationNotify)
+ m_pOperationNotify->OnDelete(m_wpCaret, m_wpOldCaret);
+
+ return true;
+}
+
+bool CPWL_EditImpl::Empty() {
+ if (m_pVT->IsValid()) {
+ m_pVT->DeleteWords(GetWholeWordRange());
+ SetCaret(m_pVT->GetBeginWordPlace());
+
+ return true;
+ }
+
+ return false;
+}
+
+bool CPWL_EditImpl::Clear(bool bAddUndo, bool bPaint) {
+ if (!m_pVT->IsValid() || m_SelState.IsEmpty())
+ return false;
+
+ CPVT_WordRange range = m_SelState.ConvertToWordRange();
+ if (bAddUndo && m_bEnableUndo) {
+ AddEditUndoItem(
+ pdfium::MakeUnique<CFXEU_Clear>(this, range, GetSelectedText()));
+ }
+
+ SelectNone();
+ SetCaret(m_pVT->DeleteWords(range));
+ m_SelState.Set(m_wpCaret, m_wpCaret);
+ if (bPaint) {
+ RearrangePart(range);
+ ScrollToCaret();
+ Refresh();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+ if (m_pOperationNotify)
+ m_pOperationNotify->OnClear(m_wpCaret, m_wpOldCaret);
+
+ return true;
+}
+
+bool CPWL_EditImpl::InsertText(const WideString& sText,
+ int32_t charset,
+ bool bAddUndo,
+ bool bPaint) {
+ if (IsTextOverflow())
+ return false;
+
+ m_pVT->UpdateWordPlace(m_wpCaret);
+ SetCaret(DoInsertText(m_wpCaret, sText, charset));
+ m_SelState.Set(m_wpCaret, m_wpCaret);
+ if (m_wpCaret == m_wpOldCaret)
+ return false;
+
+ if (bAddUndo && m_bEnableUndo) {
+ AddEditUndoItem(pdfium::MakeUnique<CFXEU_InsertText>(
+ this, m_wpOldCaret, m_wpCaret, sText, charset));
+ }
+ if (bPaint)
+ PaintInsertText(m_wpOldCaret, m_wpCaret);
+
+ if (m_pOperationNotify)
+ m_pOperationNotify->OnInsertText(m_wpCaret, m_wpOldCaret);
+
+ return true;
+}
+
+void CPWL_EditImpl::PaintInsertText(const CPVT_WordPlace& wpOld,
+ const CPVT_WordPlace& wpNew) {
+ if (m_pVT->IsValid()) {
+ RearrangePart(CPVT_WordRange(wpOld, wpNew));
+ ScrollToCaret();
+ Refresh();
+ SetCaretOrigin();
+ SetCaretInfo();
+ }
+}
+
+bool CPWL_EditImpl::Redo() {
+ if (m_bEnableUndo) {
+ if (m_Undo.CanRedo()) {
+ m_Undo.Redo();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CPWL_EditImpl::Undo() {
+ if (m_bEnableUndo) {
+ if (m_Undo.CanUndo()) {
+ m_Undo.Undo();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CPWL_EditImpl::SetCaretOrigin() {
+ if (!m_pVT->IsValid())
+ return;
+
+ CPDF_VariableText::Iterator* pIterator = m_pVT->GetIterator();
+ pIterator->SetAt(m_wpCaret);
+ CPVT_Word word;
+ CPVT_Line line;
+ if (pIterator->GetWord(word)) {
+ m_ptCaret.x = word.ptWord.x + word.fWidth;
+ m_ptCaret.y = word.ptWord.y;
+ } else if (pIterator->GetLine(line)) {
+ m_ptCaret.x = line.ptLine.x;
+ m_ptCaret.y = line.ptLine.y;
+ }
+}
+
+CPVT_WordPlace CPWL_EditImpl::WordIndexToWordPlace(int32_t index) const {
+ if (m_pVT->IsValid())
+ return m_pVT->WordIndexToWordPlace(index);
+
+ return CPVT_WordPlace();
+}
+
+bool CPWL_EditImpl::IsTextFull() const {
+ int32_t nTotalWords = m_pVT->GetTotalWords();
+ int32_t nLimitChar = m_pVT->GetLimitChar();
+ int32_t nCharArray = m_pVT->GetCharArray();
+
+ return IsTextOverflow() || (nLimitChar > 0 && nTotalWords >= nLimitChar) ||
+ (nCharArray > 0 && nTotalWords >= nCharArray);
+}
+
+bool CPWL_EditImpl::IsTextOverflow() const {
+ if (!m_bEnableScroll && !m_bEnableOverflow) {
+ CFX_FloatRect rcPlate = m_pVT->GetPlateRect();
+ CFX_FloatRect rcContent = m_pVT->GetContentRect();
+
+ if (m_pVT->IsMultiLine() && GetTotalLines() > 1 &&
+ IsFloatBigger(rcContent.Height(), rcPlate.Height())) {
+ return true;
+ }
+
+ if (IsFloatBigger(rcContent.Width(), rcPlate.Width()))
+ return true;
+ }
+
+ return false;
+}
+
+bool CPWL_EditImpl::CanUndo() const {
+ if (m_bEnableUndo) {
+ return m_Undo.CanUndo();
+ }
+
+ return false;
+}
+
+bool CPWL_EditImpl::CanRedo() const {
+ if (m_bEnableUndo) {
+ return m_Undo.CanRedo();
+ }
+
+ return false;
+}
+
+void CPWL_EditImpl::EnableRefresh(bool bRefresh) {
+ m_bEnableRefresh = bRefresh;
+}
+
+void CPWL_EditImpl::EnableUndo(bool bUndo) {
+ m_bEnableUndo = bUndo;
+}
+
+CPVT_WordPlace CPWL_EditImpl::DoInsertText(const CPVT_WordPlace& place,
+ const WideString& sText,
+ int32_t charset) {
+ CPVT_WordPlace wp = place;
+
+ if (m_pVT->IsValid()) {
+ for (int32_t i = 0, sz = sText.GetLength(); i < sz; i++) {
+ uint16_t word = sText[i];
+ switch (word) {
+ case 0x0D:
+ wp = m_pVT->InsertSection(wp);
+ if (i + 1 < sz && sText[i + 1] == 0x0A)
+ i++;
+ break;
+ case 0x0A:
+ wp = m_pVT->InsertSection(wp);
+ break;
+ case 0x09:
+ word = 0x20;
+ default:
+ wp =
+ m_pVT->InsertWord(wp, word, GetCharSetFromUnicode(word, charset));
+ break;
+ }
+ }
+ }
+
+ return wp;
+}
+
+int32_t CPWL_EditImpl::GetCharSetFromUnicode(uint16_t word,
+ int32_t nOldCharset) {
+ if (IPVT_FontMap* pFontMap = GetFontMap())
+ return pFontMap->CharSetFromUnicode(word, nOldCharset);
+ return nOldCharset;
+}
+
+void CPWL_EditImpl::AddEditUndoItem(
+ std::unique_ptr<IFX_Edit_UndoItem> pEditUndoItem) {
+ m_Undo.AddItem(std::move(pEditUndoItem));
+}
+
+ByteString CPWL_EditImpl::GetPDFWordString(int32_t nFontIndex,
+ uint16_t Word,
+ uint16_t SubWord) {
+ IPVT_FontMap* pFontMap = GetFontMap();
+ CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex);
+ if (!pPDFFont)
+ return ByteString();
+
+ ByteString sWord;
+ if (SubWord > 0) {
+ Word = SubWord;
+ } else {
+ uint32_t dwCharCode = pPDFFont->IsUnicodeCompatible()
+ ? pPDFFont->CharCodeFromUnicode(Word)
+ : pFontMap->CharCodeFromUnicode(nFontIndex, Word);
+ if (dwCharCode > 0) {
+ pPDFFont->AppendChar(&sWord, dwCharCode);
+ return sWord;
+ }
+ }
+ pPDFFont->AppendChar(&sWord, Word);
+ return sWord;
+}
+
+CPWL_EditImpl_Select::CPWL_EditImpl_Select() {}
+
+CPWL_EditImpl_Select::CPWL_EditImpl_Select(const CPVT_WordRange& range) {
+ Set(range.BeginPos, range.EndPos);
+}
+
+CPVT_WordRange CPWL_EditImpl_Select::ConvertToWordRange() const {
+ return CPVT_WordRange(BeginPos, EndPos);
+}
+
+void CPWL_EditImpl_Select::Reset() {
+ BeginPos.Reset();
+ EndPos.Reset();
+}
+
+void CPWL_EditImpl_Select::Set(const CPVT_WordPlace& begin,
+ const CPVT_WordPlace& end) {
+ BeginPos = begin;
+ EndPos = end;
+}
+
+void CPWL_EditImpl_Select::SetEndPos(const CPVT_WordPlace& end) {
+ EndPos = end;
+}
+
+bool CPWL_EditImpl_Select::IsEmpty() const {
+ return BeginPos == EndPos;
+}
diff --git a/fpdfsdk/pwl/cpwl_edit_impl.h b/fpdfsdk/pwl/cpwl_edit_impl.h
new file mode 100644
index 0000000..38477db
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_edit_impl.h
@@ -0,0 +1,439 @@
+// Copyright 2014 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_PWL_CPWL_EDIT_IMPL_H_
+#define FPDFSDK_PWL_CPWL_EDIT_IMPL_H_
+
+#include <deque>
+#include <memory>
+#include <vector>
+
+#include "core/fpdfdoc/cpdf_variabletext.h"
+#include "core/fpdfdoc/cpvt_wordrange.h"
+#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxge/fx_dib.h"
+
+#define FX_EDIT_ISLATINWORD(u) \
+ (u == 0x2D || (u <= 0x005A && u >= 0x0041) || \
+ (u <= 0x007A && u >= 0x0061) || (u <= 0x02AF && u >= 0x00C0))
+
+class CFFL_FormFiller;
+class CPWL_EditImpl;
+class CPWL_EditImpl_Iterator;
+class CPWL_EditImpl_Provider;
+class CFX_RenderDevice;
+class CFX_SystemHandler;
+class CPWL_Edit;
+class CPWL_EditCtrl;
+class IFX_Edit_UndoItem;
+
+struct CPWL_EditImpl_LineRect {
+ CPWL_EditImpl_LineRect(const CPVT_WordRange& wrLine,
+ const CFX_FloatRect& rcLine)
+ : m_wrLine(wrLine), m_rcLine(rcLine) {}
+
+ CPVT_WordRange m_wrLine;
+ CFX_FloatRect m_rcLine;
+};
+
+class CPWL_EditImpl_Refresh {
+ public:
+ CPWL_EditImpl_Refresh();
+ ~CPWL_EditImpl_Refresh();
+
+ void BeginRefresh();
+ void Push(const CPVT_WordRange& linerange, const CFX_FloatRect& rect);
+ void NoAnalyse();
+ std::vector<CFX_FloatRect>* GetRefreshRects();
+ void EndRefresh();
+
+ private:
+ void Add(const CFX_FloatRect& new_rect);
+
+ std::vector<CPWL_EditImpl_LineRect> m_NewLineRects;
+ std::vector<CPWL_EditImpl_LineRect> m_OldLineRects;
+ std::vector<CFX_FloatRect> m_RefreshRects;
+};
+
+class CPWL_EditImpl_Select {
+ public:
+ CPWL_EditImpl_Select();
+ explicit CPWL_EditImpl_Select(const CPVT_WordRange& range);
+
+ void Reset();
+ void Set(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
+ void SetEndPos(const CPVT_WordPlace& end);
+
+ CPVT_WordRange ConvertToWordRange() const;
+ bool IsEmpty() const;
+
+ CPVT_WordPlace BeginPos;
+ CPVT_WordPlace EndPos;
+};
+
+class CPWL_EditImpl_Undo {
+ public:
+ CPWL_EditImpl_Undo();
+ ~CPWL_EditImpl_Undo();
+
+ void AddItem(std::unique_ptr<IFX_Edit_UndoItem> pItem);
+ void Undo();
+ void Redo();
+ bool CanUndo() const;
+ bool CanRedo() const;
+
+ private:
+ void RemoveHeads();
+ void RemoveTails();
+
+ std::deque<std::unique_ptr<IFX_Edit_UndoItem>> m_UndoItemStack;
+ size_t m_nCurUndoPos;
+ bool m_bWorking;
+};
+
+class IFX_Edit_UndoItem {
+ public:
+ virtual ~IFX_Edit_UndoItem() {}
+
+ virtual void Undo() = 0;
+ virtual void Redo() = 0;
+};
+
+class CFXEU_InsertWord : public IFX_Edit_UndoItem {
+ public:
+ CFXEU_InsertWord(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace,
+ uint16_t word,
+ int32_t charset);
+ ~CFXEU_InsertWord() override;
+
+ // IFX_Edit_UndoItem:
+ void Redo() override;
+ void Undo() override;
+
+ private:
+ UnownedPtr<CPWL_EditImpl> m_pEdit;
+
+ CPVT_WordPlace m_wpOld;
+ CPVT_WordPlace m_wpNew;
+ uint16_t m_Word;
+ int32_t m_nCharset;
+};
+
+class CFXEU_InsertReturn : public IFX_Edit_UndoItem {
+ public:
+ CFXEU_InsertReturn(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace);
+ ~CFXEU_InsertReturn() override;
+
+ // IFX_Edit_UndoItem:
+ void Redo() override;
+ void Undo() override;
+
+ private:
+ UnownedPtr<CPWL_EditImpl> m_pEdit;
+
+ CPVT_WordPlace m_wpOld;
+ CPVT_WordPlace m_wpNew;
+};
+
+class CFXEU_Backspace : public IFX_Edit_UndoItem {
+ public:
+ CFXEU_Backspace(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace,
+ uint16_t word,
+ int32_t charset);
+ ~CFXEU_Backspace() override;
+
+ // IFX_Edit_UndoItem:
+ void Redo() override;
+ void Undo() override;
+
+ private:
+ UnownedPtr<CPWL_EditImpl> m_pEdit;
+
+ CPVT_WordPlace m_wpOld;
+ CPVT_WordPlace m_wpNew;
+ uint16_t m_Word;
+ int32_t m_nCharset;
+};
+
+class CFXEU_Delete : public IFX_Edit_UndoItem {
+ public:
+ CFXEU_Delete(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace,
+ uint16_t word,
+ int32_t charset,
+ bool bSecEnd);
+ ~CFXEU_Delete() override;
+
+ // IFX_Edit_UndoItem:
+ void Redo() override;
+ void Undo() override;
+
+ private:
+ UnownedPtr<CPWL_EditImpl> m_pEdit;
+
+ CPVT_WordPlace m_wpOld;
+ CPVT_WordPlace m_wpNew;
+ uint16_t m_Word;
+ int32_t m_nCharset;
+ bool m_bSecEnd;
+};
+
+class CFXEU_Clear : public IFX_Edit_UndoItem {
+ public:
+ CFXEU_Clear(CPWL_EditImpl* pEdit,
+ const CPVT_WordRange& wrSel,
+ const WideString& swText);
+ ~CFXEU_Clear() override;
+
+ // IFX_Edit_UndoItem:
+ void Redo() override;
+ void Undo() override;
+
+ private:
+ UnownedPtr<CPWL_EditImpl> m_pEdit;
+
+ CPVT_WordRange m_wrSel;
+ WideString m_swText;
+};
+
+class CFXEU_InsertText : public IFX_Edit_UndoItem {
+ public:
+ CFXEU_InsertText(CPWL_EditImpl* pEdit,
+ const CPVT_WordPlace& wpOldPlace,
+ const CPVT_WordPlace& wpNewPlace,
+ const WideString& swText,
+ int32_t charset);
+ ~CFXEU_InsertText() override;
+
+ // IFX_Edit_UndoItem:
+ void Redo() override;
+ void Undo() override;
+
+ private:
+ UnownedPtr<CPWL_EditImpl> m_pEdit;
+
+ CPVT_WordPlace m_wpOld;
+ CPVT_WordPlace m_wpNew;
+ WideString m_swText;
+ int32_t m_nCharset;
+};
+
+class CPWL_EditImpl {
+ public:
+ static void DrawEdit(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device,
+ CPWL_EditImpl* pEdit,
+ FX_COLORREF crTextFill,
+ const CFX_FloatRect& rcClip,
+ const CFX_PointF& ptOffset,
+ const CPVT_WordRange* pRange,
+ CFX_SystemHandler* pSystemHandler,
+ CFFL_FormFiller* pFFLData);
+
+ CPWL_EditImpl();
+ ~CPWL_EditImpl();
+
+ void SetFontMap(IPVT_FontMap* pFontMap);
+ void SetNotify(CPWL_EditCtrl* pNotify);
+ void SetOperationNotify(CPWL_Edit* pOperationNotify);
+
+ // Returns an iterator for the contents. Should not be released.
+ CPWL_EditImpl_Iterator* GetIterator();
+ IPVT_FontMap* GetFontMap();
+ void Initialize();
+
+ // Set the bounding box of the text area.
+ void SetPlateRect(const CFX_FloatRect& rect);
+ void SetScrollPos(const CFX_PointF& point);
+
+ // Set the horizontal text alignment. (nFormat [0:left, 1:middle, 2:right])
+ void SetAlignmentH(int32_t nFormat, bool bPaint);
+ // Set the vertical text alignment. (nFormat [0:left, 1:middle, 2:right])
+ void SetAlignmentV(int32_t nFormat, bool bPaint);
+
+ // Set the substitution character for hidden text.
+ void SetPasswordChar(uint16_t wSubWord, bool bPaint);
+
+ // Set the maximum number of words in the text.
+ void SetLimitChar(int32_t nLimitChar);
+ void SetCharArray(int32_t nCharArray);
+ void SetCharSpace(float fCharSpace);
+ void SetMultiLine(bool bMultiLine, bool bPaint);
+ void SetAutoReturn(bool bAuto, bool bPaint);
+ void SetAutoFontSize(bool bAuto, bool bPaint);
+ void SetAutoScroll(bool bAuto, bool bPaint);
+ void SetFontSize(float fFontSize);
+ void SetTextOverflow(bool bAllowed, bool bPaint);
+ void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl);
+ void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl);
+ void OnVK_UP(bool bShift, bool bCtrl);
+ void OnVK_DOWN(bool bShift, bool bCtrl);
+ void OnVK_LEFT(bool bShift, bool bCtrl);
+ void OnVK_RIGHT(bool bShift, bool bCtrl);
+ void OnVK_HOME(bool bShift, bool bCtrl);
+ void OnVK_END(bool bShift, bool bCtrl);
+ void SetText(const WideString& sText);
+ bool InsertWord(uint16_t word, int32_t charset);
+ bool InsertReturn();
+ bool Backspace();
+ bool Delete();
+ bool ClearSelection();
+ bool InsertText(const WideString& sText, int32_t charset);
+ bool Redo();
+ bool Undo();
+ CPVT_WordPlace WordIndexToWordPlace(int32_t index) const;
+ CPVT_WordPlace SearchWordPlace(const CFX_PointF& point) const;
+ int32_t GetCaret() const;
+ CPVT_WordPlace GetCaretWordPlace() const;
+ WideString GetSelectedText() const;
+ WideString GetText() const;
+ float GetFontSize() const;
+ uint16_t GetPasswordChar() const;
+ CFX_PointF GetScrollPos() const;
+ int32_t GetCharArray() const;
+ CFX_FloatRect GetContentRect() const;
+ WideString GetRangeText(const CPVT_WordRange& range) const;
+ int32_t GetHorzScale() const;
+ float GetCharSpace() const;
+ void SetSelection(int32_t nStartChar, int32_t nEndChar);
+ void GetSelection(int32_t& nStartChar, int32_t& nEndChar) const;
+ void SelectAll();
+ void SelectNone();
+ bool IsSelected() const;
+ void Paint();
+ void EnableRefresh(bool bRefresh);
+ void RefreshWordRange(const CPVT_WordRange& wr);
+ CPVT_WordRange GetWholeWordRange() const;
+ CPVT_WordRange GetSelectWordRange() const;
+ void EnableUndo(bool bUndo);
+ bool IsTextFull() const;
+ bool IsTextOverflow() const;
+ bool CanUndo() const;
+ bool CanRedo() const;
+ CPVT_WordRange GetVisibleWordRange() const;
+
+ bool Empty();
+
+ CPVT_WordPlace DoInsertText(const CPVT_WordPlace& place,
+ const WideString& sText,
+ int32_t charset);
+ int32_t GetCharSetFromUnicode(uint16_t word, int32_t nOldCharset);
+
+ int32_t GetTotalLines() const;
+
+ ByteString GetPDFWordString(int32_t nFontIndex,
+ uint16_t Word,
+ uint16_t SubWord);
+
+ void SetSelection(const CPVT_WordPlace& begin, const CPVT_WordPlace& end);
+
+ bool Delete(bool bAddUndo, bool bPaint);
+ bool Clear(bool bAddUndo, bool bPaint);
+ bool InsertText(const WideString& sText,
+ int32_t charset,
+ bool bAddUndo,
+ bool bPaint);
+ bool InsertWord(uint16_t word, int32_t charset, bool bAddUndo, bool bPaint);
+ bool InsertReturn(bool bAddUndo, bool bPaint);
+ bool Backspace(bool bAddUndo, bool bPaint);
+ void SetCaret(const CPVT_WordPlace& place);
+
+ CFX_PointF VTToEdit(const CFX_PointF& point) const;
+
+ private:
+ void RearrangeAll();
+ void RearrangePart(const CPVT_WordRange& range);
+ void ScrollToCaret();
+ void SetScrollInfo();
+ void SetScrollPosX(float fx);
+ void SetScrollPosY(float fy);
+ void SetScrollLimit();
+ void SetContentChanged();
+
+ void PaintInsertText(const CPVT_WordPlace& wpOld,
+ const CPVT_WordPlace& wpNew);
+
+ CFX_PointF EditToVT(const CFX_PointF& point) const;
+ CFX_FloatRect VTToEdit(const CFX_FloatRect& rect) const;
+
+ void Refresh();
+ void RefreshPushLineRects(const CPVT_WordRange& wr);
+
+ void SetCaretInfo();
+ void SetCaretOrigin();
+
+ void AddEditUndoItem(std::unique_ptr<IFX_Edit_UndoItem> pEditUndoItem);
+
+ std::unique_ptr<CPDF_VariableText> m_pVT;
+ UnownedPtr<CPWL_EditCtrl> m_pNotify;
+ UnownedPtr<CPWL_Edit> m_pOperationNotify;
+ std::unique_ptr<CPWL_EditImpl_Provider> m_pVTProvider;
+ CPVT_WordPlace m_wpCaret;
+ CPVT_WordPlace m_wpOldCaret;
+ CPWL_EditImpl_Select m_SelState;
+ CFX_PointF m_ptScrollPos;
+ CFX_PointF m_ptRefreshScrollPos;
+ bool m_bEnableScroll;
+ std::unique_ptr<CPWL_EditImpl_Iterator> m_pIterator;
+ CPWL_EditImpl_Refresh m_Refresh;
+ CFX_PointF m_ptCaret;
+ CPWL_EditImpl_Undo m_Undo;
+ int32_t m_nAlignment;
+ bool m_bNotifyFlag;
+ bool m_bEnableOverflow;
+ bool m_bEnableRefresh;
+ CFX_FloatRect m_rcOldContent;
+ bool m_bEnableUndo;
+};
+
+class CPWL_EditImpl_Iterator {
+ public:
+ CPWL_EditImpl_Iterator(CPWL_EditImpl* pEdit,
+ CPDF_VariableText::Iterator* pVTIterator);
+ ~CPWL_EditImpl_Iterator();
+
+ bool NextWord();
+ bool PrevWord();
+ bool GetWord(CPVT_Word& word) const;
+ bool GetLine(CPVT_Line& line) const;
+ void SetAt(int32_t nWordIndex);
+ void SetAt(const CPVT_WordPlace& place);
+ const CPVT_WordPlace& GetAt() const;
+
+ private:
+ UnownedPtr<CPWL_EditImpl> m_pEdit;
+ CPDF_VariableText::Iterator* m_pVTIterator;
+};
+
+class CPWL_EditImpl_Provider : public CPDF_VariableText::Provider {
+ public:
+ explicit CPWL_EditImpl_Provider(IPVT_FontMap* pFontMap);
+ ~CPWL_EditImpl_Provider() override;
+
+ IPVT_FontMap* GetFontMap() const;
+
+ // CPDF_VariableText::Provider:
+ int32_t GetCharWidth(int32_t nFontIndex, uint16_t word) override;
+ int32_t GetTypeAscent(int32_t nFontIndex) override;
+ int32_t GetTypeDescent(int32_t nFontIndex) override;
+ int32_t GetWordFontIndex(uint16_t word,
+ int32_t charset,
+ int32_t nFontIndex) override;
+ int32_t GetDefaultFontIndex() override;
+ bool IsLatinWord(uint16_t word) override;
+
+ private:
+ IPVT_FontMap* m_pFontMap;
+};
+
+#endif // FPDFSDK_PWL_CPWL_EDIT_IMPL_H_
diff --git a/fpdfsdk/pwl/cpwl_font_map.cpp b/fpdfsdk/pwl/cpwl_font_map.cpp
new file mode 100644
index 0000000..5e5556e
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_font_map.cpp
@@ -0,0 +1,408 @@
+// Copyright 2014 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/pwl/cpwl_font_map.h"
+
+#include <utility>
+
+#include "core/fpdfapi/cpdf_modulemgr.h"
+#include "core/fpdfapi/font/cpdf_font.h"
+#include "core/fpdfapi/font/cpdf_fontencoding.h"
+#include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fpdfapi/parser/cpdf_parser.h"
+#include "core/fpdfdoc/ipvt_fontmap.h"
+#include "core/fxcrt/fx_codepage.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+
+namespace {
+
+const char kDefaultFontName[] = "Helvetica";
+
+const char* const g_sDEStandardFontName[] = {"Courier",
+ "Courier-Bold",
+ "Courier-BoldOblique",
+ "Courier-Oblique",
+ "Helvetica",
+ "Helvetica-Bold",
+ "Helvetica-BoldOblique",
+ "Helvetica-Oblique",
+ "Times-Roman",
+ "Times-Bold",
+ "Times-Italic",
+ "Times-BoldItalic",
+ "Symbol",
+ "ZapfDingbats"};
+
+} // namespace
+
+CPWL_FontMap::CPWL_FontMap(CFX_SystemHandler* pSystemHandler)
+ : m_pSystemHandler(pSystemHandler) {
+ ASSERT(m_pSystemHandler);
+}
+
+CPWL_FontMap::~CPWL_FontMap() {
+ Empty();
+}
+
+CPDF_Document* CPWL_FontMap::GetDocument() {
+ if (!m_pPDFDoc) {
+ if (CPDF_ModuleMgr::Get()) {
+ m_pPDFDoc = pdfium::MakeUnique<CPDF_Document>(nullptr);
+ m_pPDFDoc->CreateNewDoc();
+ }
+ }
+ return m_pPDFDoc.get();
+}
+
+CPDF_Font* CPWL_FontMap::GetPDFFont(int32_t nFontIndex) {
+ if (pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex])
+ return m_Data[nFontIndex]->pFont;
+
+ return nullptr;
+}
+
+ByteString CPWL_FontMap::GetPDFFontAlias(int32_t nFontIndex) {
+ if (pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex])
+ return m_Data[nFontIndex]->sFontName;
+
+ return ByteString();
+}
+
+bool CPWL_FontMap::KnowWord(int32_t nFontIndex, uint16_t word) {
+ return pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex] &&
+ CharCodeFromUnicode(nFontIndex, word) >= 0;
+}
+
+int32_t CPWL_FontMap::GetWordFontIndex(uint16_t word,
+ int32_t nCharset,
+ int32_t nFontIndex) {
+ if (nFontIndex > 0) {
+ if (KnowWord(nFontIndex, word))
+ return nFontIndex;
+ } else {
+ if (const CPWL_FontMap_Data* pData = GetFontMapData(0)) {
+ if (nCharset == FX_CHARSET_Default ||
+ pData->nCharset == FX_CHARSET_Symbol || nCharset == pData->nCharset) {
+ if (KnowWord(0, word))
+ return 0;
+ }
+ }
+ }
+
+ int32_t nNewFontIndex =
+ GetFontIndex(GetNativeFontName(nCharset), nCharset, true);
+ if (nNewFontIndex >= 0) {
+ if (KnowWord(nNewFontIndex, word))
+ return nNewFontIndex;
+ }
+ nNewFontIndex = GetFontIndex("Arial Unicode MS", FX_CHARSET_Default, false);
+ if (nNewFontIndex >= 0) {
+ if (KnowWord(nNewFontIndex, word))
+ return nNewFontIndex;
+ }
+ return -1;
+}
+
+int32_t CPWL_FontMap::CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) {
+ if (!pdfium::IndexInBounds(m_Data, nFontIndex))
+ return -1;
+
+ CPWL_FontMap_Data* pData = m_Data[nFontIndex].get();
+ if (!pData || !pData->pFont)
+ return -1;
+
+ if (pData->pFont->IsUnicodeCompatible())
+ return pData->pFont->CharCodeFromUnicode(word);
+
+ return word < 0xFF ? word : -1;
+}
+
+ByteString CPWL_FontMap::GetNativeFontName(int32_t nCharset) {
+ for (const auto& pData : m_NativeFont) {
+ if (pData && pData->nCharset == nCharset)
+ return pData->sFontName;
+ }
+
+ ByteString sNew = GetNativeFont(nCharset);
+ if (sNew.IsEmpty())
+ return ByteString();
+
+ auto pNewData = pdfium::MakeUnique<CPWL_FontMap_Native>();
+ pNewData->nCharset = nCharset;
+ pNewData->sFontName = sNew;
+ m_NativeFont.push_back(std::move(pNewData));
+ return sNew;
+}
+
+void CPWL_FontMap::Empty() {
+ m_Data.clear();
+ m_NativeFont.clear();
+}
+
+void CPWL_FontMap::Initialize() {
+ GetFontIndex(kDefaultFontName, FX_CHARSET_ANSI, false);
+}
+
+bool CPWL_FontMap::IsStandardFont(const ByteString& sFontName) {
+ for (const char* name : g_sDEStandardFontName) {
+ if (sFontName == name)
+ return true;
+ }
+
+ return false;
+}
+
+int32_t CPWL_FontMap::FindFont(const ByteString& sFontName, int32_t nCharset) {
+ int32_t i = 0;
+ for (const auto& pData : m_Data) {
+ if (pData &&
+ (nCharset == FX_CHARSET_Default || nCharset == pData->nCharset) &&
+ (sFontName.IsEmpty() || pData->sFontName == sFontName)) {
+ return i;
+ }
+ ++i;
+ }
+ return -1;
+}
+
+int32_t CPWL_FontMap::GetFontIndex(const ByteString& sFontName,
+ int32_t nCharset,
+ bool bFind) {
+ int32_t nFontIndex = FindFont(EncodeFontAlias(sFontName, nCharset), nCharset);
+ if (nFontIndex >= 0)
+ return nFontIndex;
+
+ ByteString sAlias;
+ CPDF_Font* pFont = bFind ? FindFontSameCharset(&sAlias, nCharset) : nullptr;
+ if (!pFont) {
+ ByteString sTemp = sFontName;
+ pFont = AddFontToDocument(GetDocument(), sTemp, nCharset);
+ sAlias = EncodeFontAlias(sTemp, nCharset);
+ }
+ AddedFont(pFont, sAlias);
+ return AddFontData(pFont, sAlias, nCharset);
+}
+
+CPDF_Font* CPWL_FontMap::FindFontSameCharset(ByteString* sFontAlias,
+ int32_t nCharset) {
+ return nullptr;
+}
+
+int32_t CPWL_FontMap::AddFontData(CPDF_Font* pFont,
+ const ByteString& sFontAlias,
+ int32_t nCharset) {
+ auto pNewData = pdfium::MakeUnique<CPWL_FontMap_Data>();
+ pNewData->pFont = pFont;
+ pNewData->sFontName = sFontAlias;
+ pNewData->nCharset = nCharset;
+ m_Data.push_back(std::move(pNewData));
+ return pdfium::CollectionSize<int32_t>(m_Data) - 1;
+}
+
+void CPWL_FontMap::AddedFont(CPDF_Font* pFont, const ByteString& sFontAlias) {}
+
+ByteString CPWL_FontMap::GetNativeFont(int32_t nCharset) {
+ if (nCharset == FX_CHARSET_Default)
+ nCharset = GetNativeCharset();
+
+ ByteString sFontName = GetDefaultFontByCharset(nCharset);
+ if (!m_pSystemHandler->FindNativeTrueTypeFont(sFontName))
+ return ByteString();
+
+ return sFontName;
+}
+
+CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc,
+ ByteString& sFontName,
+ uint8_t nCharset) {
+ if (IsStandardFont(sFontName))
+ return AddStandardFont(pDoc, sFontName);
+
+ return AddSystemFont(pDoc, sFontName, nCharset);
+}
+
+CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc,
+ ByteString& sFontName) {
+ if (!pDoc)
+ return nullptr;
+
+ CPDF_Font* pFont = nullptr;
+
+ if (sFontName == "ZapfDingbats") {
+ pFont = pDoc->AddStandardFont(sFontName.c_str(), nullptr);
+ } else {
+ CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI);
+ pFont = pDoc->AddStandardFont(sFontName.c_str(), &fe);
+ }
+
+ return pFont;
+}
+
+CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc,
+ ByteString& sFontName,
+ uint8_t nCharset) {
+ if (!pDoc)
+ return nullptr;
+
+ if (sFontName.IsEmpty())
+ sFontName = GetNativeFont(nCharset);
+ if (nCharset == FX_CHARSET_Default)
+ nCharset = GetNativeCharset();
+
+ return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName,
+ nCharset);
+}
+
+ByteString CPWL_FontMap::EncodeFontAlias(const ByteString& sFontName,
+ int32_t nCharset) {
+ return EncodeFontAlias(sFontName) + ByteString::Format("_%02X", nCharset);
+}
+
+ByteString CPWL_FontMap::EncodeFontAlias(const ByteString& sFontName) {
+ ByteString sRet = sFontName;
+ sRet.Remove(' ');
+ return sRet;
+}
+
+const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(int32_t nIndex) const {
+ return pdfium::IndexInBounds(m_Data, nIndex) ? m_Data[nIndex].get() : nullptr;
+}
+
+int32_t CPWL_FontMap::GetNativeCharset() {
+ uint8_t nCharset = FX_CHARSET_ANSI;
+ int32_t iCodePage = FXSYS_GetACP();
+ switch (iCodePage) {
+ case FX_CODEPAGE_ShiftJIS:
+ nCharset = FX_CHARSET_ShiftJIS;
+ break;
+ case FX_CODEPAGE_ChineseSimplified:
+ nCharset = FX_CHARSET_ChineseSimplified;
+ break;
+ case FX_CODEPAGE_ChineseTraditional:
+ nCharset = FX_CHARSET_ChineseTraditional;
+ break;
+ case FX_CODEPAGE_MSWin_WesternEuropean:
+ nCharset = FX_CHARSET_ANSI;
+ break;
+ case FX_CODEPAGE_MSDOS_Thai:
+ nCharset = FX_CHARSET_Thai;
+ break;
+ case FX_CODEPAGE_Hangul:
+ nCharset = FX_CHARSET_Hangul;
+ break;
+ case FX_CODEPAGE_UTF16LE:
+ nCharset = FX_CHARSET_ANSI;
+ break;
+ case FX_CODEPAGE_MSWin_EasternEuropean:
+ nCharset = FX_CHARSET_MSWin_EasternEuropean;
+ break;
+ case FX_CODEPAGE_MSWin_Cyrillic:
+ nCharset = FX_CHARSET_MSWin_Cyrillic;
+ break;
+ case FX_CODEPAGE_MSWin_Greek:
+ nCharset = FX_CHARSET_MSWin_Greek;
+ break;
+ case FX_CODEPAGE_MSWin_Turkish:
+ nCharset = FX_CHARSET_MSWin_Turkish;
+ break;
+ case FX_CODEPAGE_MSWin_Hebrew:
+ nCharset = FX_CHARSET_MSWin_Hebrew;
+ break;
+ case FX_CODEPAGE_MSWin_Arabic:
+ nCharset = FX_CHARSET_MSWin_Arabic;
+ break;
+ case FX_CODEPAGE_MSWin_Baltic:
+ nCharset = FX_CHARSET_MSWin_Baltic;
+ break;
+ case FX_CODEPAGE_MSWin_Vietnamese:
+ nCharset = FX_CHARSET_MSWin_Vietnamese;
+ break;
+ case FX_CODEPAGE_Johab:
+ nCharset = FX_CHARSET_Johab;
+ break;
+ }
+ return nCharset;
+}
+
+const FPDF_CharsetFontMap CPWL_FontMap::defaultTTFMap[] = {
+ {FX_CHARSET_ANSI, "Helvetica"},
+ {FX_CHARSET_ChineseSimplified, "SimSun"},
+ {FX_CHARSET_ChineseTraditional, "MingLiU"},
+ {FX_CHARSET_ShiftJIS, "MS Gothic"},
+ {FX_CHARSET_Hangul, "Batang"},
+ {FX_CHARSET_MSWin_Cyrillic, "Arial"},
+#if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ || _FX_PLATFORM_ == _FX_PLATFORM_APPLE_
+ {FX_CHARSET_MSWin_EasternEuropean, "Arial"},
+#else
+ {FX_CHARSET_MSWin_EasternEuropean, "Tahoma"},
+#endif
+ {FX_CHARSET_MSWin_Arabic, "Arial"},
+ {-1, nullptr}};
+
+ByteString CPWL_FontMap::GetDefaultFontByCharset(int32_t nCharset) {
+ int i = 0;
+ while (defaultTTFMap[i].charset != -1) {
+ if (nCharset == defaultTTFMap[i].charset)
+ return defaultTTFMap[i].fontname;
+ ++i;
+ }
+ return "";
+}
+
+int32_t CPWL_FontMap::CharSetFromUnicode(uint16_t word, int32_t nOldCharset) {
+ // to avoid CJK Font to show ASCII
+ if (word < 0x7F)
+ return FX_CHARSET_ANSI;
+ // follow the old charset
+ if (nOldCharset != FX_CHARSET_Default)
+ return nOldCharset;
+
+ // find new charset
+ if ((word >= 0x4E00 && word <= 0x9FA5) ||
+ (word >= 0xE7C7 && word <= 0xE7F3) ||
+ (word >= 0x3000 && word <= 0x303F) ||
+ (word >= 0x2000 && word <= 0x206F)) {
+ return FX_CHARSET_ChineseSimplified;
+ }
+
+ if (((word >= 0x3040) && (word <= 0x309F)) ||
+ ((word >= 0x30A0) && (word <= 0x30FF)) ||
+ ((word >= 0x31F0) && (word <= 0x31FF)) ||
+ ((word >= 0xFF00) && (word <= 0xFFEF))) {
+ return FX_CHARSET_ShiftJIS;
+ }
+
+ if (((word >= 0xAC00) && (word <= 0xD7AF)) ||
+ ((word >= 0x1100) && (word <= 0x11FF)) ||
+ ((word >= 0x3130) && (word <= 0x318F))) {
+ return FX_CHARSET_Hangul;
+ }
+
+ if (word >= 0x0E00 && word <= 0x0E7F)
+ return FX_CHARSET_Thai;
+
+ if ((word >= 0x0370 && word <= 0x03FF) || (word >= 0x1F00 && word <= 0x1FFF))
+ return FX_CHARSET_MSWin_Greek;
+
+ if ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
+ return FX_CHARSET_MSWin_Arabic;
+
+ if (word >= 0x0590 && word <= 0x05FF)
+ return FX_CHARSET_MSWin_Hebrew;
+
+ if (word >= 0x0400 && word <= 0x04FF)
+ return FX_CHARSET_MSWin_Cyrillic;
+
+ if (word >= 0x0100 && word <= 0x024F)
+ return FX_CHARSET_MSWin_EasternEuropean;
+
+ if (word >= 0x1E00 && word <= 0x1EFF)
+ return FX_CHARSET_MSWin_Vietnamese;
+
+ return FX_CHARSET_ANSI;
+}
diff --git a/fpdfsdk/pwl/cpwl_font_map.h b/fpdfsdk/pwl/cpwl_font_map.h
new file mode 100644
index 0000000..592c3fa
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_font_map.h
@@ -0,0 +1,93 @@
+// Copyright 2014 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_PWL_CPWL_FONT_MAP_H_
+#define FPDFSDK_PWL_CPWL_FONT_MAP_H_
+
+#include <memory>
+#include <vector>
+
+#include "core/fpdfdoc/ipvt_fontmap.h"
+#include "core/fxcrt/fx_codepage.h"
+#include "public/fpdf_sysfontinfo.h"
+
+class CPDF_Document;
+class CFX_SystemHandler;
+
+struct CPWL_FontMap_Data {
+ CPDF_Font* pFont;
+ int32_t nCharset;
+ ByteString sFontName;
+};
+
+struct CPWL_FontMap_Native {
+ int32_t nCharset;
+ ByteString sFontName;
+};
+
+class CPWL_FontMap : public IPVT_FontMap {
+ public:
+ explicit CPWL_FontMap(CFX_SystemHandler* pSystemHandler);
+ ~CPWL_FontMap() override;
+
+ // IPVT_FontMap
+ CPDF_Font* GetPDFFont(int32_t nFontIndex) override;
+ ByteString GetPDFFontAlias(int32_t nFontIndex) override;
+ int32_t GetWordFontIndex(uint16_t word,
+ int32_t nCharset,
+ int32_t nFontIndex) override;
+ int32_t CharCodeFromUnicode(int32_t nFontIndex, uint16_t word) override;
+ int32_t CharSetFromUnicode(uint16_t word, int32_t nOldCharset) override;
+
+ const CPWL_FontMap_Data* GetFontMapData(int32_t nIndex) const;
+ static int32_t GetNativeCharset();
+ ByteString GetNativeFontName(int32_t nCharset);
+
+ static ByteString GetDefaultFontByCharset(int32_t nCharset);
+ static const FPDF_CharsetFontMap defaultTTFMap[];
+
+ protected:
+ virtual void Initialize();
+ virtual CPDF_Document* GetDocument();
+ virtual CPDF_Font* FindFontSameCharset(ByteString* sFontAlias,
+ int32_t nCharset);
+ virtual void AddedFont(CPDF_Font* pFont, const ByteString& sFontAlias);
+
+ bool KnowWord(int32_t nFontIndex, uint16_t word);
+
+ void Empty();
+ int32_t GetFontIndex(const ByteString& sFontName,
+ int32_t nCharset,
+ bool bFind);
+ int32_t AddFontData(CPDF_Font* pFont,
+ const ByteString& sFontAlias,
+ int32_t nCharset = FX_CHARSET_Default);
+
+ ByteString EncodeFontAlias(const ByteString& sFontName, int32_t nCharset);
+ ByteString EncodeFontAlias(const ByteString& sFontName);
+
+ std::vector<std::unique_ptr<CPWL_FontMap_Data>> m_Data;
+ std::vector<std::unique_ptr<CPWL_FontMap_Native>> m_NativeFont;
+
+ private:
+ int32_t FindFont(const ByteString& sFontName,
+ int32_t nCharset = FX_CHARSET_Default);
+
+ ByteString GetNativeFont(int32_t nCharset);
+ CPDF_Font* AddFontToDocument(CPDF_Document* pDoc,
+ ByteString& sFontName,
+ uint8_t nCharset);
+ bool IsStandardFont(const ByteString& sFontName);
+ CPDF_Font* AddStandardFont(CPDF_Document* pDoc, ByteString& sFontName);
+ CPDF_Font* AddSystemFont(CPDF_Document* pDoc,
+ ByteString& sFontName,
+ uint8_t nCharset);
+
+ std::unique_ptr<CPDF_Document> m_pPDFDoc;
+ UnownedPtr<CFX_SystemHandler> const m_pSystemHandler;
+};
+
+#endif // FPDFSDK_PWL_CPWL_FONT_MAP_H_
diff --git a/fpdfsdk/pwl/cpwl_icon.cpp b/fpdfsdk/pwl/cpwl_icon.cpp
new file mode 100644
index 0000000..e7669b3
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_icon.cpp
@@ -0,0 +1,131 @@
+// Copyright 2014 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/pwl/cpwl_icon.h"
+
+#include <algorithm>
+#include <sstream>
+
+#include "core/fpdfapi/parser/cpdf_array.h"
+#include "core/fpdfapi/parser/cpdf_stream.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+CPWL_Icon::CPWL_Icon() : m_pPDFStream(nullptr), m_pIconFit(nullptr) {}
+
+CPWL_Icon::~CPWL_Icon() {}
+
+std::pair<float, float> CPWL_Icon::GetImageSize() {
+ if (!m_pPDFStream)
+ return {0.0f, 0.0f};
+
+ CPDF_Dictionary* pDict = m_pPDFStream->GetDict();
+ if (!pDict)
+ return {0.0f, 0.0f};
+
+ CFX_FloatRect rect = pDict->GetRectFor("BBox");
+ return {rect.right - rect.left, rect.top - rect.bottom};
+}
+
+CFX_Matrix CPWL_Icon::GetImageMatrix() {
+ if (!m_pPDFStream)
+ return CFX_Matrix();
+ if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict())
+ return pDict->GetMatrixFor("Matrix");
+ return CFX_Matrix();
+}
+
+ByteString CPWL_Icon::GetImageAlias() {
+ if (!m_pPDFStream)
+ return ByteString();
+ if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict())
+ return pDict->GetStringFor("Name");
+ return ByteString();
+}
+
+std::pair<float, float> CPWL_Icon::GetIconPosition() {
+ if (!m_pIconFit)
+ return {0.0f, 0.0f};
+
+ CPDF_Array* pA =
+ m_pIconFit->GetDict() ? m_pIconFit->GetDict()->GetArrayFor("A") : nullptr;
+ if (!pA)
+ return {0.0f, 0.0f};
+
+ size_t dwCount = pA->GetCount();
+ return {dwCount > 0 ? pA->GetNumberAt(0) : 0.0f,
+ dwCount > 1 ? pA->GetNumberAt(1) : 0.0f};
+}
+
+std::pair<float, float> CPWL_Icon::GetScale() {
+ float fHScale = 1.0f;
+ float fVScale = 1.0f;
+
+ if (!m_pPDFStream)
+ return {fHScale, fVScale};
+
+ CFX_FloatRect rcPlate = GetClientRect();
+ float fPlateWidth = rcPlate.right - rcPlate.left;
+ float fPlateHeight = rcPlate.top - rcPlate.bottom;
+
+ float fImageWidth;
+ float fImageHeight;
+ std::tie(fImageWidth, fImageHeight) = GetImageSize();
+
+ int32_t nScaleMethod = m_pIconFit ? m_pIconFit->GetScaleMethod() : 0;
+
+ switch (nScaleMethod) {
+ default:
+ case 0:
+ fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
+ fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
+ break;
+ case 1:
+ if (fPlateWidth < fImageWidth)
+ fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
+ if (fPlateHeight < fImageHeight)
+ fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
+ break;
+ case 2:
+ if (fPlateWidth > fImageWidth)
+ fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
+ if (fPlateHeight > fImageHeight)
+ fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
+ break;
+ case 3:
+ break;
+ }
+
+ float fMinScale;
+ if (m_pIconFit && m_pIconFit->IsProportionalScale()) {
+ fMinScale = std::min(fHScale, fVScale);
+ fHScale = fMinScale;
+ fVScale = fMinScale;
+ }
+ return {fHScale, fVScale};
+}
+
+std::pair<float, float> CPWL_Icon::GetImageOffset() {
+ float fLeft;
+ float fBottom;
+ std::tie(fLeft, fBottom) = GetIconPosition();
+
+ float fImageWidth;
+ float fImageHeight;
+ std::tie(fImageWidth, fImageHeight) = GetImageSize();
+
+ float fHScale, fVScale;
+ std::tie(fHScale, fVScale) = GetScale();
+
+ float fImageFactWidth = fImageWidth * fHScale;
+ float fImageFactHeight = fImageHeight * fVScale;
+
+ CFX_FloatRect rcPlate = GetClientRect();
+ float fPlateWidth = rcPlate.right - rcPlate.left;
+ float fPlateHeight = rcPlate.top - rcPlate.bottom;
+
+ return {(fPlateWidth - fImageFactWidth) * fLeft,
+ (fPlateHeight - fImageFactHeight) * fBottom};
+}
diff --git a/fpdfsdk/pwl/cpwl_icon.h b/fpdfsdk/pwl/cpwl_icon.h
new file mode 100644
index 0000000..df88465
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_icon.h
@@ -0,0 +1,44 @@
+// Copyright 2014 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_PWL_CPWL_ICON_H_
+#define FPDFSDK_PWL_CPWL_ICON_H_
+
+#include <utility>
+
+#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/unowned_ptr.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+class CPWL_Icon : public CPWL_Wnd {
+ public:
+ CPWL_Icon();
+ ~CPWL_Icon() override;
+
+ void SetIconFit(CPDF_IconFit* pIconFit) { m_pIconFit = pIconFit; }
+ void SetPDFStream(CPDF_Stream* pStream) { m_pPDFStream = pStream; }
+
+ // horizontal scale, vertical scale
+ std::pair<float, float> GetScale();
+
+ // x, y
+ std::pair<float, float> GetImageOffset();
+
+ CFX_Matrix GetImageMatrix();
+ ByteString GetImageAlias();
+
+ private:
+ // left, bottom
+ std::pair<float, float> GetIconPosition();
+
+ // width, height
+ std::pair<float, float> GetImageSize();
+
+ UnownedPtr<CPDF_Stream> m_pPDFStream;
+ UnownedPtr<CPDF_IconFit> m_pIconFit;
+};
+
+#endif // FPDFSDK_PWL_CPWL_ICON_H_
diff --git a/fpdfsdk/pwl/cpwl_list_box.cpp b/fpdfsdk/pwl/cpwl_list_box.cpp
new file mode 100644
index 0000000..a7c02e4
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_list_box.cpp
@@ -0,0 +1,385 @@
+// Copyright 2014 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/pwl/cpwl_list_box.h"
+
+#include <sstream>
+
+#include "core/fxge/cfx_renderdevice.h"
+#include "fpdfsdk/pwl/cpwl_edit.h"
+#include "fpdfsdk/pwl/cpwl_edit_ctrl.h"
+#include "fpdfsdk/pwl/cpwl_edit_impl.h"
+#include "fpdfsdk/pwl/cpwl_list_impl.h"
+#include "fpdfsdk/pwl/cpwl_scroll_bar.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "public/fpdf_fwlevent.h"
+#include "third_party/base/ptr_util.h"
+
+CPWL_List_Notify::CPWL_List_Notify(CPWL_ListBox* pList) : m_pList(pList) {
+ ASSERT(m_pList);
+}
+
+CPWL_List_Notify::~CPWL_List_Notify() {}
+
+void CPWL_List_Notify::IOnSetScrollInfoY(float fPlateMin,
+ float fPlateMax,
+ float fContentMin,
+ float fContentMax,
+ float fSmallStep,
+ float fBigStep) {
+ PWL_SCROLL_INFO Info;
+ Info.fPlateWidth = fPlateMax - fPlateMin;
+ Info.fContentMin = fContentMin;
+ Info.fContentMax = fContentMax;
+ Info.fSmallStep = fSmallStep;
+ Info.fBigStep = fBigStep;
+ m_pList->SetScrollInfo(Info);
+
+ CPWL_ScrollBar* pScroll = m_pList->GetVScrollBar();
+ if (!pScroll)
+ return;
+
+ if (IsFloatBigger(Info.fPlateWidth, Info.fContentMax - Info.fContentMin) ||
+ IsFloatEqual(Info.fPlateWidth, Info.fContentMax - Info.fContentMin)) {
+ if (pScroll->IsVisible()) {
+ pScroll->SetVisible(false);
+ m_pList->RePosChildWnd();
+ }
+ } else {
+ if (!pScroll->IsVisible()) {
+ pScroll->SetVisible(true);
+ m_pList->RePosChildWnd();
+ }
+ }
+}
+
+void CPWL_List_Notify::IOnSetScrollPosY(float fy) {
+ m_pList->SetScrollPosition(fy);
+}
+
+void CPWL_List_Notify::IOnInvalidateRect(CFX_FloatRect* pRect) {
+ m_pList->InvalidateRect(pRect);
+}
+
+CPWL_ListBox::CPWL_ListBox()
+ : m_pList(new CPWL_ListCtrl),
+ m_bMouseDown(false),
+ m_bHoverSel(false),
+ m_pFillerNotify(nullptr) {}
+
+CPWL_ListBox::~CPWL_ListBox() {}
+
+ByteString CPWL_ListBox::GetClassName() const {
+ return "CPWL_ListBox";
+}
+
+void CPWL_ListBox::OnCreated() {
+ m_pList->SetFontMap(GetFontMap());
+ m_pListNotify = pdfium::MakeUnique<CPWL_List_Notify>(this);
+ m_pList->SetNotify(m_pListNotify.get());
+
+ SetHoverSel(HasFlag(PLBS_HOVERSEL));
+ m_pList->SetMultipleSel(HasFlag(PLBS_MULTIPLESEL));
+ m_pList->SetFontSize(GetCreationParams().fFontSize);
+
+ m_bHoverSel = HasFlag(PLBS_HOVERSEL);
+}
+
+void CPWL_ListBox::OnDestroy() {
+ // Make sure the notifier is removed from the list as we are about to
+ // destroy the notifier and don't want to leave a dangling pointer.
+ m_pList->SetNotify(nullptr);
+ m_pListNotify.reset();
+}
+
+void CPWL_ListBox::DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device);
+
+ CFX_FloatRect rcPlate = m_pList->GetPlateRect();
+ CFX_FloatRect rcList = GetListRect();
+ CFX_FloatRect rcClient = GetClientRect();
+
+ for (int32_t i = 0, sz = m_pList->GetCount(); i < sz; i++) {
+ CFX_FloatRect rcItem = m_pList->GetItemRect(i);
+ if (rcItem.bottom > rcPlate.top || rcItem.top < rcPlate.bottom)
+ continue;
+
+ CFX_PointF ptOffset(rcItem.left, (rcItem.top + rcItem.bottom) * 0.5f);
+ if (CPWL_EditImpl* pEdit = m_pList->GetItemEdit(i)) {
+ CFX_FloatRect rcContent = pEdit->GetContentRect();
+ if (rcContent.Width() > rcClient.Width())
+ rcItem.Intersect(rcList);
+ else
+ rcItem.Intersect(rcClient);
+ }
+
+ if (m_pList->IsItemSelected(i)) {
+ CFX_SystemHandler* pSysHandler = GetSystemHandler();
+ if (pSysHandler && pSysHandler->IsSelectionImplemented()) {
+ CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device, m_pList->GetItemEdit(i),
+ GetTextColor().ToFXColor(255), rcList, ptOffset,
+ nullptr, pSysHandler, m_pFormFiller.Get());
+ pSysHandler->OutputSelectedRect(m_pFormFiller.Get(), rcItem);
+ } else {
+ pDevice->DrawFillRect(&mtUser2Device, rcItem,
+ ArgbEncode(255, 0, 51, 113));
+ CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device, m_pList->GetItemEdit(i),
+ ArgbEncode(255, 255, 255, 255), rcList,
+ ptOffset, nullptr, pSysHandler,
+ m_pFormFiller.Get());
+ }
+ } else {
+ CFX_SystemHandler* pSysHandler = GetSystemHandler();
+ CPWL_EditImpl::DrawEdit(pDevice, mtUser2Device, m_pList->GetItemEdit(i),
+ GetTextColor().ToFXColor(255), rcList, ptOffset,
+ nullptr, pSysHandler, nullptr);
+ }
+ }
+}
+
+bool CPWL_ListBox::OnKeyDown(uint16_t nChar, uint32_t nFlag) {
+ CPWL_Wnd::OnKeyDown(nChar, nFlag);
+
+ switch (nChar) {
+ default:
+ return false;
+ case FWL_VKEY_Up:
+ case FWL_VKEY_Down:
+ case FWL_VKEY_Home:
+ case FWL_VKEY_Left:
+ case FWL_VKEY_End:
+ case FWL_VKEY_Right:
+ break;
+ }
+
+ switch (nChar) {
+ case FWL_VKEY_Up:
+ m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Down:
+ m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Home:
+ m_pList->OnVK_HOME(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Left:
+ m_pList->OnVK_LEFT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_End:
+ m_pList->OnVK_END(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Right:
+ m_pList->OnVK_RIGHT(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ break;
+ case FWL_VKEY_Delete:
+ break;
+ }
+ OnNotifySelectionChanged(true, nFlag);
+ return true;
+}
+
+bool CPWL_ListBox::OnChar(uint16_t nChar, uint32_t nFlag) {
+ CPWL_Wnd::OnChar(nChar, nFlag);
+
+ if (!m_pList->OnChar(nChar, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag)))
+ return false;
+
+ OnNotifySelectionChanged(true, nFlag);
+ return true;
+}
+
+bool CPWL_ListBox::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonDown(point, nFlag);
+
+ if (ClientHitTest(point)) {
+ m_bMouseDown = true;
+ SetFocus();
+ SetCapture();
+
+ m_pList->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ }
+
+ return true;
+}
+
+bool CPWL_ListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonUp(point, nFlag);
+
+ if (m_bMouseDown) {
+ ReleaseCapture();
+ m_bMouseDown = false;
+ }
+ OnNotifySelectionChanged(false, nFlag);
+ return true;
+}
+
+void CPWL_ListBox::SetHoverSel(bool bHoverSel) {
+ m_bHoverSel = bHoverSel;
+}
+
+bool CPWL_ListBox::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnMouseMove(point, nFlag);
+
+ if (m_bHoverSel && !IsCaptureMouse() && ClientHitTest(point))
+ m_pList->Select(m_pList->GetItemIndex(point));
+ if (m_bMouseDown)
+ m_pList->OnMouseMove(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+
+ return true;
+}
+
+void CPWL_ListBox::SetScrollInfo(const PWL_SCROLL_INFO& info) {
+ if (CPWL_Wnd* pChild = GetVScrollBar())
+ pChild->SetScrollInfo(info);
+}
+
+void CPWL_ListBox::SetScrollPosition(float pos) {
+ if (CPWL_Wnd* pChild = GetVScrollBar())
+ pChild->SetScrollPosition(pos);
+}
+
+void CPWL_ListBox::ScrollWindowVertically(float pos) {
+ m_pList->SetScrollPos(CFX_PointF(0, pos));
+}
+
+void CPWL_ListBox::KillFocus() {
+ CPWL_Wnd::KillFocus();
+}
+
+bool CPWL_ListBox::RePosChildWnd() {
+ if (!CPWL_Wnd::RePosChildWnd())
+ return false;
+
+ m_pList->SetPlateRect(GetListRect());
+ return true;
+}
+
+bool CPWL_ListBox::OnNotifySelectionChanged(bool bKeyDown, uint32_t nFlag) {
+ if (!m_pFillerNotify)
+ return false;
+
+ CPWL_Wnd::ObservedPtr thisObserved(this);
+
+ WideString swChange = GetText();
+ WideString strChangeEx;
+ int nSelStart = 0;
+ int nSelEnd = swChange.GetLength();
+ bool bRC;
+ bool bExit;
+ std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke(
+ GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, bKeyDown,
+ nFlag);
+
+ if (!thisObserved)
+ return false;
+
+ return bExit;
+}
+
+CFX_FloatRect CPWL_ListBox::GetFocusRect() const {
+ if (m_pList->IsMultipleSel()) {
+ CFX_FloatRect rcCaret = m_pList->GetItemRect(m_pList->GetCaret());
+ rcCaret.Intersect(GetClientRect());
+ return rcCaret;
+ }
+
+ return CPWL_Wnd::GetFocusRect();
+}
+
+void CPWL_ListBox::AddString(const WideString& str) {
+ m_pList->AddString(str);
+}
+
+WideString CPWL_ListBox::GetText() const {
+ return m_pList->GetText();
+}
+
+void CPWL_ListBox::SetFontSize(float fFontSize) {
+ m_pList->SetFontSize(fFontSize);
+}
+
+float CPWL_ListBox::GetFontSize() const {
+ return m_pList->GetFontSize();
+}
+
+void CPWL_ListBox::Select(int32_t nItemIndex) {
+ m_pList->Select(nItemIndex);
+}
+
+void CPWL_ListBox::SetCaret(int32_t nItemIndex) {
+ m_pList->SetCaret(nItemIndex);
+}
+
+void CPWL_ListBox::SetTopVisibleIndex(int32_t nItemIndex) {
+ m_pList->SetTopItem(nItemIndex);
+}
+
+void CPWL_ListBox::ScrollToListItem(int32_t nItemIndex) {
+ m_pList->ScrollToListItem(nItemIndex);
+}
+
+void CPWL_ListBox::ResetContent() {
+ m_pList->Empty();
+}
+
+void CPWL_ListBox::Reset() {
+ m_pList->Cancel();
+}
+
+bool CPWL_ListBox::IsMultipleSel() const {
+ return m_pList->IsMultipleSel();
+}
+
+int32_t CPWL_ListBox::GetCaretIndex() const {
+ return m_pList->GetCaret();
+}
+
+int32_t CPWL_ListBox::GetCurSel() const {
+ return m_pList->GetSelect();
+}
+
+bool CPWL_ListBox::IsItemSelected(int32_t nItemIndex) const {
+ return m_pList->IsItemSelected(nItemIndex);
+}
+
+int32_t CPWL_ListBox::GetTopVisibleIndex() const {
+ m_pList->ScrollToListItem(m_pList->GetFirstSelected());
+ return m_pList->GetTopItem();
+}
+
+int32_t CPWL_ListBox::GetCount() const {
+ return m_pList->GetCount();
+}
+
+int32_t CPWL_ListBox::FindNext(int32_t nIndex, wchar_t nChar) const {
+ return m_pList->FindNext(nIndex, nChar);
+}
+
+CFX_FloatRect CPWL_ListBox::GetContentRect() const {
+ return m_pList->GetContentRect();
+}
+
+float CPWL_ListBox::GetFirstHeight() const {
+ return m_pList->GetFirstHeight();
+}
+
+CFX_FloatRect CPWL_ListBox::GetListRect() const {
+ float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth());
+ return GetWindowRect().GetDeflated(width, width);
+}
+
+bool CPWL_ListBox::OnMouseWheel(short zDelta,
+ const CFX_PointF& point,
+ uint32_t nFlag) {
+ if (zDelta < 0)
+ m_pList->OnVK_DOWN(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+ else
+ m_pList->OnVK_UP(IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+
+ OnNotifySelectionChanged(false, nFlag);
+ return true;
+}
diff --git a/fpdfsdk/pwl/cpwl_list_box.h b/fpdfsdk/pwl/cpwl_list_box.h
new file mode 100644
index 0000000..9a725d1
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_list_box.h
@@ -0,0 +1,108 @@
+// Copyright 2014 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_PWL_CPWL_LIST_BOX_H_
+#define FPDFSDK_PWL_CPWL_LIST_BOX_H_
+
+#include <memory>
+
+#include "core/fxcrt/unowned_ptr.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+class CPWL_ListCtrl;
+class CPWL_List_Notify;
+class CPWL_ListBox;
+class IPWL_Filler_Notify;
+struct CPVT_WordPlace;
+
+class CPWL_List_Notify {
+ public:
+ explicit CPWL_List_Notify(CPWL_ListBox* pList);
+ ~CPWL_List_Notify();
+
+ void IOnSetScrollInfoY(float fPlateMin,
+ float fPlateMax,
+ float fContentMin,
+ float fContentMax,
+ float fSmallStep,
+ float fBigStep);
+ void IOnSetScrollPosY(float fy);
+ void IOnInvalidateRect(CFX_FloatRect* pRect);
+
+ private:
+ UnownedPtr<CPWL_ListBox> m_pList;
+};
+
+class CPWL_ListBox : public CPWL_Wnd {
+ public:
+ CPWL_ListBox();
+ ~CPWL_ListBox() override;
+
+ // CPWL_Wnd
+ ByteString GetClassName() const override;
+ void OnCreated() override;
+ void OnDestroy() override;
+ void DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) override;
+ bool OnKeyDown(uint16_t nChar, uint32_t nFlag) override;
+ bool OnChar(uint16_t nChar, uint32_t nFlag) override;
+ bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override;
+ bool OnMouseWheel(short zDelta,
+ const CFX_PointF& point,
+ uint32_t nFlag) override;
+ void KillFocus() override;
+ void SetScrollInfo(const PWL_SCROLL_INFO& info) override;
+ void SetScrollPosition(float pos) override;
+ void ScrollWindowVertically(float pos) override;
+ bool RePosChildWnd() override;
+ CFX_FloatRect GetFocusRect() const override;
+ void SetFontSize(float fFontSize) override;
+ float GetFontSize() const override;
+
+ virtual WideString GetText() const;
+
+ bool OnNotifySelectionChanged(bool bKeyDown, uint32_t nFlag);
+
+ void AddString(const WideString& str);
+ void SetTopVisibleIndex(int32_t nItemIndex);
+ void ScrollToListItem(int32_t nItemIndex);
+ void ResetContent();
+ void Reset();
+ void Select(int32_t nItemIndex);
+ void SetCaret(int32_t nItemIndex);
+ void SetHoverSel(bool bHoverSel);
+
+ int32_t GetCount() const;
+ bool IsMultipleSel() const;
+ int32_t GetCaretIndex() const;
+ int32_t GetCurSel() const;
+ bool IsItemSelected(int32_t nItemIndex) const;
+ int32_t GetTopVisibleIndex() const;
+ int32_t FindNext(int32_t nIndex, wchar_t nChar) const;
+ CFX_FloatRect GetContentRect() const;
+ float GetFirstHeight() const;
+ CFX_FloatRect GetListRect() const;
+
+ void SetFillerNotify(IPWL_Filler_Notify* pNotify) {
+ m_pFillerNotify = pNotify;
+ }
+
+ void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; }
+
+ protected:
+ std::unique_ptr<CPWL_ListCtrl> m_pList;
+ std::unique_ptr<CPWL_List_Notify> m_pListNotify;
+ bool m_bMouseDown;
+ bool m_bHoverSel;
+ UnownedPtr<IPWL_Filler_Notify> m_pFillerNotify;
+
+ private:
+ UnownedPtr<CFFL_FormFiller> m_pFormFiller;
+};
+
+#endif // FPDFSDK_PWL_CPWL_LIST_BOX_H_
diff --git a/fpdfsdk/pwl/cpwl_list_impl.cpp b/fpdfsdk/pwl/cpwl_list_impl.cpp
new file mode 100644
index 0000000..da455d0
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_list_impl.cpp
@@ -0,0 +1,637 @@
+// Copyright 2014 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/pwl/cpwl_list_impl.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "core/fpdfdoc/cpvt_word.h"
+#include "core/fxcrt/fx_extension.h"
+#include "fpdfsdk/pwl/cpwl_edit_impl.h"
+#include "fpdfsdk/pwl/cpwl_list_box.h"
+#include "third_party/base/stl_util.h"
+
+CPWL_ListCtrl::Item::Item()
+ : m_pEdit(new CPWL_EditImpl),
+ m_bSelected(false),
+ m_rcListItem(0.0f, 0.0f, 0.0f, 0.0f) {
+ m_pEdit->SetAlignmentV(1, true);
+ m_pEdit->Initialize();
+}
+
+CPWL_ListCtrl::Item::~Item() {}
+
+void CPWL_ListCtrl::Item::SetFontMap(IPVT_FontMap* pFontMap) {
+ m_pEdit->SetFontMap(pFontMap);
+}
+
+void CPWL_ListCtrl::Item::SetText(const WideString& text) {
+ m_pEdit->SetText(text);
+}
+
+void CPWL_ListCtrl::Item::SetFontSize(float fFontSize) {
+ m_pEdit->SetFontSize(fFontSize);
+}
+
+float CPWL_ListCtrl::Item::GetItemHeight() const {
+ return m_pEdit->GetContentRect().Height();
+}
+
+uint16_t CPWL_ListCtrl::Item::GetFirstChar() const {
+ CPVT_Word word;
+ CPWL_EditImpl_Iterator* pIterator = m_pEdit->GetIterator();
+ pIterator->SetAt(1);
+ pIterator->GetWord(word);
+ return word.Word;
+}
+
+WideString CPWL_ListCtrl::Item::GetText() const {
+ return m_pEdit->GetText();
+}
+
+CPLST_Select::CPLST_Select() {}
+
+CPLST_Select::~CPLST_Select() {}
+
+void CPLST_Select::Add(int32_t nItemIndex) {
+ m_Items[nItemIndex] = SELECTING;
+}
+
+void CPLST_Select::Add(int32_t nBeginIndex, int32_t nEndIndex) {
+ if (nBeginIndex > nEndIndex)
+ std::swap(nBeginIndex, nEndIndex);
+
+ for (int32_t i = nBeginIndex; i <= nEndIndex; ++i)
+ Add(i);
+}
+
+void CPLST_Select::Sub(int32_t nItemIndex) {
+ auto it = m_Items.find(nItemIndex);
+ if (it != m_Items.end())
+ it->second = DESELECTING;
+}
+
+void CPLST_Select::Sub(int32_t nBeginIndex, int32_t nEndIndex) {
+ if (nBeginIndex > nEndIndex)
+ std::swap(nBeginIndex, nEndIndex);
+
+ for (int32_t i = nBeginIndex; i <= nEndIndex; ++i)
+ Sub(i);
+}
+
+void CPLST_Select::DeselectAll() {
+ for (auto& item : m_Items)
+ item.second = DESELECTING;
+}
+
+void CPLST_Select::Done() {
+ auto it = m_Items.begin();
+ while (it != m_Items.end()) {
+ if (it->second == DESELECTING)
+ it = m_Items.erase(it);
+ else
+ (it++)->second = NORMAL;
+ }
+}
+
+CPWL_ListCtrl::CPWL_ListCtrl()
+ : m_pNotify(nullptr),
+ m_bNotifyFlag(false),
+ m_nSelItem(-1),
+ m_nFootIndex(-1),
+ m_bCtrlSel(false),
+ m_nCaretIndex(-1),
+ m_fFontSize(0.0f),
+ m_pFontMap(nullptr),
+ m_bMultiple(false) {}
+
+CPWL_ListCtrl::~CPWL_ListCtrl() {
+ Empty();
+}
+
+CFX_PointF CPWL_ListCtrl::InToOut(const CFX_PointF& point) const {
+ CFX_FloatRect rcPlate = m_rcPlate;
+ return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left),
+ point.y - (m_ptScrollPos.y - rcPlate.top));
+}
+
+CFX_PointF CPWL_ListCtrl::OutToIn(const CFX_PointF& point) const {
+ CFX_FloatRect rcPlate = m_rcPlate;
+ return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left),
+ point.y + (m_ptScrollPos.y - rcPlate.top));
+}
+
+CFX_FloatRect CPWL_ListCtrl::InToOut(const CFX_FloatRect& rect) const {
+ CFX_PointF ptLeftBottom = InToOut(CFX_PointF(rect.left, rect.bottom));
+ CFX_PointF ptRightTop = InToOut(CFX_PointF(rect.right, rect.top));
+ return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
+ ptRightTop.y);
+}
+
+CFX_FloatRect CPWL_ListCtrl::OutToIn(const CFX_FloatRect& rect) const {
+ CFX_PointF ptLeftBottom = OutToIn(CFX_PointF(rect.left, rect.bottom));
+ CFX_PointF ptRightTop = OutToIn(CFX_PointF(rect.right, rect.top));
+ return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
+ ptRightTop.y);
+}
+
+CFX_PointF CPWL_ListCtrl::InnerToOuter(const CFX_PointF& point) const {
+ return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
+}
+
+CFX_PointF CPWL_ListCtrl::OuterToInner(const CFX_PointF& point) const {
+ return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
+}
+
+CFX_FloatRect CPWL_ListCtrl::InnerToOuter(const CFX_FloatRect& rect) const {
+ CFX_PointF ptLeftTop = InnerToOuter(CFX_PointF(rect.left, rect.top));
+ CFX_PointF ptRightBottom = InnerToOuter(CFX_PointF(rect.right, rect.bottom));
+ return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x,
+ ptLeftTop.y);
+}
+
+CFX_FloatRect CPWL_ListCtrl::OuterToInner(const CFX_FloatRect& rect) const {
+ CFX_PointF ptLeftTop = OuterToInner(CFX_PointF(rect.left, rect.top));
+ CFX_PointF ptRightBottom = OuterToInner(CFX_PointF(rect.right, rect.bottom));
+ return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x,
+ ptLeftTop.y);
+}
+
+void CPWL_ListCtrl::OnMouseDown(const CFX_PointF& point,
+ bool bShift,
+ bool bCtrl) {
+ int32_t nHitIndex = GetItemIndex(point);
+
+ if (IsMultipleSel()) {
+ if (bCtrl) {
+ if (IsItemSelected(nHitIndex)) {
+ m_aSelItems.Sub(nHitIndex);
+ SelectItems();
+ m_bCtrlSel = false;
+ } else {
+ m_aSelItems.Add(nHitIndex);
+ SelectItems();
+ m_bCtrlSel = true;
+ }
+
+ m_nFootIndex = nHitIndex;
+ } else if (bShift) {
+ m_aSelItems.DeselectAll();
+ m_aSelItems.Add(m_nFootIndex, nHitIndex);
+ SelectItems();
+ } else {
+ m_aSelItems.DeselectAll();
+ m_aSelItems.Add(nHitIndex);
+ SelectItems();
+
+ m_nFootIndex = nHitIndex;
+ }
+
+ SetCaret(nHitIndex);
+ } else {
+ SetSingleSelect(nHitIndex);
+ }
+
+ if (!IsItemVisible(nHitIndex))
+ ScrollToListItem(nHitIndex);
+}
+
+void CPWL_ListCtrl::OnMouseMove(const CFX_PointF& point,
+ bool bShift,
+ bool bCtrl) {
+ int32_t nHitIndex = GetItemIndex(point);
+
+ if (IsMultipleSel()) {
+ if (bCtrl) {
+ if (m_bCtrlSel)
+ m_aSelItems.Add(m_nFootIndex, nHitIndex);
+ else
+ m_aSelItems.Sub(m_nFootIndex, nHitIndex);
+
+ SelectItems();
+ } else {
+ m_aSelItems.DeselectAll();
+ m_aSelItems.Add(m_nFootIndex, nHitIndex);
+ SelectItems();
+ }
+
+ SetCaret(nHitIndex);
+ } else {
+ SetSingleSelect(nHitIndex);
+ }
+
+ if (!IsItemVisible(nHitIndex))
+ ScrollToListItem(nHitIndex);
+}
+
+void CPWL_ListCtrl::OnVK(int32_t nItemIndex, bool bShift, bool bCtrl) {
+ if (IsMultipleSel()) {
+ if (nItemIndex >= 0 && nItemIndex < GetCount()) {
+ if (bCtrl) {
+ } else if (bShift) {
+ m_aSelItems.DeselectAll();
+ m_aSelItems.Add(m_nFootIndex, nItemIndex);
+ SelectItems();
+ } else {
+ m_aSelItems.DeselectAll();
+ m_aSelItems.Add(nItemIndex);
+ SelectItems();
+ m_nFootIndex = nItemIndex;
+ }
+
+ SetCaret(nItemIndex);
+ }
+ } else {
+ SetSingleSelect(nItemIndex);
+ }
+
+ if (!IsItemVisible(nItemIndex))
+ ScrollToListItem(nItemIndex);
+}
+
+void CPWL_ListCtrl::OnVK_UP(bool bShift, bool bCtrl) {
+ OnVK(IsMultipleSel() ? GetCaret() - 1 : GetSelect() - 1, bShift, bCtrl);
+}
+
+void CPWL_ListCtrl::OnVK_DOWN(bool bShift, bool bCtrl) {
+ OnVK(IsMultipleSel() ? GetCaret() + 1 : GetSelect() + 1, bShift, bCtrl);
+}
+
+void CPWL_ListCtrl::OnVK_LEFT(bool bShift, bool bCtrl) {
+ OnVK(0, bShift, bCtrl);
+}
+
+void CPWL_ListCtrl::OnVK_RIGHT(bool bShift, bool bCtrl) {
+ OnVK(GetCount() - 1, bShift, bCtrl);
+}
+
+void CPWL_ListCtrl::OnVK_HOME(bool bShift, bool bCtrl) {
+ OnVK(0, bShift, bCtrl);
+}
+
+void CPWL_ListCtrl::OnVK_END(bool bShift, bool bCtrl) {
+ OnVK(GetCount() - 1, bShift, bCtrl);
+}
+
+bool CPWL_ListCtrl::OnChar(uint16_t nChar, bool bShift, bool bCtrl) {
+ int32_t nIndex = GetLastSelected();
+ int32_t nFindIndex = FindNext(nIndex, nChar);
+
+ if (nFindIndex != nIndex) {
+ OnVK(nFindIndex, bShift, bCtrl);
+ return true;
+ }
+ return false;
+}
+
+void CPWL_ListCtrl::SetPlateRect(const CFX_FloatRect& rect) {
+ m_rcPlate = rect;
+ m_ptScrollPos.x = rect.left;
+ SetScrollPos(CFX_PointF(rect.left, rect.top));
+ ReArrange(0);
+ InvalidateItem(-1);
+}
+
+CFX_FloatRect CPWL_ListCtrl::GetItemRect(int32_t nIndex) const {
+ return InToOut(GetItemRectInternal(nIndex));
+}
+
+CFX_FloatRect CPWL_ListCtrl::GetItemRectInternal(int32_t nIndex) const {
+ if (!pdfium::IndexInBounds(m_ListItems, nIndex) || !m_ListItems[nIndex])
+ return CFX_FloatRect();
+
+ CFX_FloatRect rcItem = m_ListItems[nIndex]->GetRect();
+ rcItem.left = 0.0f;
+ rcItem.right = m_rcPlate.Width();
+ return InnerToOuter(rcItem);
+}
+
+void CPWL_ListCtrl::AddString(const WideString& str) {
+ AddItem(str);
+ ReArrange(GetCount() - 1);
+}
+
+void CPWL_ListCtrl::SetMultipleSelect(int32_t nItemIndex, bool bSelected) {
+ if (!IsValid(nItemIndex))
+ return;
+
+ if (bSelected != IsItemSelected(nItemIndex)) {
+ if (bSelected) {
+ SetItemSelect(nItemIndex, true);
+ InvalidateItem(nItemIndex);
+ } else {
+ SetItemSelect(nItemIndex, false);
+ InvalidateItem(nItemIndex);
+ }
+ }
+}
+
+void CPWL_ListCtrl::SetSingleSelect(int32_t nItemIndex) {
+ if (!IsValid(nItemIndex))
+ return;
+
+ if (m_nSelItem != nItemIndex) {
+ if (m_nSelItem >= 0) {
+ SetItemSelect(m_nSelItem, false);
+ InvalidateItem(m_nSelItem);
+ }
+
+ SetItemSelect(nItemIndex, true);
+ InvalidateItem(nItemIndex);
+ m_nSelItem = nItemIndex;
+ }
+}
+
+void CPWL_ListCtrl::SetCaret(int32_t nItemIndex) {
+ if (!IsValid(nItemIndex))
+ return;
+
+ if (IsMultipleSel()) {
+ int32_t nOldIndex = m_nCaretIndex;
+
+ if (nOldIndex != nItemIndex) {
+ m_nCaretIndex = nItemIndex;
+ InvalidateItem(nOldIndex);
+ InvalidateItem(nItemIndex);
+ }
+ }
+}
+
+void CPWL_ListCtrl::InvalidateItem(int32_t nItemIndex) {
+ if (m_pNotify) {
+ if (nItemIndex == -1) {
+ if (!m_bNotifyFlag) {
+ m_bNotifyFlag = true;
+ CFX_FloatRect rcRefresh = m_rcPlate;
+ m_pNotify->IOnInvalidateRect(&rcRefresh);
+ m_bNotifyFlag = false;
+ }
+ } else {
+ if (!m_bNotifyFlag) {
+ m_bNotifyFlag = true;
+ CFX_FloatRect rcRefresh = GetItemRect(nItemIndex);
+ rcRefresh.left -= 1.0f;
+ rcRefresh.right += 1.0f;
+ rcRefresh.bottom -= 1.0f;
+ rcRefresh.top += 1.0f;
+
+ m_pNotify->IOnInvalidateRect(&rcRefresh);
+ m_bNotifyFlag = false;
+ }
+ }
+ }
+}
+
+void CPWL_ListCtrl::SelectItems() {
+ for (const auto& item : m_aSelItems) {
+ if (item.second != CPLST_Select::NORMAL)
+ SetMultipleSelect(item.first, item.second == CPLST_Select::SELECTING);
+ }
+ m_aSelItems.Done();
+}
+
+void CPWL_ListCtrl::Select(int32_t nItemIndex) {
+ if (!IsValid(nItemIndex))
+ return;
+
+ if (IsMultipleSel()) {
+ m_aSelItems.Add(nItemIndex);
+ SelectItems();
+ } else {
+ SetSingleSelect(nItemIndex);
+ }
+}
+
+bool CPWL_ListCtrl::IsItemVisible(int32_t nItemIndex) const {
+ CFX_FloatRect rcPlate = m_rcPlate;
+ CFX_FloatRect rcItem = GetItemRect(nItemIndex);
+
+ return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top;
+}
+
+void CPWL_ListCtrl::ScrollToListItem(int32_t nItemIndex) {
+ if (!IsValid(nItemIndex))
+ return;
+
+ CFX_FloatRect rcPlate = m_rcPlate;
+ CFX_FloatRect rcItem = GetItemRectInternal(nItemIndex);
+ CFX_FloatRect rcItemCtrl = GetItemRect(nItemIndex);
+
+ if (IsFloatSmaller(rcItemCtrl.bottom, rcPlate.bottom)) {
+ if (IsFloatSmaller(rcItemCtrl.top, rcPlate.top)) {
+ SetScrollPosY(rcItem.bottom + rcPlate.Height());
+ }
+ } else if (IsFloatBigger(rcItemCtrl.top, rcPlate.top)) {
+ if (IsFloatBigger(rcItemCtrl.bottom, rcPlate.bottom)) {
+ SetScrollPosY(rcItem.top);
+ }
+ }
+}
+
+void CPWL_ListCtrl::SetScrollInfo() {
+ if (m_pNotify) {
+ CFX_FloatRect rcPlate = m_rcPlate;
+ CFX_FloatRect rcContent = GetContentRectInternal();
+
+ if (!m_bNotifyFlag) {
+ m_bNotifyFlag = true;
+ m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top,
+ rcContent.bottom, rcContent.top,
+ GetFirstHeight(), rcPlate.Height());
+ m_bNotifyFlag = false;
+ }
+ }
+}
+
+void CPWL_ListCtrl::SetScrollPos(const CFX_PointF& point) {
+ SetScrollPosY(point.y);
+}
+
+void CPWL_ListCtrl::SetScrollPosY(float fy) {
+ if (!IsFloatEqual(m_ptScrollPos.y, fy)) {
+ CFX_FloatRect rcPlate = m_rcPlate;
+ CFX_FloatRect rcContent = GetContentRectInternal();
+
+ if (rcPlate.Height() > rcContent.Height()) {
+ fy = rcPlate.top;
+ } else {
+ if (IsFloatSmaller(fy - rcPlate.Height(), rcContent.bottom)) {
+ fy = rcContent.bottom + rcPlate.Height();
+ } else if (IsFloatBigger(fy, rcContent.top)) {
+ fy = rcContent.top;
+ }
+ }
+
+ m_ptScrollPos.y = fy;
+ InvalidateItem(-1);
+
+ if (m_pNotify) {
+ if (!m_bNotifyFlag) {
+ m_bNotifyFlag = true;
+ m_pNotify->IOnSetScrollPosY(fy);
+ m_bNotifyFlag = false;
+ }
+ }
+ }
+}
+
+CFX_FloatRect CPWL_ListCtrl::GetContentRectInternal() const {
+ return InnerToOuter(m_rcContent);
+}
+
+CFX_FloatRect CPWL_ListCtrl::GetContentRect() const {
+ return InToOut(GetContentRectInternal());
+}
+
+void CPWL_ListCtrl::ReArrange(int32_t nItemIndex) {
+ float fPosY = 0.0f;
+ if (pdfium::IndexInBounds(m_ListItems, nItemIndex - 1) &&
+ m_ListItems[nItemIndex - 1]) {
+ fPosY = m_ListItems[nItemIndex - 1]->GetRect().bottom;
+ }
+ for (const auto& pListItem : m_ListItems) {
+ if (pListItem) {
+ float fListItemHeight = pListItem->GetItemHeight();
+ pListItem->SetRect(
+ CFX_FloatRect(0.0f, fPosY + fListItemHeight, 0.0f, fPosY));
+ fPosY += fListItemHeight;
+ }
+ }
+ SetContentRect(CFX_FloatRect(0.0f, fPosY, 0.0f, 0.0f));
+ SetScrollInfo();
+}
+
+void CPWL_ListCtrl::SetTopItem(int32_t nIndex) {
+ if (IsValid(nIndex)) {
+ CFX_FloatRect rcItem = GetItemRectInternal(nIndex);
+ SetScrollPosY(rcItem.top);
+ }
+}
+
+int32_t CPWL_ListCtrl::GetTopItem() const {
+ int32_t nItemIndex = GetItemIndex(GetBTPoint());
+ if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1))
+ nItemIndex += 1;
+
+ return nItemIndex;
+}
+
+void CPWL_ListCtrl::Empty() {
+ m_ListItems.clear();
+ InvalidateItem(-1);
+}
+
+void CPWL_ListCtrl::Cancel() {
+ m_aSelItems.DeselectAll();
+}
+
+int32_t CPWL_ListCtrl::GetItemIndex(const CFX_PointF& point) const {
+ CFX_PointF pt = OuterToInner(OutToIn(point));
+ bool bFirst = true;
+ bool bLast = true;
+ for (const auto& pListItem : m_ListItems) {
+ if (!pListItem)
+ continue;
+ CFX_FloatRect rcListItem = pListItem->GetRect();
+ if (IsFloatBigger(pt.y, rcListItem.top))
+ bFirst = false;
+ if (IsFloatSmaller(pt.y, rcListItem.bottom))
+ bLast = false;
+ if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom)
+ return &pListItem - &m_ListItems.front();
+ }
+ if (bFirst)
+ return 0;
+ if (bLast)
+ return pdfium::CollectionSize<int32_t>(m_ListItems) - 1;
+ return -1;
+}
+
+WideString CPWL_ListCtrl::GetText() const {
+ if (IsMultipleSel())
+ return GetItemText(m_nCaretIndex);
+ return GetItemText(m_nSelItem);
+}
+
+void CPWL_ListCtrl::AddItem(const WideString& str) {
+ auto pListItem = pdfium::MakeUnique<Item>();
+ pListItem->SetFontMap(m_pFontMap.Get());
+ pListItem->SetFontSize(m_fFontSize);
+ pListItem->SetText(str);
+ m_ListItems.push_back(std::move(pListItem));
+}
+
+CPWL_EditImpl* CPWL_ListCtrl::GetItemEdit(int32_t nIndex) const {
+ if (!pdfium::IndexInBounds(m_ListItems, nIndex) || !m_ListItems[nIndex])
+ return nullptr;
+ return m_ListItems[nIndex]->GetEdit();
+}
+
+int32_t CPWL_ListCtrl::GetCount() const {
+ return pdfium::CollectionSize<int32_t>(m_ListItems);
+}
+
+float CPWL_ListCtrl::GetFirstHeight() const {
+ if (m_ListItems.empty() || !m_ListItems.front())
+ return 1.0f;
+ return m_ListItems.front()->GetItemHeight();
+}
+
+int32_t CPWL_ListCtrl::GetFirstSelected() const {
+ int32_t i = 0;
+ for (const auto& pListItem : m_ListItems) {
+ if (pListItem && pListItem->IsSelected())
+ return i;
+ ++i;
+ }
+ return -1;
+}
+
+int32_t CPWL_ListCtrl::GetLastSelected() const {
+ for (auto iter = m_ListItems.rbegin(); iter != m_ListItems.rend(); ++iter) {
+ if (*iter && (*iter)->IsSelected())
+ return &*iter - &m_ListItems.front();
+ }
+ return -1;
+}
+
+int32_t CPWL_ListCtrl::FindNext(int32_t nIndex, wchar_t nChar) const {
+ int32_t nCircleIndex = nIndex;
+ int32_t sz = pdfium::CollectionSize<int32_t>(m_ListItems);
+ for (int32_t i = 0; i < sz; i++) {
+ nCircleIndex++;
+ if (nCircleIndex >= sz)
+ nCircleIndex = 0;
+
+ if (Item* pListItem = m_ListItems[nCircleIndex].get()) {
+ if (FXSYS_toupper(pListItem->GetFirstChar()) == FXSYS_toupper(nChar))
+ return nCircleIndex;
+ }
+ }
+
+ return nCircleIndex;
+}
+
+bool CPWL_ListCtrl::IsItemSelected(int32_t nIndex) const {
+ return pdfium::IndexInBounds(m_ListItems, nIndex) && m_ListItems[nIndex] &&
+ m_ListItems[nIndex]->IsSelected();
+}
+
+void CPWL_ListCtrl::SetItemSelect(int32_t nIndex, bool bSelected) {
+ if (pdfium::IndexInBounds(m_ListItems, nIndex) && m_ListItems[nIndex])
+ m_ListItems[nIndex]->SetSelect(bSelected);
+}
+
+bool CPWL_ListCtrl::IsValid(int32_t nItemIndex) const {
+ return pdfium::IndexInBounds(m_ListItems, nItemIndex);
+}
+
+WideString CPWL_ListCtrl::GetItemText(int32_t nIndex) const {
+ if (pdfium::IndexInBounds(m_ListItems, nIndex) && m_ListItems[nIndex])
+ return m_ListItems[nIndex]->GetText();
+ return L"";
+}
diff --git a/fpdfsdk/pwl/cpwl_list_impl.h b/fpdfsdk/pwl/cpwl_list_impl.h
new file mode 100644
index 0000000..e39a9c8
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_list_impl.h
@@ -0,0 +1,169 @@
+// Copyright 2014 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_PWL_CPWL_LIST_IMPL_H_
+#define FPDFSDK_PWL_CPWL_LIST_IMPL_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/unowned_ptr.h"
+
+class CPWL_EditImpl;
+class CPWL_EditImpl_Iterator;
+class CPWL_List_Notify;
+class IPVT_FontMap;
+
+class CPLST_Select {
+ public:
+ enum State { DESELECTING = -1, NORMAL = 0, SELECTING = 1 };
+ using const_iterator = std::map<int32_t, State>::const_iterator;
+
+ CPLST_Select();
+ virtual ~CPLST_Select();
+
+ void Add(int32_t nItemIndex);
+ void Add(int32_t nBeginIndex, int32_t nEndIndex);
+ void Sub(int32_t nItemIndex);
+ void Sub(int32_t nBeginIndex, int32_t nEndIndex);
+ void DeselectAll();
+ void Done();
+
+ const_iterator begin() const { return m_Items.begin(); }
+ const_iterator end() const { return m_Items.end(); }
+
+ private:
+ std::map<int32_t, State> m_Items;
+};
+
+class CPWL_ListCtrl {
+ public:
+ CPWL_ListCtrl();
+ ~CPWL_ListCtrl();
+
+ void SetNotify(CPWL_List_Notify* pNotify) { m_pNotify = pNotify; }
+ void OnMouseDown(const CFX_PointF& point, bool bShift, bool bCtrl);
+ void OnMouseMove(const CFX_PointF& point, bool bShift, bool bCtrl);
+ void OnVK_UP(bool bShift, bool bCtrl);
+ void OnVK_DOWN(bool bShift, bool bCtrl);
+ void OnVK_LEFT(bool bShift, bool bCtrl);
+ void OnVK_RIGHT(bool bShift, bool bCtrl);
+ void OnVK_HOME(bool bShift, bool bCtrl);
+ void OnVK_END(bool bShift, bool bCtrl);
+ bool OnChar(uint16_t nChar, bool bShift, bool bCtrl);
+
+ void SetScrollPos(const CFX_PointF& point);
+ void ScrollToListItem(int32_t nItemIndex);
+ CFX_FloatRect GetItemRect(int32_t nIndex) const;
+ int32_t GetCaret() const { return m_nCaretIndex; }
+ int32_t GetSelect() const { return m_nSelItem; }
+ int32_t GetTopItem() const;
+ void SetContentRect(const CFX_FloatRect& rect) { m_rcContent = rect; }
+ CFX_FloatRect GetContentRect() const;
+
+ int32_t GetItemIndex(const CFX_PointF& point) const;
+ void AddString(const WideString& str);
+ void SetTopItem(int32_t nIndex);
+ void Select(int32_t nItemIndex);
+ void SetCaret(int32_t nItemIndex);
+ void Empty();
+ void Cancel();
+ WideString GetText() const;
+
+ void SetFontMap(IPVT_FontMap* pFontMap) { m_pFontMap = pFontMap; }
+ void SetFontSize(float fFontSize) { m_fFontSize = fFontSize; }
+ CFX_FloatRect GetPlateRect() const { return m_rcPlate; }
+ void SetPlateRect(const CFX_FloatRect& rect);
+
+ float GetFontSize() const { return m_fFontSize; }
+ CPWL_EditImpl* GetItemEdit(int32_t nIndex) const;
+ int32_t GetCount() const;
+ bool IsItemSelected(int32_t nIndex) const;
+ float GetFirstHeight() const;
+ void SetMultipleSel(bool bMultiple) { m_bMultiple = bMultiple; }
+ bool IsMultipleSel() const { return m_bMultiple; }
+ int32_t FindNext(int32_t nIndex, wchar_t nChar) const;
+ int32_t GetFirstSelected() const;
+
+ private:
+ class Item {
+ public:
+ Item();
+ ~Item();
+
+ void SetFontMap(IPVT_FontMap* pFontMap);
+ CPWL_EditImpl* GetEdit() const { return m_pEdit.get(); }
+
+ void SetRect(const CFX_FloatRect& rect) { m_rcListItem = rect; }
+ void SetSelect(bool bSelected) { m_bSelected = bSelected; }
+ void SetText(const WideString& text);
+ void SetFontSize(float fFontSize);
+ WideString GetText() const;
+
+ CFX_FloatRect GetRect() const { return m_rcListItem; }
+ bool IsSelected() const { return m_bSelected; }
+ float GetItemHeight() const;
+ uint16_t GetFirstChar() const;
+
+ private:
+ CPWL_EditImpl_Iterator* GetIterator() const;
+
+ std::unique_ptr<CPWL_EditImpl> m_pEdit;
+ bool m_bSelected;
+ CFX_FloatRect m_rcListItem;
+ };
+
+ CFX_PointF InToOut(const CFX_PointF& point) const;
+ CFX_PointF OutToIn(const CFX_PointF& point) const;
+ CFX_FloatRect InToOut(const CFX_FloatRect& rect) const;
+ CFX_FloatRect OutToIn(const CFX_FloatRect& rect) const;
+
+ CFX_PointF InnerToOuter(const CFX_PointF& point) const;
+ CFX_PointF OuterToInner(const CFX_PointF& point) const;
+ CFX_FloatRect InnerToOuter(const CFX_FloatRect& rect) const;
+ CFX_FloatRect OuterToInner(const CFX_FloatRect& rect) const;
+
+ void OnVK(int32_t nItemIndex, bool bShift, bool bCtrl);
+ bool IsValid(int32_t nItemIndex) const;
+
+ void ReArrange(int32_t nItemIndex);
+ CFX_FloatRect GetItemRectInternal(int32_t nIndex) const;
+ CFX_FloatRect GetContentRectInternal() const;
+ void SetMultipleSelect(int32_t nItemIndex, bool bSelected);
+ void SetSingleSelect(int32_t nItemIndex);
+ void InvalidateItem(int32_t nItemIndex);
+ void SelectItems();
+ bool IsItemVisible(int32_t nItemIndex) const;
+ void SetScrollInfo();
+ void SetScrollPosY(float fy);
+ void AddItem(const WideString& str);
+ WideString GetItemText(int32_t nIndex) const;
+ void SetItemSelect(int32_t nItemIndex, bool bSelected);
+ int32_t GetLastSelected() const;
+ CFX_PointF GetBTPoint() const {
+ return CFX_PointF(m_rcPlate.left, m_rcPlate.top);
+ }
+
+ CFX_FloatRect m_rcPlate;
+ CFX_FloatRect m_rcContent;
+ UnownedPtr<CPWL_List_Notify> m_pNotify;
+ bool m_bNotifyFlag;
+ CFX_PointF m_ptScrollPos;
+ CPLST_Select m_aSelItems; // for multiple
+ int32_t m_nSelItem; // for single
+ int32_t m_nFootIndex; // for multiple
+ bool m_bCtrlSel; // for multiple
+ int32_t m_nCaretIndex; // for multiple
+ std::vector<std::unique_ptr<Item>> m_ListItems;
+ float m_fFontSize;
+ UnownedPtr<IPVT_FontMap> m_pFontMap;
+ bool m_bMultiple;
+};
+
+#endif // FPDFSDK_PWL_CPWL_LIST_IMPL_H_
diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.cpp b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
new file mode 100644
index 0000000..65a51e3
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
@@ -0,0 +1,930 @@
+// Copyright 2014 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/pwl/cpwl_scroll_bar.h"
+
+#include <algorithm>
+#include <sstream>
+#include <vector>
+
+#include "core/fxge/cfx_pathdata.h"
+#include "core/fxge/cfx_renderdevice.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+
+namespace {
+
+constexpr float kButtonWidth = 9.0f;
+constexpr float kPosButtonMinWidth = 2.0f;
+constexpr float kScrollBarTriangleHalfLength = 2.0f;
+
+} // namespace
+
+#define PWL_DEFAULT_HEAVYGRAYCOLOR CFX_Color(CFX_Color::kGray, 0.50)
+
+PWL_FLOATRANGE::PWL_FLOATRANGE() {
+ Default();
+}
+
+PWL_FLOATRANGE::PWL_FLOATRANGE(float min, float max) {
+ Set(min, max);
+}
+
+void PWL_FLOATRANGE::Default() {
+ fMin = 0;
+ fMax = 0;
+}
+
+void PWL_FLOATRANGE::Set(float min, float max) {
+ if (min > max) {
+ fMin = max;
+ fMax = min;
+ } else {
+ fMin = min;
+ fMax = max;
+ }
+}
+
+bool PWL_FLOATRANGE::In(float x) const {
+ return (IsFloatBigger(x, fMin) || IsFloatEqual(x, fMin)) &&
+ (IsFloatSmaller(x, fMax) || IsFloatEqual(x, fMax));
+}
+
+float PWL_FLOATRANGE::GetWidth() const {
+ return fMax - fMin;
+}
+
+PWL_SCROLL_PRIVATEDATA::PWL_SCROLL_PRIVATEDATA() {
+ Default();
+}
+
+void PWL_SCROLL_PRIVATEDATA::Default() {
+ ScrollRange.Default();
+ fScrollPos = ScrollRange.fMin;
+ fClientWidth = 0;
+ fBigStep = 10;
+ fSmallStep = 1;
+}
+
+void PWL_SCROLL_PRIVATEDATA::SetScrollRange(float min, float max) {
+ ScrollRange.Set(min, max);
+
+ if (IsFloatSmaller(fScrollPos, ScrollRange.fMin))
+ fScrollPos = ScrollRange.fMin;
+ if (IsFloatBigger(fScrollPos, ScrollRange.fMax))
+ fScrollPos = ScrollRange.fMax;
+}
+
+void PWL_SCROLL_PRIVATEDATA::SetClientWidth(float width) {
+ fClientWidth = width;
+}
+
+void PWL_SCROLL_PRIVATEDATA::SetSmallStep(float step) {
+ fSmallStep = step;
+}
+
+void PWL_SCROLL_PRIVATEDATA::SetBigStep(float step) {
+ fBigStep = step;
+}
+
+bool PWL_SCROLL_PRIVATEDATA::SetPos(float pos) {
+ if (ScrollRange.In(pos)) {
+ fScrollPos = pos;
+ return true;
+ }
+ return false;
+}
+
+void PWL_SCROLL_PRIVATEDATA::AddSmall() {
+ if (!SetPos(fScrollPos + fSmallStep))
+ SetPos(ScrollRange.fMax);
+}
+
+void PWL_SCROLL_PRIVATEDATA::SubSmall() {
+ if (!SetPos(fScrollPos - fSmallStep))
+ SetPos(ScrollRange.fMin);
+}
+
+void PWL_SCROLL_PRIVATEDATA::AddBig() {
+ if (!SetPos(fScrollPos + fBigStep))
+ SetPos(ScrollRange.fMax);
+}
+
+void PWL_SCROLL_PRIVATEDATA::SubBig() {
+ if (!SetPos(fScrollPos - fBigStep))
+ SetPos(ScrollRange.fMin);
+}
+
+CPWL_SBButton::CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType,
+ PWL_SBBUTTON_TYPE eButtonType) {
+ m_eScrollBarType = eScrollBarType;
+ m_eSBButtonType = eButtonType;
+
+ m_bMouseDown = false;
+}
+
+CPWL_SBButton::~CPWL_SBButton() {}
+
+ByteString CPWL_SBButton::GetClassName() const {
+ return "CPWL_SBButton";
+}
+
+void CPWL_SBButton::OnCreate(CreateParams* pParamsToAdjust) {
+ pParamsToAdjust->eCursorType = FXCT_ARROW;
+}
+
+void CPWL_SBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ if (!IsVisible())
+ return;
+
+ CFX_FloatRect rectWnd = GetWindowRect();
+ if (rectWnd.IsEmpty())
+ return;
+
+ CFX_PointF ptCenter = GetCenterPoint();
+ int32_t nTransparency = GetTransparency();
+
+ if (m_eScrollBarType == SBT_HSCROLL) {
+ CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device);
+
+ CFX_PointF pt1;
+ CFX_PointF pt2;
+ CFX_PointF pt3;
+ static constexpr float kScrollBarTriangleQuarterLength =
+ kScrollBarTriangleHalfLength * 0.5;
+ if (m_eSBButtonType == PSBT_MIN) {
+ pt1 =
+ CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength, ptCenter.y);
+ pt2 = CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength,
+ ptCenter.y + kScrollBarTriangleHalfLength);
+ pt3 = CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength,
+ ptCenter.y - kScrollBarTriangleHalfLength);
+ } else if (m_eSBButtonType == PSBT_MAX) {
+ pt1 =
+ CFX_PointF(ptCenter.x + kScrollBarTriangleQuarterLength, ptCenter.y);
+ pt2 = CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength,
+ ptCenter.y + kScrollBarTriangleHalfLength);
+ pt3 = CFX_PointF(ptCenter.x - kScrollBarTriangleQuarterLength,
+ ptCenter.y - kScrollBarTriangleHalfLength);
+ }
+
+ if (rectWnd.right - rectWnd.left > kScrollBarTriangleHalfLength * 2 &&
+ rectWnd.top - rectWnd.bottom > kScrollBarTriangleHalfLength) {
+ CFX_PathData path;
+ path.AppendPoint(pt1, FXPT_TYPE::MoveTo, false);
+ path.AppendPoint(pt2, FXPT_TYPE::LineTo, false);
+ path.AppendPoint(pt3, FXPT_TYPE::LineTo, false);
+ path.AppendPoint(pt1, FXPT_TYPE::LineTo, false);
+
+ pDevice->DrawPath(&path, &mtUser2Device, nullptr,
+ PWL_DEFAULT_BLACKCOLOR.ToFXColor(nTransparency), 0,
+ FXFILL_ALTERNATE);
+ }
+ return;
+ }
+
+ // draw border
+ pDevice->DrawStrokeRect(&mtUser2Device, rectWnd,
+ ArgbEncode(nTransparency, 100, 100, 100), 0.0f);
+ pDevice->DrawStrokeRect(&mtUser2Device, rectWnd.GetDeflated(0.5f, 0.5f),
+ ArgbEncode(nTransparency, 255, 255, 255), 1.0f);
+
+ if (m_eSBButtonType != PSBT_POS) {
+ // draw background
+ if (IsEnabled()) {
+ pDevice->DrawShadow(&mtUser2Device, true, false,
+ rectWnd.GetDeflated(1.0f, 1.0f), nTransparency, 80,
+ 220);
+ } else {
+ pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(1.0f, 1.0f),
+ ArgbEncode(255, 255, 255, 255));
+ }
+
+ // draw arrow
+ if (rectWnd.top - rectWnd.bottom > 6.0f) {
+ float fX = rectWnd.left + 1.5f;
+ float fY = rectWnd.bottom;
+ std::vector<CFX_PointF> pts;
+ if (m_eSBButtonType == PSBT_MIN) {
+ pts.push_back(CFX_PointF(fX + 2.5f, fY + 4.0f));
+ pts.push_back(CFX_PointF(fX + 2.5f, fY + 3.0f));
+ pts.push_back(CFX_PointF(fX + 4.5f, fY + 5.0f));
+ pts.push_back(CFX_PointF(fX + 6.5f, fY + 3.0f));
+ pts.push_back(CFX_PointF(fX + 6.5f, fY + 4.0f));
+ pts.push_back(CFX_PointF(fX + 4.5f, fY + 6.0f));
+ pts.push_back(CFX_PointF(fX + 2.5f, fY + 4.0f));
+ } else {
+ pts.push_back(CFX_PointF(fX + 2.5f, fY + 5.0f));
+ pts.push_back(CFX_PointF(fX + 2.5f, fY + 6.0f));
+ pts.push_back(CFX_PointF(fX + 4.5f, fY + 4.0f));
+ pts.push_back(CFX_PointF(fX + 6.5f, fY + 6.0f));
+ pts.push_back(CFX_PointF(fX + 6.5f, fY + 5.0f));
+ pts.push_back(CFX_PointF(fX + 4.5f, fY + 3.0f));
+ pts.push_back(CFX_PointF(fX + 2.5f, fY + 5.0f));
+ }
+ pDevice->DrawFillArea(&mtUser2Device, pts.data(), 7,
+ IsEnabled()
+ ? ArgbEncode(nTransparency, 255, 255, 255)
+ : PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255));
+ }
+ return;
+ }
+
+ if (IsEnabled()) {
+ // draw shadow effect
+ CFX_PointF ptTop = CFX_PointF(rectWnd.left, rectWnd.top - 1.0f);
+ CFX_PointF ptBottom = CFX_PointF(rectWnd.left, rectWnd.bottom + 1.0f);
+
+ ptTop.x += 1.5f;
+ ptBottom.x += 1.5f;
+
+ const FX_COLORREF refs[] = {ArgbEncode(nTransparency, 210, 210, 210),
+ ArgbEncode(nTransparency, 220, 220, 220),
+ ArgbEncode(nTransparency, 240, 240, 240),
+ ArgbEncode(nTransparency, 240, 240, 240),
+ ArgbEncode(nTransparency, 210, 210, 210),
+ ArgbEncode(nTransparency, 180, 180, 180),
+ ArgbEncode(nTransparency, 150, 150, 150),
+ ArgbEncode(nTransparency, 150, 150, 150),
+ ArgbEncode(nTransparency, 180, 180, 180),
+ ArgbEncode(nTransparency, 210, 210, 210)};
+ for (FX_COLORREF ref : refs) {
+ pDevice->DrawStrokeLine(&mtUser2Device, ptTop, ptBottom, ref, 1.0f);
+
+ ptTop.x += 1.0f;
+ ptBottom.x += 1.0f;
+ }
+ } else {
+ pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(0.5f, 0.5f),
+ ArgbEncode(255, 255, 255, 255));
+ }
+
+ // draw friction
+ if (rectWnd.Height() <= 8.0f)
+ return;
+
+ FX_COLORREF crStroke = ArgbEncode(nTransparency, 120, 120, 120);
+ if (!IsEnabled())
+ crStroke = PWL_DEFAULT_HEAVYGRAYCOLOR.ToFXColor(255);
+
+ float nFrictionWidth = 5.0f;
+ float nFrictionHeight = 5.5f;
+
+ CFX_PointF ptLeft = CFX_PointF(ptCenter.x - nFrictionWidth / 2.0f,
+ ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
+ CFX_PointF ptRight = CFX_PointF(ptCenter.x + nFrictionWidth / 2.0f,
+ ptCenter.y - nFrictionHeight / 2.0f + 0.5f);
+
+ for (size_t i = 0; i < 3; ++i) {
+ pDevice->DrawStrokeLine(&mtUser2Device, ptLeft, ptRight, crStroke, 1.0f);
+ ptLeft.y += 2.0f;
+ ptRight.y += 2.0f;
+ }
+}
+
+bool CPWL_SBButton::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonDown(point, nFlag);
+
+ if (CPWL_Wnd* pParent = GetParentWindow())
+ pParent->NotifyLButtonDown(this, point);
+
+ m_bMouseDown = true;
+ SetCapture();
+
+ return true;
+}
+
+bool CPWL_SBButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonUp(point, nFlag);
+
+ if (CPWL_Wnd* pParent = GetParentWindow())
+ pParent->NotifyLButtonUp(this, point);
+
+ m_bMouseDown = false;
+ ReleaseCapture();
+
+ return true;
+}
+
+bool CPWL_SBButton::OnMouseMove(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnMouseMove(point, nFlag);
+
+ if (CPWL_Wnd* pParent = GetParentWindow())
+ pParent->NotifyMouseMove(this, point);
+
+ return true;
+}
+
+CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType)
+ : m_sbType(sbType),
+ m_pMinButton(nullptr),
+ m_pMaxButton(nullptr),
+ m_pPosButton(nullptr),
+ m_bMouseDown(false),
+ m_bMinOrMax(false),
+ m_bNotifyForever(true) {}
+
+CPWL_ScrollBar::~CPWL_ScrollBar() {}
+
+ByteString CPWL_ScrollBar::GetClassName() const {
+ return "CPWL_ScrollBar";
+}
+
+void CPWL_ScrollBar::OnCreate(CreateParams* pParamsToAdjust) {
+ pParamsToAdjust->eCursorType = FXCT_ARROW;
+}
+
+void CPWL_ScrollBar::OnDestroy() {
+ // Until cleanup takes place in the virtual destructor for CPWL_Wnd
+ // subclasses, implement the virtual OnDestroy method that does the
+ // cleanup first, then invokes the superclass OnDestroy ... gee,
+ // like a dtor would.
+ m_pMinButton.Release();
+ m_pMaxButton.Release();
+ m_pPosButton.Release();
+ CPWL_Wnd::OnDestroy();
+}
+
+bool CPWL_ScrollBar::RePosChildWnd() {
+ CFX_FloatRect rcClient = GetClientRect();
+ CFX_FloatRect rcMinButton, rcMaxButton;
+ float fBWidth = 0;
+
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ if (rcClient.right - rcClient.left >
+ kButtonWidth * 2 + kPosButtonMinWidth + 2) {
+ rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
+ rcClient.left + kButtonWidth, rcClient.top);
+ rcMaxButton =
+ CFX_FloatRect(rcClient.right - kButtonWidth, rcClient.bottom,
+ rcClient.right, rcClient.top);
+ } else {
+ fBWidth = (rcClient.right - rcClient.left - kPosButtonMinWidth - 2) / 2;
+
+ if (fBWidth > 0) {
+ rcMinButton = CFX_FloatRect(rcClient.left, rcClient.bottom,
+ rcClient.left + fBWidth, rcClient.top);
+ rcMaxButton = CFX_FloatRect(rcClient.right - fBWidth, rcClient.bottom,
+ rcClient.right, rcClient.top);
+ } else {
+ if (!SetVisible(false))
+ return false;
+ }
+ }
+ break;
+ case SBT_VSCROLL:
+ if (IsFloatBigger(rcClient.top - rcClient.bottom,
+ kButtonWidth * 2 + kPosButtonMinWidth + 2)) {
+ rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - kButtonWidth,
+ rcClient.right, rcClient.top);
+ rcMaxButton =
+ CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
+ rcClient.bottom + kButtonWidth);
+ } else {
+ fBWidth = (rcClient.top - rcClient.bottom - kPosButtonMinWidth - 2) / 2;
+
+ if (IsFloatBigger(fBWidth, 0)) {
+ rcMinButton = CFX_FloatRect(rcClient.left, rcClient.top - fBWidth,
+ rcClient.right, rcClient.top);
+ rcMaxButton =
+ CFX_FloatRect(rcClient.left, rcClient.bottom, rcClient.right,
+ rcClient.bottom + fBWidth);
+ } else {
+ if (!SetVisible(false))
+ return false;
+ }
+ }
+ break;
+ }
+
+ ObservedPtr thisObserved(this);
+
+ if (m_pMinButton) {
+ m_pMinButton->Move(rcMinButton, true, false);
+ if (!thisObserved)
+ return false;
+ }
+
+ if (m_pMaxButton) {
+ m_pMaxButton->Move(rcMaxButton, true, false);
+ if (!thisObserved)
+ return false;
+ }
+
+ if (!MovePosButton(false))
+ return false;
+
+ return true;
+}
+
+void CPWL_ScrollBar::DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ CFX_FloatRect rectWnd = GetWindowRect();
+
+ if (IsVisible() && !rectWnd.IsEmpty()) {
+ pDevice->DrawFillRect(&mtUser2Device, rectWnd, GetBackgroundColor(),
+ GetTransparency());
+
+ pDevice->DrawStrokeLine(
+ &mtUser2Device, CFX_PointF(rectWnd.left + 2.0f, rectWnd.top - 2.0f),
+ CFX_PointF(rectWnd.left + 2.0f, rectWnd.bottom + 2.0f),
+ ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
+
+ pDevice->DrawStrokeLine(
+ &mtUser2Device, CFX_PointF(rectWnd.right - 2.0f, rectWnd.top - 2.0f),
+ CFX_PointF(rectWnd.right - 2.0f, rectWnd.bottom + 2.0f),
+ ArgbEncode(GetTransparency(), 100, 100, 100), 1.0f);
+ }
+}
+
+bool CPWL_ScrollBar::OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonDown(point, nFlag);
+
+ if (HasFlag(PWS_AUTOTRANSPARENT)) {
+ if (GetTransparency() != 255) {
+ SetTransparency(255);
+ if (!InvalidateRect(nullptr))
+ return true;
+ }
+ }
+
+ CFX_FloatRect rcMinArea, rcMaxArea;
+
+ if (m_pPosButton && m_pPosButton->IsVisible()) {
+ CFX_FloatRect rcClient = GetClientRect();
+ CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
+
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ rcMinArea = CFX_FloatRect(rcClient.left + kButtonWidth, rcClient.bottom,
+ rcPosButton.left, rcClient.top);
+ rcMaxArea = CFX_FloatRect(rcPosButton.right, rcClient.bottom,
+ rcClient.right - kButtonWidth, rcClient.top);
+
+ break;
+ case SBT_VSCROLL:
+ rcMinArea = CFX_FloatRect(rcClient.left, rcPosButton.top,
+ rcClient.right, rcClient.top - kButtonWidth);
+ rcMaxArea = CFX_FloatRect(rcClient.left, rcClient.bottom + kButtonWidth,
+ rcClient.right, rcPosButton.bottom);
+ break;
+ }
+
+ rcMinArea.Normalize();
+ rcMaxArea.Normalize();
+
+ if (rcMinArea.Contains(point)) {
+ m_sData.SubBig();
+ if (!MovePosButton(true))
+ return true;
+ NotifyScrollWindow();
+ }
+
+ if (rcMaxArea.Contains(point)) {
+ m_sData.AddBig();
+ if (!MovePosButton(true))
+ return true;
+ NotifyScrollWindow();
+ }
+ }
+
+ return true;
+}
+
+bool CPWL_ScrollBar::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
+ CPWL_Wnd::OnLButtonUp(point, nFlag);
+
+ if (HasFlag(PWS_AUTOTRANSPARENT)) {
+ if (GetTransparency() != PWL_SCROLLBAR_TRANSPARENCY) {
+ SetTransparency(PWL_SCROLLBAR_TRANSPARENCY);
+ if (!InvalidateRect(nullptr))
+ return true;
+ }
+ }
+
+ EndTimer();
+ m_bMouseDown = false;
+
+ return true;
+}
+
+void CPWL_ScrollBar::SetScrollInfo(const PWL_SCROLL_INFO& info) {
+ if (info == m_OriginInfo)
+ return;
+
+ m_OriginInfo = info;
+ float fMax =
+ std::max(0.0f, info.fContentMax - info.fContentMin - info.fPlateWidth);
+ SetScrollRange(0, fMax, info.fPlateWidth);
+ SetScrollStep(info.fBigStep, info.fSmallStep);
+}
+
+void CPWL_ScrollBar::SetScrollPosition(float pos) {
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ pos = pos - m_OriginInfo.fContentMin;
+ break;
+ case SBT_VSCROLL:
+ pos = m_OriginInfo.fContentMax - pos;
+ break;
+ }
+ SetScrollPos(pos);
+}
+
+void CPWL_ScrollBar::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
+ if (child == m_pMinButton)
+ OnMinButtonLBDown(pos);
+ else if (child == m_pMaxButton)
+ OnMaxButtonLBDown(pos);
+ else if (child == m_pPosButton)
+ OnPosButtonLBDown(pos);
+}
+
+void CPWL_ScrollBar::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
+ if (child == m_pMinButton)
+ OnMinButtonLBUp(pos);
+ else if (child == m_pMaxButton)
+ OnMaxButtonLBUp(pos);
+ else if (child == m_pPosButton)
+ OnPosButtonLBUp(pos);
+}
+
+void CPWL_ScrollBar::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) {
+ if (child == m_pMinButton)
+ OnMinButtonMouseMove(pos);
+ else if (child == m_pMaxButton)
+ OnMaxButtonMouseMove(pos);
+ else if (child == m_pPosButton)
+ OnPosButtonMouseMove(pos);
+}
+
+void CPWL_ScrollBar::CreateButtons(const CreateParams& cp) {
+ CreateParams scp = cp;
+ scp.pParentWnd = this;
+ scp.dwBorderWidth = 2;
+ scp.nBorderStyle = BorderStyle::BEVELED;
+
+ scp.dwFlags =
+ PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP;
+
+ if (!m_pMinButton) {
+ m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN);
+ m_pMinButton->Create(scp);
+ }
+
+ if (!m_pMaxButton) {
+ m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX);
+ m_pMaxButton->Create(scp);
+ }
+
+ if (!m_pPosButton) {
+ m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS);
+
+ ObservedPtr thisObserved(this);
+ if (!m_pPosButton->SetVisible(false) || !thisObserved)
+ return;
+ m_pPosButton->Create(scp);
+ }
+}
+
+float CPWL_ScrollBar::GetScrollBarWidth() const {
+ if (!IsVisible())
+ return 0;
+
+ return PWL_SCROLLBAR_WIDTH;
+}
+
+void CPWL_ScrollBar::SetScrollRange(float fMin,
+ float fMax,
+ float fClientWidth) {
+ if (!m_pPosButton)
+ return;
+
+ m_sData.SetScrollRange(fMin, fMax);
+ m_sData.SetClientWidth(fClientWidth);
+
+ ObservedPtr thisObserved(this);
+
+ if (IsFloatSmaller(m_sData.ScrollRange.GetWidth(), 0.0f)) {
+ m_pPosButton->SetVisible(false);
+ // Note, |this| may no longer be viable at this point. If more work needs
+ // to be done, check thisObserved.
+ return;
+ }
+
+ if (!m_pPosButton->SetVisible(true) || !thisObserved)
+ return;
+
+ MovePosButton(true);
+ // Note, |this| may no longer be viable at this point. If more work needs
+ // to be done, check the return value of MovePosButton().
+}
+
+void CPWL_ScrollBar::SetScrollPos(float fPos) {
+ float fOldPos = m_sData.fScrollPos;
+ m_sData.SetPos(fPos);
+ if (!IsFloatEqual(m_sData.fScrollPos, fOldPos)) {
+ MovePosButton(true);
+ // Note, |this| may no longer be viable at this point. If more work needs
+ // to be done, check the return value of MovePosButton().
+ }
+}
+
+void CPWL_ScrollBar::SetScrollStep(float fBigStep, float fSmallStep) {
+ m_sData.SetBigStep(fBigStep);
+ m_sData.SetSmallStep(fSmallStep);
+}
+
+bool CPWL_ScrollBar::MovePosButton(bool bRefresh) {
+ ASSERT(m_pMinButton);
+ ASSERT(m_pMaxButton);
+
+ if (m_pPosButton->IsVisible()) {
+ CFX_FloatRect rcClient;
+ CFX_FloatRect rcPosArea, rcPosButton;
+
+ rcClient = GetClientRect();
+ rcPosArea = GetScrollArea();
+
+ float fLeft, fRight, fTop, fBottom;
+
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ fLeft = TrueToFace(m_sData.fScrollPos);
+ fRight = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
+
+ if (fRight - fLeft < kPosButtonMinWidth)
+ fRight = fLeft + kPosButtonMinWidth;
+
+ if (fRight > rcPosArea.right) {
+ fRight = rcPosArea.right;
+ fLeft = fRight - kPosButtonMinWidth;
+ }
+
+ rcPosButton =
+ CFX_FloatRect(fLeft, rcPosArea.bottom, fRight, rcPosArea.top);
+
+ break;
+ case SBT_VSCROLL:
+ fBottom = TrueToFace(m_sData.fScrollPos + m_sData.fClientWidth);
+ fTop = TrueToFace(m_sData.fScrollPos);
+
+ if (IsFloatSmaller(fTop - fBottom, kPosButtonMinWidth))
+ fBottom = fTop - kPosButtonMinWidth;
+
+ if (IsFloatSmaller(fBottom, rcPosArea.bottom)) {
+ fBottom = rcPosArea.bottom;
+ fTop = fBottom + kPosButtonMinWidth;
+ }
+
+ rcPosButton =
+ CFX_FloatRect(rcPosArea.left, fBottom, rcPosArea.right, fTop);
+
+ break;
+ }
+
+ ObservedPtr thisObserved(this);
+
+ m_pPosButton->Move(rcPosButton, true, bRefresh);
+ if (!thisObserved)
+ return false;
+ }
+
+ return true;
+}
+
+void CPWL_ScrollBar::OnMinButtonLBDown(const CFX_PointF& point) {
+ m_sData.SubSmall();
+ if (!MovePosButton(true))
+ return;
+ NotifyScrollWindow();
+
+ m_bMinOrMax = true;
+
+ EndTimer();
+ BeginTimer(100);
+}
+
+void CPWL_ScrollBar::OnMinButtonLBUp(const CFX_PointF& point) {}
+
+void CPWL_ScrollBar::OnMinButtonMouseMove(const CFX_PointF& point) {}
+
+void CPWL_ScrollBar::OnMaxButtonLBDown(const CFX_PointF& point) {
+ m_sData.AddSmall();
+ if (!MovePosButton(true))
+ return;
+ NotifyScrollWindow();
+
+ m_bMinOrMax = false;
+
+ EndTimer();
+ BeginTimer(100);
+}
+
+void CPWL_ScrollBar::OnMaxButtonLBUp(const CFX_PointF& point) {}
+
+void CPWL_ScrollBar::OnMaxButtonMouseMove(const CFX_PointF& point) {}
+
+void CPWL_ScrollBar::OnPosButtonLBDown(const CFX_PointF& point) {
+ m_bMouseDown = true;
+
+ if (m_pPosButton) {
+ CFX_FloatRect rcPosButton = m_pPosButton->GetWindowRect();
+
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ m_nOldPos = point.x;
+ m_fOldPosButton = rcPosButton.left;
+ break;
+ case SBT_VSCROLL:
+ m_nOldPos = point.y;
+ m_fOldPosButton = rcPosButton.top;
+ break;
+ }
+ }
+}
+
+void CPWL_ScrollBar::OnPosButtonLBUp(const CFX_PointF& point) {
+ if (m_bMouseDown) {
+ if (!m_bNotifyForever)
+ NotifyScrollWindow();
+ }
+ m_bMouseDown = false;
+}
+
+void CPWL_ScrollBar::OnPosButtonMouseMove(const CFX_PointF& point) {
+ float fOldScrollPos = m_sData.fScrollPos;
+
+ float fNewPos = 0;
+
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ if (fabs(point.x - m_nOldPos) < 1)
+ return;
+ fNewPos = FaceToTrue(m_fOldPosButton + point.x - m_nOldPos);
+ break;
+ case SBT_VSCROLL:
+ if (fabs(point.y - m_nOldPos) < 1)
+ return;
+ fNewPos = FaceToTrue(m_fOldPosButton + point.y - m_nOldPos);
+ break;
+ }
+
+ if (m_bMouseDown) {
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+
+ if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
+ fNewPos = m_sData.ScrollRange.fMin;
+ }
+
+ if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
+ fNewPos = m_sData.ScrollRange.fMax;
+ }
+
+ m_sData.SetPos(fNewPos);
+
+ break;
+ case SBT_VSCROLL:
+
+ if (IsFloatSmaller(fNewPos, m_sData.ScrollRange.fMin)) {
+ fNewPos = m_sData.ScrollRange.fMin;
+ }
+
+ if (IsFloatBigger(fNewPos, m_sData.ScrollRange.fMax)) {
+ fNewPos = m_sData.ScrollRange.fMax;
+ }
+
+ m_sData.SetPos(fNewPos);
+
+ break;
+ }
+
+ if (!IsFloatEqual(fOldScrollPos, m_sData.fScrollPos)) {
+ if (!MovePosButton(true))
+ return;
+
+ if (m_bNotifyForever)
+ NotifyScrollWindow();
+ }
+ }
+}
+
+void CPWL_ScrollBar::NotifyScrollWindow() {
+ CPWL_Wnd* pParent = GetParentWindow();
+ if (!pParent || m_sbType != SBT_VSCROLL)
+ return;
+
+ pParent->ScrollWindowVertically(m_OriginInfo.fContentMax -
+ m_sData.fScrollPos);
+}
+
+CFX_FloatRect CPWL_ScrollBar::GetScrollArea() const {
+ CFX_FloatRect rcClient = GetClientRect();
+ CFX_FloatRect rcArea;
+
+ if (!m_pMinButton || !m_pMaxButton)
+ return rcClient;
+
+ CFX_FloatRect rcMin = m_pMinButton->GetWindowRect();
+ CFX_FloatRect rcMax = m_pMaxButton->GetWindowRect();
+
+ float fMinWidth = rcMin.right - rcMin.left;
+ float fMinHeight = rcMin.top - rcMin.bottom;
+ float fMaxWidth = rcMax.right - rcMax.left;
+ float fMaxHeight = rcMax.top - rcMax.bottom;
+
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ if (rcClient.right - rcClient.left > fMinWidth + fMaxWidth + 2) {
+ rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
+ rcClient.right - fMaxWidth - 1, rcClient.top);
+ } else {
+ rcArea = CFX_FloatRect(rcClient.left + fMinWidth + 1, rcClient.bottom,
+ rcClient.left + fMinWidth + 1, rcClient.top);
+ }
+ break;
+ case SBT_VSCROLL:
+ if (rcClient.top - rcClient.bottom > fMinHeight + fMaxHeight + 2) {
+ rcArea = CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
+ rcClient.right, rcClient.top - fMaxHeight - 1);
+ } else {
+ rcArea =
+ CFX_FloatRect(rcClient.left, rcClient.bottom + fMinHeight + 1,
+ rcClient.right, rcClient.bottom + fMinHeight + 1);
+ }
+ break;
+ }
+
+ rcArea.Normalize();
+
+ return rcArea;
+}
+
+float CPWL_ScrollBar::TrueToFace(float fTrue) {
+ CFX_FloatRect rcPosArea;
+ rcPosArea = GetScrollArea();
+
+ float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
+ fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
+
+ float fFace = 0;
+
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ fFace = rcPosArea.left +
+ fTrue * (rcPosArea.right - rcPosArea.left) / fFactWidth;
+ break;
+ case SBT_VSCROLL:
+ fFace = rcPosArea.top -
+ fTrue * (rcPosArea.top - rcPosArea.bottom) / fFactWidth;
+ break;
+ }
+
+ return fFace;
+}
+
+float CPWL_ScrollBar::FaceToTrue(float fFace) {
+ CFX_FloatRect rcPosArea;
+ rcPosArea = GetScrollArea();
+
+ float fFactWidth = m_sData.ScrollRange.GetWidth() + m_sData.fClientWidth;
+ fFactWidth = fFactWidth == 0 ? 1 : fFactWidth;
+
+ float fTrue = 0;
+
+ switch (m_sbType) {
+ case SBT_HSCROLL:
+ fTrue = (fFace - rcPosArea.left) * fFactWidth /
+ (rcPosArea.right - rcPosArea.left);
+ break;
+ case SBT_VSCROLL:
+ fTrue = (rcPosArea.top - fFace) * fFactWidth /
+ (rcPosArea.top - rcPosArea.bottom);
+ break;
+ }
+
+ return fTrue;
+}
+
+void CPWL_ScrollBar::CreateChildWnd(const CreateParams& cp) {
+ CreateButtons(cp);
+}
+
+void CPWL_ScrollBar::TimerProc() {
+ PWL_SCROLL_PRIVATEDATA sTemp = m_sData;
+ if (m_bMinOrMax)
+ m_sData.SubSmall();
+ else
+ m_sData.AddSmall();
+
+ if (sTemp != m_sData) {
+ if (!MovePosButton(true))
+ return;
+ NotifyScrollWindow();
+ }
+}
diff --git a/fpdfsdk/pdfwindow/PWL_ScrollBar.h b/fpdfsdk/pwl/cpwl_scroll_bar.h
similarity index 63%
rename from fpdfsdk/pdfwindow/PWL_ScrollBar.h
rename to fpdfsdk/pwl/cpwl_scroll_bar.h
index 9546a9e..6921732 100644
--- a/fpdfsdk/pdfwindow/PWL_ScrollBar.h
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.h
@@ -4,10 +4,11 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#ifndef FPDFSDK_PDFWINDOW_PWL_SCROLLBAR_H_
-#define FPDFSDK_PDFWINDOW_PWL_SCROLLBAR_H_
+#ifndef FPDFSDK_PWL_CPWL_SCROLL_BAR_H_
+#define FPDFSDK_PWL_CPWL_SCROLL_BAR_H_
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
+#include "core/fxcrt/unowned_ptr.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
class CPWL_SBButton;
class CPWL_ScrollBar;
@@ -30,11 +31,11 @@
return !(*this == that);
}
- FX_FLOAT fContentMin;
- FX_FLOAT fContentMax;
- FX_FLOAT fPlateWidth;
- FX_FLOAT fBigStep;
- FX_FLOAT fSmallStep;
+ float fContentMin;
+ float fContentMax;
+ float fPlateWidth;
+ float fBigStep;
+ float fSmallStep;
};
enum PWL_SCROLLBAR_TYPE { SBT_HSCROLL, SBT_VSCROLL };
@@ -48,11 +49,10 @@
~CPWL_SBButton() override;
// CPWL_Wnd
- CFX_ByteString GetClassName() const override;
- void OnCreate(PWL_CREATEPARAM& cp) override;
- void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override;
+ ByteString GetClassName() const override;
+ void OnCreate(CreateParams* pParamsToAdjust) override;
void DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
+ const CFX_Matrix& mtUser2Device) override;
bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override;
@@ -67,7 +67,7 @@
struct PWL_FLOATRANGE {
public:
PWL_FLOATRANGE();
- PWL_FLOATRANGE(FX_FLOAT min, FX_FLOAT max);
+ PWL_FLOATRANGE(float min, float max);
bool operator==(const PWL_FLOATRANGE& that) const {
return fMin == that.fMin && fMax == that.fMax;
@@ -75,12 +75,12 @@
bool operator!=(const PWL_FLOATRANGE& that) const { return !(*this == that); }
void Default();
- void Set(FX_FLOAT min, FX_FLOAT max);
- bool In(FX_FLOAT x) const;
- FX_FLOAT GetWidth() const;
+ void Set(float min, float max);
+ bool In(float x) const;
+ float GetWidth() const;
- FX_FLOAT fMin;
- FX_FLOAT fMax;
+ float fMin;
+ float fMax;
};
struct PWL_SCROLL_PRIVATEDATA {
@@ -97,11 +97,11 @@
}
void Default();
- void SetScrollRange(FX_FLOAT min, FX_FLOAT max);
- void SetClientWidth(FX_FLOAT width);
- void SetSmallStep(FX_FLOAT step);
- void SetBigStep(FX_FLOAT step);
- bool SetPos(FX_FLOAT pos);
+ void SetScrollRange(float min, float max);
+ void SetClientWidth(float width);
+ void SetSmallStep(float step);
+ void SetBigStep(float step);
+ bool SetPos(float pos);
void AddSmall();
void SubSmall();
@@ -109,10 +109,10 @@
void SubBig();
PWL_FLOATRANGE ScrollRange;
- FX_FLOAT fClientWidth;
- FX_FLOAT fScrollPos;
- FX_FLOAT fBigStep;
- FX_FLOAT fSmallStep;
+ float fClientWidth;
+ float fScrollPos;
+ float fBigStep;
+ float fSmallStep;
};
class CPWL_ScrollBar : public CPWL_Wnd {
@@ -120,37 +120,40 @@
explicit CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType = SBT_HSCROLL);
~CPWL_ScrollBar() override;
- // CPWL_Wnd
- CFX_ByteString GetClassName() const override;
- void OnCreate(PWL_CREATEPARAM& cp) override;
- void RePosChildWnd() override;
- void GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) override;
+ // CPWL_Wnd:
+ ByteString GetClassName() const override;
+ void OnCreate(CreateParams* pParamsToAdjust) override;
+ void OnDestroy() override;
+ bool RePosChildWnd() override;
void DrawThisAppearance(CFX_RenderDevice* pDevice,
- CFX_Matrix* pUser2Device) override;
+ const CFX_Matrix& mtUser2Device) override;
bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override;
bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
- void OnNotify(CPWL_Wnd* pWnd,
- uint32_t msg,
- intptr_t wParam = 0,
- intptr_t lParam = 0) override;
- void CreateChildWnd(const PWL_CREATEPARAM& cp) override;
+ void SetScrollInfo(const PWL_SCROLL_INFO& info) override;
+ void SetScrollPosition(float pos) override;
+ void NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) override;
+ void NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) override;
+ void NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) override;
+ void CreateChildWnd(const CreateParams& cp) override;
void TimerProc() override;
- FX_FLOAT GetScrollBarWidth() const;
+ float GetScrollBarWidth() const;
PWL_SCROLLBAR_TYPE GetScrollBarType() const { return m_sbType; }
void SetNotifyForever(bool bForever) { m_bNotifyForever = bForever; }
protected:
- void SetScrollRange(FX_FLOAT fMin, FX_FLOAT fMax, FX_FLOAT fClientWidth);
- void SetScrollPos(FX_FLOAT fPos);
- void MovePosButton(bool bRefresh);
- void SetScrollStep(FX_FLOAT fBigStep, FX_FLOAT fSmallStep);
+ void SetScrollRange(float fMin, float fMax, float fClientWidth);
+ void SetScrollPos(float fPos);
+
+ // Returns |true| iff this instance is still allocated.
+ bool MovePosButton(bool bRefresh);
+ void SetScrollStep(float fBigStep, float fSmallStep);
void NotifyScrollWindow();
CFX_FloatRect GetScrollArea() const;
private:
- void CreateButtons(const PWL_CREATEPARAM& cp);
+ void CreateButtons(const CreateParams& cp);
void OnMinButtonLBDown(const CFX_PointF& point);
void OnMinButtonLBUp(const CFX_PointF& point);
@@ -164,20 +167,20 @@
void OnPosButtonLBUp(const CFX_PointF& point);
void OnPosButtonMouseMove(const CFX_PointF& point);
- FX_FLOAT TrueToFace(FX_FLOAT);
- FX_FLOAT FaceToTrue(FX_FLOAT);
+ float TrueToFace(float);
+ float FaceToTrue(float);
PWL_SCROLLBAR_TYPE m_sbType;
PWL_SCROLL_INFO m_OriginInfo;
- CPWL_SBButton* m_pMinButton;
- CPWL_SBButton* m_pMaxButton;
- CPWL_SBButton* m_pPosButton;
+ UnownedPtr<CPWL_SBButton> m_pMinButton;
+ UnownedPtr<CPWL_SBButton> m_pMaxButton;
+ UnownedPtr<CPWL_SBButton> m_pPosButton;
PWL_SCROLL_PRIVATEDATA m_sData;
bool m_bMouseDown;
bool m_bMinOrMax;
bool m_bNotifyForever;
- FX_FLOAT m_nOldPos;
- FX_FLOAT m_fOldPosButton;
+ float m_nOldPos;
+ float m_fOldPosButton;
};
-#endif // FPDFSDK_PDFWINDOW_PWL_SCROLLBAR_H_
+#endif // FPDFSDK_PWL_CPWL_SCROLL_BAR_H_
diff --git a/fpdfsdk/pdfwindow/PWL_SpecialButton.cpp b/fpdfsdk/pwl/cpwl_special_button.cpp
similarity index 77%
rename from fpdfsdk/pdfwindow/PWL_SpecialButton.cpp
rename to fpdfsdk/pwl/cpwl_special_button.cpp
index 1c46c37..ddca67e 100644
--- a/fpdfsdk/pdfwindow/PWL_SpecialButton.cpp
+++ b/fpdfsdk/pwl/cpwl_special_button.cpp
@@ -4,28 +4,28 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#include "fpdfsdk/pdfwindow/PWL_Button.h"
-#include "fpdfsdk/pdfwindow/PWL_SpecialButton.h"
-#include "fpdfsdk/pdfwindow/PWL_Utils.h"
-#include "fpdfsdk/pdfwindow/PWL_Wnd.h"
+#include "fpdfsdk/pwl/cpwl_special_button.h"
+#include "fpdfsdk/pwl/cpwl_button.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
CPWL_PushButton::CPWL_PushButton() {}
CPWL_PushButton::~CPWL_PushButton() {}
-CFX_ByteString CPWL_PushButton::GetClassName() const {
+ByteString CPWL_PushButton::GetClassName() const {
return "CPWL_PushButton";
}
CFX_FloatRect CPWL_PushButton::GetFocusRect() const {
- return CPWL_Utils::DeflateRect(GetWindowRect(), (FX_FLOAT)GetBorderWidth());
+ return GetWindowRect().GetDeflated(static_cast<float>(GetBorderWidth()),
+ static_cast<float>(GetBorderWidth()));
}
CPWL_CheckBox::CPWL_CheckBox() : m_bChecked(false) {}
CPWL_CheckBox::~CPWL_CheckBox() {}
-CFX_ByteString CPWL_CheckBox::GetClassName() const {
+ByteString CPWL_CheckBox::GetClassName() const {
return "CPWL_CheckBox";
}
@@ -54,7 +54,7 @@
CPWL_RadioButton::~CPWL_RadioButton() {}
-CFX_ByteString CPWL_RadioButton::GetClassName() const {
+ByteString CPWL_RadioButton::GetClassName() const {
return "CPWL_RadioButton";
}
diff --git a/fpdfsdk/pdfwindow/PWL_SpecialButton.h b/fpdfsdk/pwl/cpwl_special_button.h
similarity index 76%
rename from fpdfsdk/pdfwindow/PWL_SpecialButton.h
rename to fpdfsdk/pwl/cpwl_special_button.h
index 93f611b..076b529 100644
--- a/fpdfsdk/pdfwindow/PWL_SpecialButton.h
+++ b/fpdfsdk/pwl/cpwl_special_button.h
@@ -4,10 +4,10 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#ifndef FPDFSDK_PDFWINDOW_PWL_SPECIALBUTTON_H_
-#define FPDFSDK_PDFWINDOW_PWL_SPECIALBUTTON_H_
+#ifndef FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_
+#define FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_
-#include "fpdfsdk/pdfwindow/PWL_Button.h"
+#include "fpdfsdk/pwl/cpwl_button.h"
class CPWL_PushButton : public CPWL_Button {
public:
@@ -15,7 +15,7 @@
~CPWL_PushButton() override;
// CPWL_Button
- CFX_ByteString GetClassName() const override;
+ ByteString GetClassName() const override;
CFX_FloatRect GetFocusRect() const override;
};
@@ -25,7 +25,7 @@
~CPWL_CheckBox() override;
// CPWL_Button
- CFX_ByteString GetClassName() const override;
+ ByteString GetClassName() const override;
bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
bool OnChar(uint16_t nChar, uint32_t nFlag) override;
@@ -42,7 +42,7 @@
~CPWL_RadioButton() override;
// CPWL_Button
- CFX_ByteString GetClassName() const override;
+ ByteString GetClassName() const override;
bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
bool OnChar(uint16_t nChar, uint32_t nFlag) override;
@@ -53,4 +53,4 @@
bool m_bChecked;
};
-#endif // FPDFSDK_PDFWINDOW_PWL_SPECIALBUTTON_H_
+#endif // FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_
diff --git a/fpdfsdk/pwl/cpwl_timer.cpp b/fpdfsdk/pwl/cpwl_timer.cpp
new file mode 100644
index 0000000..34f81fc
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_timer.cpp
@@ -0,0 +1,62 @@
+// 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/pwl/cpwl_timer.h"
+
+#include <map>
+
+#include "fpdfsdk/cfx_systemhandler.h"
+#include "fpdfsdk/pwl/cpwl_timer_handler.h"
+
+namespace {
+
+std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
+ // Leak the object at shutdown.
+ static auto* timeMap = new std::map<int32_t, CPWL_Timer*>;
+ return *timeMap;
+}
+
+} // namespace
+
+CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached,
+ CFX_SystemHandler* pSystemHandler)
+ : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) {
+ ASSERT(m_pAttached);
+ ASSERT(m_pSystemHandler);
+}
+
+CPWL_Timer::~CPWL_Timer() {
+ KillPWLTimer();
+}
+
+int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) {
+ if (m_nTimerID != 0)
+ KillPWLTimer();
+ m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);
+
+ GetPWLTimeMap()[m_nTimerID] = this;
+ return m_nTimerID;
+}
+
+void CPWL_Timer::KillPWLTimer() {
+ if (m_nTimerID == 0)
+ return;
+
+ m_pSystemHandler->KillTimer(m_nTimerID);
+ GetPWLTimeMap().erase(m_nTimerID);
+ m_nTimerID = 0;
+}
+
+// static
+void CPWL_Timer::TimerProc(int32_t idEvent) {
+ auto it = GetPWLTimeMap().find(idEvent);
+ if (it == GetPWLTimeMap().end())
+ return;
+
+ CPWL_Timer* pTimer = it->second;
+ if (pTimer->m_pAttached)
+ pTimer->m_pAttached->TimerProc();
+}
diff --git a/fpdfsdk/pwl/cpwl_timer.h b/fpdfsdk/pwl/cpwl_timer.h
new file mode 100644
index 0000000..6e082ab
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_timer.h
@@ -0,0 +1,31 @@
+// 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_PWL_CPWL_TIMER_H_
+#define FPDFSDK_PWL_CPWL_TIMER_H_
+
+#include "core/fxcrt/unowned_ptr.h"
+
+class CFX_SystemHandler;
+class CPWL_TimerHandler;
+
+class CPWL_Timer {
+ public:
+ CPWL_Timer(CPWL_TimerHandler* pAttached, CFX_SystemHandler* pSystemHandler);
+ virtual ~CPWL_Timer();
+
+ static void TimerProc(int32_t idEvent);
+
+ int32_t SetPWLTimer(int32_t nElapse);
+ void KillPWLTimer();
+
+ private:
+ int32_t m_nTimerID;
+ UnownedPtr<CPWL_TimerHandler> m_pAttached;
+ UnownedPtr<CFX_SystemHandler> m_pSystemHandler;
+};
+
+#endif // FPDFSDK_PWL_CPWL_TIMER_H_
diff --git a/fpdfsdk/pwl/cpwl_timer_handler.cpp b/fpdfsdk/pwl/cpwl_timer_handler.cpp
new file mode 100644
index 0000000..33af306
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_timer_handler.cpp
@@ -0,0 +1,27 @@
+// 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/pwl/cpwl_timer_handler.h"
+
+#include "fpdfsdk/pwl/cpwl_timer.h"
+#include "third_party/base/ptr_util.h"
+
+CPWL_TimerHandler::CPWL_TimerHandler() {}
+
+CPWL_TimerHandler::~CPWL_TimerHandler() {}
+
+void CPWL_TimerHandler::BeginTimer(int32_t nElapse) {
+ if (!m_pTimer)
+ m_pTimer = pdfium::MakeUnique<CPWL_Timer>(this, GetSystemHandler());
+ m_pTimer->SetPWLTimer(nElapse);
+}
+
+void CPWL_TimerHandler::EndTimer() {
+ if (m_pTimer)
+ m_pTimer->KillPWLTimer();
+}
+
+void CPWL_TimerHandler::TimerProc() {}
diff --git a/fpdfsdk/pwl/cpwl_timer_handler.h b/fpdfsdk/pwl/cpwl_timer_handler.h
new file mode 100644
index 0000000..f208e1c
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_timer_handler.h
@@ -0,0 +1,30 @@
+// 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_PWL_CPWL_TIMER_HANDLER_H_
+#define FPDFSDK_PWL_CPWL_TIMER_HANDLER_H_
+
+#include <memory>
+
+class CFX_SystemHandler;
+class CPWL_Timer;
+
+class CPWL_TimerHandler {
+ public:
+ CPWL_TimerHandler();
+ virtual ~CPWL_TimerHandler();
+
+ virtual void TimerProc();
+ virtual CFX_SystemHandler* GetSystemHandler() const = 0;
+
+ void BeginTimer(int32_t nElapse);
+ void EndTimer();
+
+ private:
+ std::unique_ptr<CPWL_Timer> m_pTimer;
+};
+
+#endif // FPDFSDK_PWL_CPWL_TIMER_HANDLER_H_
diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp
new file mode 100644
index 0000000..368db74
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_wnd.cpp
@@ -0,0 +1,801 @@
+// Copyright 2014 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/pwl/cpwl_wnd.h"
+
+#include <map>
+#include <sstream>
+#include <vector>
+
+#include "core/fxge/cfx_renderdevice.h"
+#include "fpdfsdk/pwl/cpwl_scroll_bar.h"
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+
+namespace {
+
+constexpr float kDefaultFontSize = 9.0f;
+
+} // namespace
+
+CPWL_Wnd::CreateParams::CreateParams()
+ : rcRectWnd(0, 0, 0, 0),
+ pSystemHandler(nullptr),
+ pFontMap(nullptr),
+ pProvider(nullptr),
+ pFocusHandler(nullptr),
+ dwFlags(0),
+ sBackgroundColor(),
+ pAttachedWidget(nullptr),
+ nBorderStyle(BorderStyle::SOLID),
+ dwBorderWidth(1),
+ sBorderColor(),
+ sTextColor(),
+ nTransparency(255),
+ fFontSize(kDefaultFontSize),
+ sDash(3, 0, 0),
+ pAttachedData(nullptr),
+ pParentWnd(nullptr),
+ pMsgControl(nullptr),
+ eCursorType(FXCT_ARROW) {}
+
+CPWL_Wnd::CreateParams::CreateParams(const CreateParams& other) = default;
+
+CPWL_Wnd::CreateParams::~CreateParams() = default;
+
+class CPWL_MsgControl : public Observable<CPWL_MsgControl> {
+ public:
+ explicit CPWL_MsgControl(CPWL_Wnd* pWnd) : m_pCreatedWnd(pWnd) {}
+ ~CPWL_MsgControl() {}
+
+ bool IsWndCreated(const CPWL_Wnd* pWnd) const {
+ return m_pCreatedWnd == pWnd;
+ }
+
+ bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
+ return pWnd && pdfium::ContainsValue(m_aMousePath, pWnd);
+ }
+
+ bool IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
+ return pWnd == m_pMainKeyboardWnd;
+ }
+
+ bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
+ return pWnd && pdfium::ContainsValue(m_aKeyboardPath, pWnd);
+ }
+
+ void SetFocus(CPWL_Wnd* pWnd) {
+ m_aKeyboardPath.clear();
+ if (!pWnd)
+ return;
+
+ m_pMainKeyboardWnd = pWnd;
+ CPWL_Wnd* pParent = pWnd;
+ while (pParent) {
+ m_aKeyboardPath.push_back(pParent);
+ pParent = pParent->GetParentWindow();
+ }
+ // Note, pWnd may get destroyed in the OnSetFocus call.
+ pWnd->OnSetFocus();
+ }
+
+ void KillFocus() {
+ ObservedPtr observed_ptr(this);
+ if (!m_aKeyboardPath.empty())
+ if (CPWL_Wnd* pWnd = m_aKeyboardPath[0])
+ pWnd->OnKillFocus();
+ if (!observed_ptr)
+ return;
+
+ m_pMainKeyboardWnd = nullptr;
+ m_aKeyboardPath.clear();
+ }
+
+ void SetCapture(CPWL_Wnd* pWnd) {
+ m_aMousePath.clear();
+ if (pWnd) {
+ CPWL_Wnd* pParent = pWnd;
+ while (pParent) {
+ m_aMousePath.push_back(pParent);
+ pParent = pParent->GetParentWindow();
+ }
+ }
+ }
+
+ void ReleaseCapture() {
+ m_aMousePath.clear();
+ }
+
+ CPWL_Wnd* GetFocusedWindow() const { return m_pMainKeyboardWnd.Get(); }
+
+ private:
+ std::vector<CPWL_Wnd*> m_aMousePath;
+ std::vector<CPWL_Wnd*> m_aKeyboardPath;
+ UnownedPtr<CPWL_Wnd> m_pCreatedWnd;
+ UnownedPtr<CPWL_Wnd> m_pMainKeyboardWnd;
+};
+
+CPWL_Wnd::CPWL_Wnd()
+ : m_rcWindow(),
+ m_rcClip(),
+ m_bCreated(false),
+ m_bVisible(false),
+ m_bNotifying(false),
+ m_bEnabled(true) {}
+
+CPWL_Wnd::~CPWL_Wnd() {
+ ASSERT(!m_bCreated);
+}
+
+ByteString CPWL_Wnd::GetClassName() const {
+ return "CPWL_Wnd";
+}
+
+void CPWL_Wnd::Create(const CreateParams& cp) {
+ if (IsValid())
+ return;
+
+ m_CreationParams = cp;
+ OnCreate(&m_CreationParams);
+ m_CreationParams.rcRectWnd.Normalize();
+ m_rcWindow = m_CreationParams.rcRectWnd;
+ m_rcClip = m_rcWindow;
+ if (!m_rcClip.IsEmpty()) {
+ m_rcClip.Inflate(1.0f, 1.0f);
+ m_rcClip.Normalize();
+ }
+ CreateMsgControl();
+ if (m_CreationParams.pParentWnd)
+ m_CreationParams.pParentWnd->AddChild(this);
+
+ CreateParams ccp = m_CreationParams;
+ ccp.dwFlags &= 0xFFFF0000L; // remove sub styles
+ CreateScrollBar(ccp);
+ CreateChildWnd(ccp);
+ m_bVisible = HasFlag(PWS_VISIBLE);
+ OnCreated();
+ if (!RePosChildWnd())
+ return;
+
+ m_bCreated = true;
+}
+
+void CPWL_Wnd::OnCreate(CreateParams* pParamsToAdjust) {}
+
+void CPWL_Wnd::OnCreated() {}
+
+void CPWL_Wnd::OnDestroy() {}
+
+void CPWL_Wnd::InvalidateFocusHandler(FocusHandlerIface* handler) {
+ if (m_CreationParams.pFocusHandler == handler)
+ m_CreationParams.pFocusHandler = nullptr;
+}
+
+void CPWL_Wnd::InvalidateProvider(ProviderIface* provider) {
+ if (m_CreationParams.pProvider.Get() == provider)
+ m_CreationParams.pProvider.Reset();
+}
+
+void CPWL_Wnd::Destroy() {
+ KillFocus();
+ OnDestroy();
+ if (m_bCreated) {
+ m_pVScrollBar = nullptr;
+ for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) {
+ CPWL_Wnd* pChild = *it;
+ if (pChild) {
+ *it = nullptr;
+ pChild->Destroy();
+ delete pChild;
+ }
+ }
+ if (m_CreationParams.pParentWnd)
+ m_CreationParams.pParentWnd->RemoveChild(this);
+
+ m_bCreated = false;
+ }
+ DestroyMsgControl();
+ m_Children.clear();
+}
+
+bool CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) {
+ if (!IsValid())
+ return true;
+
+ CFX_FloatRect rcOld = GetWindowRect();
+ m_rcWindow = rcNew;
+ m_rcWindow.Normalize();
+
+ if (bReset) {
+ if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
+ rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
+ if (!RePosChildWnd())
+ return false;
+ }
+ }
+ if (bRefresh && !InvalidateRectMove(rcOld, rcNew))
+ return false;
+
+ m_CreationParams.rcRectWnd = m_rcWindow;
+ return true;
+}
+
+bool CPWL_Wnd::InvalidateRectMove(const CFX_FloatRect& rcOld,
+ const CFX_FloatRect& rcNew) {
+ CFX_FloatRect rcUnion = rcOld;
+ rcUnion.Union(rcNew);
+
+ return InvalidateRect(&rcUnion);
+}
+
+void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ if (IsValid() && IsVisible()) {
+ DrawThisAppearance(pDevice, mtUser2Device);
+ DrawChildAppearance(pDevice, mtUser2Device);
+ }
+}
+
+void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ CFX_FloatRect rectWnd = GetWindowRect();
+ if (rectWnd.IsEmpty())
+ return;
+
+ if (HasFlag(PWS_BACKGROUND)) {
+ float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth());
+ pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(width, width),
+ GetBackgroundColor(), GetTransparency());
+ }
+
+ if (HasFlag(PWS_BORDER)) {
+ pDevice->DrawBorder(&mtUser2Device, rectWnd,
+ static_cast<float>(GetBorderWidth()), GetBorderColor(),
+ GetBorderLeftTopColor(GetBorderStyle()),
+ GetBorderRightBottomColor(GetBorderStyle()),
+ GetBorderStyle(), GetTransparency());
+ }
+}
+
+void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device) {
+ for (CPWL_Wnd* pChild : m_Children) {
+ if (!pChild)
+ continue;
+
+ CFX_Matrix mt = pChild->GetChildMatrix();
+ if (mt.IsIdentity()) {
+ pChild->DrawAppearance(pDevice, mtUser2Device);
+ } else {
+ mt.Concat(mtUser2Device);
+ pChild->DrawAppearance(pDevice, mt);
+ }
+ }
+}
+
+bool CPWL_Wnd::InvalidateRect(CFX_FloatRect* pRect) {
+ ObservedPtr thisObserved(this);
+ if (!IsValid())
+ return true;
+
+ CFX_FloatRect rcRefresh = pRect ? *pRect : GetWindowRect();
+
+ if (!HasFlag(PWS_NOREFRESHCLIP)) {
+ CFX_FloatRect rcClip = GetClipRect();
+ if (!rcClip.IsEmpty()) {
+ rcRefresh.Intersect(rcClip);
+ }
+ }
+
+ CFX_FloatRect rcWin = PWLtoWnd(rcRefresh);
+ rcWin.Inflate(1, 1);
+ rcWin.Normalize();
+
+ if (CFX_SystemHandler* pSH = GetSystemHandler()) {
+ if (CPDFSDK_Widget* widget = static_cast<CPDFSDK_Widget*>(
+ m_CreationParams.pAttachedWidget.Get())) {
+ pSH->InvalidateRect(widget, rcWin);
+ if (!thisObserved)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#define PWL_IMPLEMENT_KEY_METHOD(key_method_name) \
+ bool CPWL_Wnd::key_method_name(uint16_t nChar, uint32_t nFlag) { \
+ if (!IsValid() || !IsVisible() || !IsEnabled()) \
+ return false; \
+ if (!IsWndCaptureKeyboard(this)) \
+ return false; \
+ for (auto* pChild : m_Children) { \
+ if (pChild && IsWndCaptureKeyboard(pChild)) \
+ return pChild->key_method_name(nChar, nFlag); \
+ } \
+ return false; \
+ }
+
+PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
+PWL_IMPLEMENT_KEY_METHOD(OnChar)
+#undef PWL_IMPLEMENT_KEY_METHOD
+
+#define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name) \
+ bool CPWL_Wnd::mouse_method_name(const CFX_PointF& point, uint32_t nFlag) { \
+ if (!IsValid() || !IsVisible() || !IsEnabled()) \
+ return false; \
+ if (IsWndCaptureMouse(this)) { \
+ for (auto* pChild : m_Children) { \
+ if (pChild && IsWndCaptureMouse(pChild)) { \
+ return pChild->mouse_method_name(pChild->ParentToChild(point), \
+ nFlag); \
+ } \
+ } \
+ SetCursor(); \
+ return false; \
+ } \
+ for (auto* pChild : m_Children) { \
+ if (pChild && pChild->WndHitTest(pChild->ParentToChild(point))) { \
+ return pChild->mouse_method_name(pChild->ParentToChild(point), nFlag); \
+ } \
+ } \
+ if (WndHitTest(point)) \
+ SetCursor(); \
+ return false; \
+ }
+
+PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
+PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
+PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
+PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
+PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
+PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)
+#undef PWL_IMPLEMENT_MOUSE_METHOD
+
+WideString CPWL_Wnd::GetSelectedText() {
+ return WideString();
+}
+
+void CPWL_Wnd::ReplaceSelection(const WideString& text) {}
+
+bool CPWL_Wnd::OnMouseWheel(short zDelta,
+ const CFX_PointF& point,
+ uint32_t nFlag) {
+ if (!IsValid() || !IsVisible() || !IsEnabled())
+ return false;
+
+ SetCursor();
+ if (!IsWndCaptureKeyboard(this))
+ return false;
+
+ for (auto* pChild : m_Children) {
+ if (pChild && IsWndCaptureKeyboard(pChild))
+ return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point), nFlag);
+ }
+ return false;
+}
+
+void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) {
+ m_Children.push_back(pWnd);
+}
+
+void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
+ for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) {
+ if (*it && *it == pWnd) {
+ m_Children.erase(std::next(it).base());
+ break;
+ }
+ }
+}
+
+void CPWL_Wnd::SetScrollInfo(const PWL_SCROLL_INFO& info) {}
+
+void CPWL_Wnd::SetScrollPosition(float pos) {}
+
+void CPWL_Wnd::ScrollWindowVertically(float pos) {}
+
+void CPWL_Wnd::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {}
+
+void CPWL_Wnd::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {}
+
+void CPWL_Wnd::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) {}
+
+CPWL_Wnd* CPWL_Wnd::GetParentWindow() const {
+ return m_CreationParams.pParentWnd;
+}
+
+CFX_FloatRect CPWL_Wnd::GetWindowRect() const {
+ return m_rcWindow;
+}
+
+CFX_FloatRect CPWL_Wnd::GetClientRect() const {
+ CFX_FloatRect rcWindow = GetWindowRect();
+
+ float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth());
+ CFX_FloatRect rcClient = rcWindow.GetDeflated(width, width);
+ if (CPWL_ScrollBar* pVSB = GetVScrollBar())
+ rcClient.right -= pVSB->GetScrollBarWidth();
+
+ rcClient.Normalize();
+ return rcWindow.Contains(rcClient) ? rcClient : CFX_FloatRect();
+}
+
+CFX_PointF CPWL_Wnd::GetCenterPoint() const {
+ CFX_FloatRect rcClient = GetClientRect();
+ return CFX_PointF((rcClient.left + rcClient.right) * 0.5f,
+ (rcClient.top + rcClient.bottom) * 0.5f);
+}
+
+bool CPWL_Wnd::HasFlag(uint32_t dwFlags) const {
+ return (m_CreationParams.dwFlags & dwFlags) != 0;
+}
+
+void CPWL_Wnd::RemoveFlag(uint32_t dwFlags) {
+ m_CreationParams.dwFlags &= ~dwFlags;
+}
+
+void CPWL_Wnd::AddFlag(uint32_t dwFlags) {
+ m_CreationParams.dwFlags |= dwFlags;
+}
+
+CFX_Color CPWL_Wnd::GetBackgroundColor() const {
+ return m_CreationParams.sBackgroundColor;
+}
+
+void CPWL_Wnd::SetBackgroundColor(const CFX_Color& color) {
+ m_CreationParams.sBackgroundColor = color;
+}
+
+CFX_Color CPWL_Wnd::GetTextColor() const {
+ return m_CreationParams.sTextColor;
+}
+
+BorderStyle CPWL_Wnd::GetBorderStyle() const {
+ return m_CreationParams.nBorderStyle;
+}
+
+void CPWL_Wnd::SetBorderStyle(BorderStyle nBorderStyle) {
+ if (HasFlag(PWS_BORDER))
+ m_CreationParams.nBorderStyle = nBorderStyle;
+}
+
+int32_t CPWL_Wnd::GetBorderWidth() const {
+ return HasFlag(PWS_BORDER) ? m_CreationParams.dwBorderWidth : 0;
+}
+
+int32_t CPWL_Wnd::GetInnerBorderWidth() const {
+ return 0;
+}
+
+CFX_Color CPWL_Wnd::GetBorderColor() const {
+ return HasFlag(PWS_BORDER) ? m_CreationParams.sBorderColor : CFX_Color();
+}
+
+const CPWL_Dash& CPWL_Wnd::GetBorderDash() const {
+ return m_CreationParams.sDash;
+}
+
+CPWL_Wnd::PrivateData* CPWL_Wnd::GetAttachedData() const {
+ return m_CreationParams.pAttachedData.Get();
+}
+
+CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
+ return HasFlag(PWS_VSCROLL) ? m_pVScrollBar.Get() : nullptr;
+}
+
+void CPWL_Wnd::CreateScrollBar(const CreateParams& cp) {
+ CreateVScrollBar(cp);
+}
+
+void CPWL_Wnd::CreateVScrollBar(const CreateParams& cp) {
+ if (m_pVScrollBar || !HasFlag(PWS_VSCROLL))
+ return;
+
+ CreateParams scp = cp;
+
+ // flags
+ scp.dwFlags =
+ PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;
+
+ scp.pParentWnd = this;
+ scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
+ scp.eCursorType = FXCT_ARROW;
+ scp.nTransparency = PWL_SCROLLBAR_TRANSPARENCY;
+
+ m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL);
+ m_pVScrollBar->Create(scp);
+}
+
+void CPWL_Wnd::SetCapture() {
+ if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
+ pMsgCtrl->SetCapture(this);
+}
+
+void CPWL_Wnd::ReleaseCapture() {
+ for (auto* pChild : m_Children) {
+ if (pChild)
+ pChild->ReleaseCapture();
+ }
+ if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
+ pMsgCtrl->ReleaseCapture();
+}
+
+void CPWL_Wnd::SetFocus() {
+ if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
+ if (!pMsgCtrl->IsMainCaptureKeyboard(this))
+ pMsgCtrl->KillFocus();
+ pMsgCtrl->SetFocus(this);
+ }
+}
+
+void CPWL_Wnd::KillFocus() {
+ if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
+ if (pMsgCtrl->IsWndCaptureKeyboard(this))
+ pMsgCtrl->KillFocus();
+ }
+}
+
+void CPWL_Wnd::OnSetFocus() {}
+
+void CPWL_Wnd::OnKillFocus() {}
+
+bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const {
+ return IsValid() && IsVisible() && GetWindowRect().Contains(point);
+}
+
+bool CPWL_Wnd::ClientHitTest(const CFX_PointF& point) const {
+ return IsValid() && IsVisible() && GetClientRect().Contains(point);
+}
+
+const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const {
+ auto* pParent = m_CreationParams.pParentWnd;
+ return pParent ? pParent->GetRootWnd() : this;
+}
+
+bool CPWL_Wnd::SetVisible(bool bVisible) {
+ if (!IsValid())
+ return true;
+
+ ObservedPtr thisObserved(this);
+
+ for (auto* pChild : m_Children) {
+ if (pChild) {
+ pChild->SetVisible(bVisible);
+ if (!thisObserved)
+ return false;
+ }
+ }
+
+ if (bVisible != m_bVisible) {
+ m_bVisible = bVisible;
+ if (!RePosChildWnd())
+ return false;
+
+ if (!InvalidateRect(nullptr))
+ return false;
+ }
+ return true;
+}
+
+void CPWL_Wnd::SetClipRect(const CFX_FloatRect& rect) {
+ m_rcClip = rect;
+ m_rcClip.Normalize();
+}
+
+const CFX_FloatRect& CPWL_Wnd::GetClipRect() const {
+ return m_rcClip;
+}
+
+bool CPWL_Wnd::IsReadOnly() const {
+ return HasFlag(PWS_READONLY);
+}
+
+bool CPWL_Wnd::RePosChildWnd() {
+ CPWL_ScrollBar* pVSB = GetVScrollBar();
+ if (!pVSB)
+ return true;
+
+ CFX_FloatRect rcContent = GetWindowRect();
+ if (!rcContent.IsEmpty()) {
+ float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth());
+ rcContent.Deflate(width, width);
+ rcContent.Normalize();
+ }
+ CFX_FloatRect rcVScroll =
+ CFX_FloatRect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom,
+ rcContent.right - 1.0f, rcContent.top);
+
+ ObservedPtr thisObserved(this);
+
+ pVSB->Move(rcVScroll, true, false);
+ if (!thisObserved)
+ return false;
+
+ return true;
+}
+
+void CPWL_Wnd::CreateChildWnd(const CreateParams& cp) {}
+
+void CPWL_Wnd::SetCursor() {
+ if (IsValid()) {
+ if (CFX_SystemHandler* pSH = GetSystemHandler()) {
+ int32_t nCursorType = GetCreationParams().eCursorType;
+ pSH->SetCursor(nCursorType);
+ }
+ }
+}
+
+void CPWL_Wnd::CreateMsgControl() {
+ if (!m_CreationParams.pMsgControl)
+ m_CreationParams.pMsgControl = new CPWL_MsgControl(this);
+}
+
+void CPWL_Wnd::DestroyMsgControl() {
+ CPWL_MsgControl* pMsgControl = GetMsgControl();
+ if (pMsgControl && pMsgControl->IsWndCreated(this))
+ delete pMsgControl;
+}
+
+CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
+ return m_CreationParams.pMsgControl;
+}
+
+bool CPWL_Wnd::IsCaptureMouse() const {
+ return IsWndCaptureMouse(this);
+}
+
+bool CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
+ CPWL_MsgControl* pCtrl = GetMsgControl();
+ return pCtrl ? pCtrl->IsWndCaptureMouse(pWnd) : false;
+}
+
+bool CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
+ CPWL_MsgControl* pCtrl = GetMsgControl();
+ return pCtrl ? pCtrl->IsWndCaptureKeyboard(pWnd) : false;
+}
+
+bool CPWL_Wnd::IsFocused() const {
+ CPWL_MsgControl* pCtrl = GetMsgControl();
+ return pCtrl ? pCtrl->IsMainCaptureKeyboard(this) : false;
+}
+
+CFX_FloatRect CPWL_Wnd::GetFocusRect() const {
+ CFX_FloatRect rect = GetWindowRect();
+ if (!rect.IsEmpty()) {
+ rect.Inflate(1.0f, 1.0f);
+ rect.Normalize();
+ }
+ return rect;
+}
+
+float CPWL_Wnd::GetFontSize() const {
+ return m_CreationParams.fFontSize;
+}
+
+void CPWL_Wnd::SetFontSize(float fFontSize) {
+ m_CreationParams.fFontSize = fFontSize;
+}
+
+CFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
+ return m_CreationParams.pSystemHandler;
+}
+
+CPWL_Wnd::FocusHandlerIface* CPWL_Wnd::GetFocusHandler() const {
+ return m_CreationParams.pFocusHandler.Get();
+}
+
+CPWL_Wnd::ProviderIface* CPWL_Wnd::GetProvider() const {
+ return m_CreationParams.pProvider.Get();
+}
+
+IPVT_FontMap* CPWL_Wnd::GetFontMap() const {
+ return m_CreationParams.pFontMap;
+}
+
+CFX_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const {
+ switch (nBorderStyle) {
+ case BorderStyle::BEVELED:
+ return CFX_Color(CFX_Color::kGray, 1);
+ case BorderStyle::INSET:
+ return CFX_Color(CFX_Color::kGray, 0.5f);
+ default:
+ return CFX_Color();
+ }
+}
+
+CFX_Color CPWL_Wnd::GetBorderRightBottomColor(BorderStyle nBorderStyle) const {
+ switch (nBorderStyle) {
+ case BorderStyle::BEVELED:
+ return GetBackgroundColor() / 2.0f;
+ case BorderStyle::INSET:
+ return CFX_Color(CFX_Color::kGray, 0.75f);
+ default:
+ return CFX_Color();
+ }
+}
+
+int32_t CPWL_Wnd::GetTransparency() {
+ return m_CreationParams.nTransparency;
+}
+
+void CPWL_Wnd::SetTransparency(int32_t nTransparency) {
+ for (auto* pChild : m_Children) {
+ if (pChild)
+ pChild->SetTransparency(nTransparency);
+ }
+ m_CreationParams.nTransparency = nTransparency;
+}
+
+CFX_Matrix CPWL_Wnd::GetWindowMatrix() const {
+ CFX_Matrix mt = GetChildToRoot();
+ if (ProviderIface* pProvider = GetProvider())
+ mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
+ return mt;
+}
+
+CFX_FloatRect CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const {
+ CFX_Matrix mt = GetWindowMatrix();
+ return mt.TransformRect(rect);
+}
+
+CFX_PointF CPWL_Wnd::ParentToChild(const CFX_PointF& point) const {
+ CFX_Matrix mt = GetChildMatrix();
+ if (mt.IsIdentity())
+ return point;
+
+ CFX_Matrix inverse = mt.GetInverse();
+ if (!inverse.IsIdentity())
+ mt = inverse;
+ return mt.Transform(point);
+}
+
+CFX_FloatRect CPWL_Wnd::ParentToChild(const CFX_FloatRect& rect) const {
+ CFX_Matrix mt = GetChildMatrix();
+ if (mt.IsIdentity())
+ return rect;
+
+ CFX_Matrix inverse = mt.GetInverse();
+ if (!inverse.IsIdentity())
+ mt = inverse;
+
+ return mt.TransformRect(rect);
+}
+
+CFX_Matrix CPWL_Wnd::GetChildToRoot() const {
+ CFX_Matrix mt;
+ if (HasFlag(PWS_CHILD)) {
+ const CPWL_Wnd* pParent = this;
+ while (pParent) {
+ mt.Concat(pParent->GetChildMatrix());
+ pParent = pParent->GetParentWindow();
+ }
+ }
+ return mt;
+}
+
+CFX_Matrix CPWL_Wnd::GetChildMatrix() const {
+ return HasFlag(PWS_CHILD) ? m_CreationParams.mtChild : CFX_Matrix();
+}
+
+void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) {
+ m_CreationParams.mtChild = mt;
+}
+
+const CPWL_Wnd* CPWL_Wnd::GetFocused() const {
+ CPWL_MsgControl* pMsgCtrl = GetMsgControl();
+ return pMsgCtrl ? pMsgCtrl->GetFocusedWindow() : nullptr;
+}
+
+void CPWL_Wnd::EnableWindow(bool bEnable) {
+ if (m_bEnabled == bEnable)
+ return;
+
+ for (auto* pChild : m_Children) {
+ if (pChild)
+ pChild->EnableWindow(bEnable);
+ }
+ m_bEnabled = bEnable;
+}
diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h
new file mode 100644
index 0000000..ba52420
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_wnd.h
@@ -0,0 +1,326 @@
+// Copyright 2014 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_PWL_CPWL_WND_H_
+#define FPDFSDK_PWL_CPWL_WND_H_
+
+#include <memory>
+#include <vector>
+
+#include "core/fpdfdoc/cpdf_formcontrol.h"
+#include "core/fxcrt/observable.h"
+#include "core/fxcrt/unowned_ptr.h"
+#include "core/fxge/cfx_color.h"
+#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
+#include "fpdfsdk/cpdfsdk_widget.h"
+#include "fpdfsdk/pwl/cpwl_timer.h"
+#include "fpdfsdk/pwl/cpwl_timer_handler.h"
+
+class CPWL_Edit;
+class CPWL_MsgControl;
+class CPWL_ScrollBar;
+class CFX_SystemHandler;
+class IPVT_FontMap;
+struct PWL_SCROLL_INFO;
+
+// window styles
+#define PWS_CHILD 0x80000000L
+#define PWS_BORDER 0x40000000L
+#define PWS_BACKGROUND 0x20000000L
+#define PWS_HSCROLL 0x10000000L
+#define PWS_VSCROLL 0x08000000L
+#define PWS_VISIBLE 0x04000000L
+#define PWS_READONLY 0x01000000L
+#define PWS_AUTOFONTSIZE 0x00800000L
+#define PWS_AUTOTRANSPARENT 0x00400000L
+#define PWS_NOREFRESHCLIP 0x00200000L
+
+// edit and label styles
+#define PES_MULTILINE 0x0001L
+#define PES_PASSWORD 0x0002L
+#define PES_LEFT 0x0004L
+#define PES_RIGHT 0x0008L
+#define PES_MIDDLE 0x0010L
+#define PES_TOP 0x0020L
+#define PES_BOTTOM 0x0040L
+#define PES_CENTER 0x0080L
+#define PES_CHARARRAY 0x0100L
+#define PES_AUTOSCROLL 0x0200L
+#define PES_AUTORETURN 0x0400L
+#define PES_UNDO 0x0800L
+#define PES_RICH 0x1000L
+#define PES_SPELLCHECK 0x2000L
+#define PES_TEXTOVERFLOW 0x4000L
+#define PES_NOREAD 0x8000L
+
+// listbox styles
+#define PLBS_MULTIPLESEL 0x0001L
+#define PLBS_HOVERSEL 0x0008L
+
+// combobox styles
+#define PCBS_ALLOWCUSTOMTEXT 0x0001L
+
+struct CPWL_Dash {
+ CPWL_Dash() : nDash(0), nGap(0), nPhase(0) {}
+ CPWL_Dash(int32_t dash, int32_t gap, int32_t phase)
+ : nDash(dash), nGap(gap), nPhase(phase) {}
+
+ void Reset() {
+ nDash = 0;
+ nGap = 0;
+ nPhase = 0;
+ }
+
+ int32_t nDash;
+ int32_t nGap;
+ int32_t nPhase;
+};
+
+inline bool operator==(const CFX_Color& c1, const CFX_Color& c2) {
+ return c1.nColorType == c2.nColorType && c1.fColor1 - c2.fColor1 < 0.0001 &&
+ c1.fColor1 - c2.fColor1 > -0.0001 &&
+ c1.fColor2 - c2.fColor2 < 0.0001 &&
+ c1.fColor2 - c2.fColor2 > -0.0001 &&
+ c1.fColor3 - c2.fColor3 < 0.0001 &&
+ c1.fColor3 - c2.fColor3 > -0.0001 &&
+ c1.fColor4 - c2.fColor4 < 0.0001 && c1.fColor4 - c2.fColor4 > -0.0001;
+}
+
+inline bool operator!=(const CFX_Color& c1, const CFX_Color& c2) {
+ return !(c1 == c2);
+}
+
+#define PWL_SCROLLBAR_WIDTH 12.0f
+#define PWL_SCROLLBAR_TRANSPARENCY 150
+#define PWL_DEFAULT_BLACKCOLOR CFX_Color(CFX_Color::kGray, 0)
+#define PWL_DEFAULT_WHITECOLOR CFX_Color(CFX_Color::kGray, 1)
+
+class CPWL_Wnd : public CPWL_TimerHandler, public Observable<CPWL_Wnd> {
+ public:
+ class PrivateData {
+ protected:
+ ~PrivateData() {}
+ };
+
+ class ProviderIface : public Observable<ProviderIface> {
+ public:
+ virtual ~ProviderIface() {}
+
+ // get a matrix which map user space to CWnd client space
+ virtual CFX_Matrix GetWindowMatrix(PrivateData* pAttached) = 0;
+ };
+
+ class FocusHandlerIface {
+ public:
+ virtual ~FocusHandlerIface() {}
+ virtual void OnSetFocus(CPWL_Edit* pEdit) = 0;
+ };
+
+ class CreateParams {
+ public:
+ CreateParams();
+ CreateParams(const CreateParams& other);
+ ~CreateParams();
+
+ CFX_FloatRect rcRectWnd; // required
+ CFX_SystemHandler* pSystemHandler; // required
+ IPVT_FontMap* pFontMap; // required
+ ProviderIface::ObservedPtr pProvider; // required
+ UnownedPtr<FocusHandlerIface> pFocusHandler; // optional
+ uint32_t dwFlags; // optional
+ CFX_Color sBackgroundColor; // optional
+ CPDFSDK_Widget::ObservedPtr pAttachedWidget; // required
+ BorderStyle nBorderStyle; // optional
+ int32_t dwBorderWidth; // optional
+ CFX_Color sBorderColor; // optional
+ CFX_Color sTextColor; // optional
+ int32_t nTransparency; // optional
+ float fFontSize; // optional
+ CPWL_Dash sDash; // optional
+ UnownedPtr<PrivateData> pAttachedData; // optional
+ CPWL_Wnd* pParentWnd; // ignore
+ CPWL_MsgControl* pMsgControl; // ignore
+ int32_t eCursorType; // ignore
+ CFX_Matrix mtChild; // ignore
+ };
+
+ CPWL_Wnd();
+ ~CPWL_Wnd() override;
+
+ virtual ByteString GetClassName() const;
+
+ // Returns |true| iff this instance is still allocated.
+ virtual bool InvalidateRect(CFX_FloatRect* pRect);
+
+ virtual bool OnKeyDown(uint16_t nChar, uint32_t nFlag);
+ virtual bool OnChar(uint16_t nChar, uint32_t nFlag);
+ virtual bool OnLButtonDblClk(const CFX_PointF& point, uint32_t nFlag);
+ virtual bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag);
+ virtual bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag);
+ virtual bool OnRButtonDown(const CFX_PointF& point, uint32_t nFlag);
+ virtual bool OnRButtonUp(const CFX_PointF& point, uint32_t nFlag);
+ virtual bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag);
+ virtual bool OnMouseWheel(short zDelta,
+ const CFX_PointF& point,
+ uint32_t nFlag);
+ virtual void SetScrollInfo(const PWL_SCROLL_INFO& info);
+ virtual void SetScrollPosition(float pos);
+ virtual void ScrollWindowVertically(float pos);
+ virtual void NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos);
+ virtual void NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos);
+ virtual void NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos);
+ virtual void SetFocus();
+ virtual void KillFocus();
+ virtual void SetCursor();
+
+ // Returns |true| iff this instance is still allocated.
+ virtual bool SetVisible(bool bVisible);
+ virtual void SetFontSize(float fFontSize);
+ virtual float GetFontSize() const;
+
+ virtual WideString GetSelectedText();
+ virtual void ReplaceSelection(const WideString& text);
+ virtual CFX_FloatRect GetFocusRect() const;
+ virtual CFX_FloatRect GetClientRect() const;
+
+ void InvalidateFocusHandler(FocusHandlerIface* handler);
+ void InvalidateProvider(ProviderIface* provider);
+ void Create(const CreateParams& cp);
+ void Destroy();
+ bool Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh);
+
+ void SetCapture();
+ void ReleaseCapture();
+
+ void DrawAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device);
+
+ CFX_Color GetBackgroundColor() const;
+ void SetBackgroundColor(const CFX_Color& color);
+ CFX_Color GetBorderColor() const;
+ CFX_Color GetTextColor() const;
+ void SetTextColor(const CFX_Color& color);
+ CFX_Color GetBorderLeftTopColor(BorderStyle nBorderStyle) const;
+ CFX_Color GetBorderRightBottomColor(BorderStyle nBorderStyle) const;
+
+ void SetBorderStyle(BorderStyle eBorderStyle);
+ BorderStyle GetBorderStyle() const;
+ const CPWL_Dash& GetBorderDash() const;
+
+ int32_t GetBorderWidth() const;
+ int32_t GetInnerBorderWidth() const;
+ CFX_FloatRect GetWindowRect() const;
+ CFX_PointF GetCenterPoint() const;
+
+ bool IsVisible() const { return m_bVisible; }
+ bool HasFlag(uint32_t dwFlags) const;
+ void AddFlag(uint32_t dwFlags);
+ void RemoveFlag(uint32_t dwFlags);
+
+ void SetClipRect(const CFX_FloatRect& rect);
+ const CFX_FloatRect& GetClipRect() const;
+
+ CPWL_Wnd* GetParentWindow() const;
+ PrivateData* GetAttachedData() const;
+
+ bool WndHitTest(const CFX_PointF& point) const;
+ bool ClientHitTest(const CFX_PointF& point) const;
+ bool IsCaptureMouse() const;
+
+ void EnableWindow(bool bEnable);
+ bool IsEnabled() const { return m_bEnabled; }
+ const CPWL_Wnd* GetFocused() const;
+ bool IsFocused() const;
+ bool IsReadOnly() const;
+ CPWL_ScrollBar* GetVScrollBar() const;
+
+ IPVT_FontMap* GetFontMap() const;
+ ProviderIface* GetProvider() const;
+ FocusHandlerIface* GetFocusHandler() const;
+
+ int32_t GetTransparency();
+ void SetTransparency(int32_t nTransparency);
+
+ CFX_Matrix GetChildToRoot() const;
+ CFX_Matrix GetChildMatrix() const;
+ void SetChildMatrix(const CFX_Matrix& mt);
+ CFX_Matrix GetWindowMatrix() const;
+
+ virtual void OnSetFocus();
+ virtual void OnKillFocus();
+
+ protected:
+ // CPWL_TimerHandler
+ CFX_SystemHandler* GetSystemHandler() const override;
+
+ virtual void CreateChildWnd(const CreateParams& cp);
+
+ // Returns |true| iff this instance is still allocated.
+ virtual bool RePosChildWnd();
+
+ virtual void DrawThisAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device);
+
+ virtual void OnCreate(CreateParams* pParamsToAdjust);
+ virtual void OnCreated();
+ virtual void OnDestroy();
+
+ void SetNotifyFlag(bool bNotifying = true) { m_bNotifying = bNotifying; }
+ bool IsNotifying() const { return m_bNotifying; }
+ bool IsValid() const { return m_bCreated; }
+ const CreateParams& GetCreationParams() const { return m_CreationParams; }
+
+ // Returns |true| iff this instance is still allocated.
+ bool InvalidateRectMove(const CFX_FloatRect& rcOld,
+ const CFX_FloatRect& rcNew);
+
+ bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const;
+ bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const;
+ const CPWL_Wnd* GetRootWnd() const;
+
+ static bool IsCTRLpressed(uint32_t nFlag) {
+ return CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
+ }
+ static bool IsSHIFTpressed(uint32_t nFlag) {
+ return CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
+ }
+ static bool IsALTpressed(uint32_t nFlag) {
+ return CPDFSDK_FormFillEnvironment::IsALTKeyDown(nFlag);
+ }
+
+ private:
+ CFX_PointF ParentToChild(const CFX_PointF& point) const;
+ CFX_FloatRect ParentToChild(const CFX_FloatRect& rect) const;
+
+ void DrawChildAppearance(CFX_RenderDevice* pDevice,
+ const CFX_Matrix& mtUser2Device);
+
+ CFX_FloatRect PWLtoWnd(const CFX_FloatRect& rect) const;
+
+ void AddChild(CPWL_Wnd* pWnd);
+ void RemoveChild(CPWL_Wnd* pWnd);
+
+ void CreateScrollBar(const CreateParams& cp);
+ void CreateVScrollBar(const CreateParams& cp);
+
+ void AdjustStyle();
+ void CreateMsgControl();
+ void DestroyMsgControl();
+
+ CPWL_MsgControl* GetMsgControl() const;
+
+ CreateParams m_CreationParams;
+ std::vector<CPWL_Wnd*> m_Children;
+ UnownedPtr<CPWL_ScrollBar> m_pVScrollBar;
+ CFX_FloatRect m_rcWindow;
+ CFX_FloatRect m_rcClip;
+ bool m_bCreated;
+ bool m_bVisible;
+ bool m_bNotifying;
+ bool m_bEnabled;
+};
+
+#endif // FPDFSDK_PWL_CPWL_WND_H_