From c411eb943bb51e16ff4fb5a6ffb06e277ca6a982 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Tue, 25 Jul 2017 09:39:30 -0400 Subject: Move fpdfsdk/pdfwindow to fpdfsdk/pwl This makes it clearer what the directory contains. Change-Id: I34fc38dd30b8e0f6e057052ea33c8b5a10f1b9c3 Reviewed-on: https://pdfium-review.googlesource.com/8791 Commit-Queue: dsinclair Reviewed-by: Henrique Nakashima Reviewed-by: Tom Sepez --- BUILD.gn | 72 +- docs/getting-started.md | 2 +- fpdfsdk/cpdfsdk_widget.cpp | 4 +- fpdfsdk/formfiller/cba_fontmap.h | 2 +- fpdfsdk/formfiller/cffl_checkbox.cpp | 2 +- fpdfsdk/formfiller/cffl_combobox.cpp | 2 +- fpdfsdk/formfiller/cffl_interactiveformfiller.h | 2 +- fpdfsdk/formfiller/cffl_listbox.cpp | 2 +- fpdfsdk/formfiller/cffl_pushbutton.cpp | 2 +- fpdfsdk/formfiller/cffl_radiobutton.cpp | 2 +- fpdfsdk/fpdf_sysfontinfo.cpp | 2 +- fpdfsdk/javascript/color.h | 2 +- fpdfsdk/pdfwindow/cpwl_appstream.cpp | 1992 -------------------- fpdfsdk/pdfwindow/cpwl_appstream.h | 43 - fpdfsdk/pdfwindow/cpwl_button.cpp | 38 - fpdfsdk/pdfwindow/cpwl_button.h | 27 - fpdfsdk/pdfwindow/cpwl_caret.cpp | 114 -- fpdfsdk/pdfwindow/cpwl_caret.h | 41 - fpdfsdk/pdfwindow/cpwl_combo_box.cpp | 541 ------ fpdfsdk/pdfwindow/cpwl_combo_box.h | 103 -- fpdfsdk/pdfwindow/cpwl_combo_box_embeddertest.cpp | 268 --- fpdfsdk/pdfwindow/cpwl_edit.cpp | 709 ------- fpdfsdk/pdfwindow/cpwl_edit.h | 129 -- fpdfsdk/pdfwindow/cpwl_edit_ctrl.cpp | 420 ----- fpdfsdk/pdfwindow/cpwl_edit_ctrl.h | 96 - fpdfsdk/pdfwindow/cpwl_edit_embeddertest.cpp | 187 -- fpdfsdk/pdfwindow/cpwl_edit_impl.cpp | 2053 --------------------- fpdfsdk/pdfwindow/cpwl_edit_impl.h | 515 ------ fpdfsdk/pdfwindow/cpwl_font_map.cpp | 413 ----- fpdfsdk/pdfwindow/cpwl_font_map.h | 95 - fpdfsdk/pdfwindow/cpwl_icon.cpp | 131 -- fpdfsdk/pdfwindow/cpwl_icon.h | 44 - fpdfsdk/pdfwindow/cpwl_list_box.cpp | 375 ---- fpdfsdk/pdfwindow/cpwl_list_box.h | 110 -- fpdfsdk/pdfwindow/cpwl_list_impl.cpp | 637 ------- fpdfsdk/pdfwindow/cpwl_list_impl.h | 168 -- fpdfsdk/pdfwindow/cpwl_scroll_bar.cpp | 881 --------- fpdfsdk/pdfwindow/cpwl_scroll_bar.h | 184 -- fpdfsdk/pdfwindow/cpwl_special_button.cpp | 80 - fpdfsdk/pdfwindow/cpwl_special_button.h | 56 - fpdfsdk/pdfwindow/cpwl_timer.cpp | 62 - fpdfsdk/pdfwindow/cpwl_timer.h | 32 - fpdfsdk/pdfwindow/cpwl_timer_handler.cpp | 27 - fpdfsdk/pdfwindow/cpwl_timer_handler.h | 32 - fpdfsdk/pdfwindow/cpwl_wnd.cpp | 806 -------- fpdfsdk/pdfwindow/cpwl_wnd.h | 344 ---- fpdfsdk/pwl/cpwl_appstream.cpp | 1992 ++++++++++++++++++++ fpdfsdk/pwl/cpwl_appstream.h | 43 + fpdfsdk/pwl/cpwl_button.cpp | 38 + fpdfsdk/pwl/cpwl_button.h | 27 + fpdfsdk/pwl/cpwl_caret.cpp | 114 ++ fpdfsdk/pwl/cpwl_caret.h | 41 + fpdfsdk/pwl/cpwl_combo_box.cpp | 541 ++++++ fpdfsdk/pwl/cpwl_combo_box.h | 103 ++ fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp | 268 +++ fpdfsdk/pwl/cpwl_edit.cpp | 709 +++++++ fpdfsdk/pwl/cpwl_edit.h | 129 ++ fpdfsdk/pwl/cpwl_edit_ctrl.cpp | 420 +++++ fpdfsdk/pwl/cpwl_edit_ctrl.h | 96 + fpdfsdk/pwl/cpwl_edit_embeddertest.cpp | 187 ++ fpdfsdk/pwl/cpwl_edit_impl.cpp | 2053 +++++++++++++++++++++ fpdfsdk/pwl/cpwl_edit_impl.h | 515 ++++++ fpdfsdk/pwl/cpwl_font_map.cpp | 413 +++++ fpdfsdk/pwl/cpwl_font_map.h | 95 + fpdfsdk/pwl/cpwl_icon.cpp | 131 ++ fpdfsdk/pwl/cpwl_icon.h | 44 + fpdfsdk/pwl/cpwl_list_box.cpp | 375 ++++ fpdfsdk/pwl/cpwl_list_box.h | 110 ++ fpdfsdk/pwl/cpwl_list_impl.cpp | 637 +++++++ fpdfsdk/pwl/cpwl_list_impl.h | 168 ++ fpdfsdk/pwl/cpwl_scroll_bar.cpp | 881 +++++++++ fpdfsdk/pwl/cpwl_scroll_bar.h | 184 ++ fpdfsdk/pwl/cpwl_special_button.cpp | 80 + fpdfsdk/pwl/cpwl_special_button.h | 56 + fpdfsdk/pwl/cpwl_timer.cpp | 62 + fpdfsdk/pwl/cpwl_timer.h | 32 + fpdfsdk/pwl/cpwl_timer_handler.cpp | 27 + fpdfsdk/pwl/cpwl_timer_handler.h | 32 + fpdfsdk/pwl/cpwl_wnd.cpp | 806 ++++++++ fpdfsdk/pwl/cpwl_wnd.h | 344 ++++ 80 files changed, 11801 insertions(+), 11801 deletions(-) delete mode 100644 fpdfsdk/pdfwindow/cpwl_appstream.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_appstream.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_button.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_button.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_caret.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_caret.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_combo_box.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_combo_box.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_combo_box_embeddertest.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_edit.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_edit.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_edit_ctrl.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_edit_ctrl.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_edit_embeddertest.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_edit_impl.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_edit_impl.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_font_map.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_font_map.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_icon.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_icon.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_list_box.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_list_box.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_list_impl.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_list_impl.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_scroll_bar.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_scroll_bar.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_special_button.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_special_button.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_timer.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_timer.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_timer_handler.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_timer_handler.h delete mode 100644 fpdfsdk/pdfwindow/cpwl_wnd.cpp delete mode 100644 fpdfsdk/pdfwindow/cpwl_wnd.h create mode 100644 fpdfsdk/pwl/cpwl_appstream.cpp create mode 100644 fpdfsdk/pwl/cpwl_appstream.h create mode 100644 fpdfsdk/pwl/cpwl_button.cpp create mode 100644 fpdfsdk/pwl/cpwl_button.h create mode 100644 fpdfsdk/pwl/cpwl_caret.cpp create mode 100644 fpdfsdk/pwl/cpwl_caret.h create mode 100644 fpdfsdk/pwl/cpwl_combo_box.cpp create mode 100644 fpdfsdk/pwl/cpwl_combo_box.h create mode 100644 fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp create mode 100644 fpdfsdk/pwl/cpwl_edit.cpp create mode 100644 fpdfsdk/pwl/cpwl_edit.h create mode 100644 fpdfsdk/pwl/cpwl_edit_ctrl.cpp create mode 100644 fpdfsdk/pwl/cpwl_edit_ctrl.h create mode 100644 fpdfsdk/pwl/cpwl_edit_embeddertest.cpp create mode 100644 fpdfsdk/pwl/cpwl_edit_impl.cpp create mode 100644 fpdfsdk/pwl/cpwl_edit_impl.h create mode 100644 fpdfsdk/pwl/cpwl_font_map.cpp create mode 100644 fpdfsdk/pwl/cpwl_font_map.h create mode 100644 fpdfsdk/pwl/cpwl_icon.cpp create mode 100644 fpdfsdk/pwl/cpwl_icon.h create mode 100644 fpdfsdk/pwl/cpwl_list_box.cpp create mode 100644 fpdfsdk/pwl/cpwl_list_box.h create mode 100644 fpdfsdk/pwl/cpwl_list_impl.cpp create mode 100644 fpdfsdk/pwl/cpwl_list_impl.h create mode 100644 fpdfsdk/pwl/cpwl_scroll_bar.cpp create mode 100644 fpdfsdk/pwl/cpwl_scroll_bar.h create mode 100644 fpdfsdk/pwl/cpwl_special_button.cpp create mode 100644 fpdfsdk/pwl/cpwl_special_button.h create mode 100644 fpdfsdk/pwl/cpwl_timer.cpp create mode 100644 fpdfsdk/pwl/cpwl_timer.h create mode 100644 fpdfsdk/pwl/cpwl_timer_handler.cpp create mode 100644 fpdfsdk/pwl/cpwl_timer_handler.h create mode 100644 fpdfsdk/pwl/cpwl_wnd.cpp create mode 100644 fpdfsdk/pwl/cpwl_wnd.h diff --git a/BUILD.gn b/BUILD.gn index ebe6c0dc46..9f8c52ae4b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -189,7 +189,7 @@ static_library("pdfium") { ":fxcrt", ":fxge", ":javascript", - ":pdfwindow", + ":pwl", "third_party:bigint", "third_party:pdfium_base", ] @@ -1076,40 +1076,40 @@ static_library("fxge") { } } -static_library("pdfwindow") { +static_library("pwl") { sources = [ - "fpdfsdk/pdfwindow/cpwl_appstream.cpp", - "fpdfsdk/pdfwindow/cpwl_appstream.h", - "fpdfsdk/pdfwindow/cpwl_button.cpp", - "fpdfsdk/pdfwindow/cpwl_button.h", - "fpdfsdk/pdfwindow/cpwl_caret.cpp", - "fpdfsdk/pdfwindow/cpwl_caret.h", - "fpdfsdk/pdfwindow/cpwl_combo_box.cpp", - "fpdfsdk/pdfwindow/cpwl_combo_box.h", - "fpdfsdk/pdfwindow/cpwl_edit.cpp", - "fpdfsdk/pdfwindow/cpwl_edit.h", - "fpdfsdk/pdfwindow/cpwl_edit_ctrl.cpp", - "fpdfsdk/pdfwindow/cpwl_edit_ctrl.h", - "fpdfsdk/pdfwindow/cpwl_edit_impl.cpp", - "fpdfsdk/pdfwindow/cpwl_edit_impl.h", - "fpdfsdk/pdfwindow/cpwl_font_map.cpp", - "fpdfsdk/pdfwindow/cpwl_font_map.h", - "fpdfsdk/pdfwindow/cpwl_icon.cpp", - "fpdfsdk/pdfwindow/cpwl_icon.h", - "fpdfsdk/pdfwindow/cpwl_list_box.cpp", - "fpdfsdk/pdfwindow/cpwl_list_box.h", - "fpdfsdk/pdfwindow/cpwl_list_impl.cpp", - "fpdfsdk/pdfwindow/cpwl_list_impl.h", - "fpdfsdk/pdfwindow/cpwl_scroll_bar.cpp", - "fpdfsdk/pdfwindow/cpwl_scroll_bar.h", - "fpdfsdk/pdfwindow/cpwl_special_button.cpp", - "fpdfsdk/pdfwindow/cpwl_special_button.h", - "fpdfsdk/pdfwindow/cpwl_timer.cpp", - "fpdfsdk/pdfwindow/cpwl_timer.h", - "fpdfsdk/pdfwindow/cpwl_timer_handler.cpp", - "fpdfsdk/pdfwindow/cpwl_timer_handler.h", - "fpdfsdk/pdfwindow/cpwl_wnd.cpp", - "fpdfsdk/pdfwindow/cpwl_wnd.h", + "fpdfsdk/pwl/cpwl_appstream.cpp", + "fpdfsdk/pwl/cpwl_appstream.h", + "fpdfsdk/pwl/cpwl_button.cpp", + "fpdfsdk/pwl/cpwl_button.h", + "fpdfsdk/pwl/cpwl_caret.cpp", + "fpdfsdk/pwl/cpwl_caret.h", + "fpdfsdk/pwl/cpwl_combo_box.cpp", + "fpdfsdk/pwl/cpwl_combo_box.h", + "fpdfsdk/pwl/cpwl_edit.cpp", + "fpdfsdk/pwl/cpwl_edit.h", + "fpdfsdk/pwl/cpwl_edit_ctrl.cpp", + "fpdfsdk/pwl/cpwl_edit_ctrl.h", + "fpdfsdk/pwl/cpwl_edit_impl.cpp", + "fpdfsdk/pwl/cpwl_edit_impl.h", + "fpdfsdk/pwl/cpwl_font_map.cpp", + "fpdfsdk/pwl/cpwl_font_map.h", + "fpdfsdk/pwl/cpwl_icon.cpp", + "fpdfsdk/pwl/cpwl_icon.h", + "fpdfsdk/pwl/cpwl_list_box.cpp", + "fpdfsdk/pwl/cpwl_list_box.h", + "fpdfsdk/pwl/cpwl_list_impl.cpp", + "fpdfsdk/pwl/cpwl_list_impl.h", + "fpdfsdk/pwl/cpwl_scroll_bar.cpp", + "fpdfsdk/pwl/cpwl_scroll_bar.h", + "fpdfsdk/pwl/cpwl_special_button.cpp", + "fpdfsdk/pwl/cpwl_special_button.h", + "fpdfsdk/pwl/cpwl_timer.cpp", + "fpdfsdk/pwl/cpwl_timer.h", + "fpdfsdk/pwl/cpwl_timer_handler.cpp", + "fpdfsdk/pwl/cpwl_timer_handler.h", + "fpdfsdk/pwl/cpwl_wnd.cpp", + "fpdfsdk/pwl/cpwl_wnd.h", ] configs += [ ":pdfium_core_config" ] deps = [ @@ -2009,8 +2009,8 @@ test("pdfium_embeddertests") { "fpdfsdk/fpdfview_c_api_test.h", "fpdfsdk/fpdfview_embeddertest.cpp", "fpdfsdk/fsdk_baseform_embeddertest.cpp", - "fpdfsdk/pdfwindow/cpwl_combo_box_embeddertest.cpp", - "fpdfsdk/pdfwindow/cpwl_edit_embeddertest.cpp", + "fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp", + "fpdfsdk/pwl/cpwl_edit_embeddertest.cpp", "testing/embedder_test.cpp", "testing/embedder_test.h", "testing/embedder_test_mock_delegate.h", diff --git a/docs/getting-started.md b/docs/getting-started.md index 8d46a74082..0cf2ff3d88 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -73,7 +73,7 @@ the link line in order to compile. My build line was: ``` PDF_LIBS="-lpdfium -lfpdfapi -lfxge -lfpdfdoc -lfxcrt -lfx_agg \ -lfxcodec -lfx_lpng -lfx_libopenjpeg -lfx_lcms2 -lfx_freetype -ljpeg \ --lfdrm -lpdfwindow -lbigint -lformfiller -ljavascript -lfxedit" +-lfdrm -lpwl -lbigint -lformfiller -ljavascript -lfxedit" PDF_DIR= clang -I $PDF_DIR/public -o init init.c -L $PDF_DIR/out/Debug -lstdc++ -framework AppKit $PDF_LIBS diff --git a/fpdfsdk/cpdfsdk_widget.cpp b/fpdfsdk/cpdfsdk_widget.cpp index 4b85333a2a..191f0dec0d 100644 --- a/fpdfsdk/cpdfsdk_widget.cpp +++ b/fpdfsdk/cpdfsdk_widget.cpp @@ -29,8 +29,8 @@ #include "fpdfsdk/formfiller/cba_fontmap.h" #include "fpdfsdk/fsdk_actionhandler.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/pdfwindow/cpwl_appstream.h" -#include "fpdfsdk/pdfwindow/cpwl_edit.h" +#include "fpdfsdk/pwl/cpwl_appstream.h" +#include "fpdfsdk/pwl/cpwl_edit.h" #ifdef PDF_ENABLE_XFA #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" diff --git a/fpdfsdk/formfiller/cba_fontmap.h b/fpdfsdk/formfiller/cba_fontmap.h index 17b7b4e989..7eb7d4e19c 100644 --- a/fpdfsdk/formfiller/cba_fontmap.h +++ b/fpdfsdk/formfiller/cba_fontmap.h @@ -8,7 +8,7 @@ #define FPDFSDK_FORMFILLER_CBA_FONTMAP_H_ #include "core/fxcrt/cfx_unowned_ptr.h" -#include "fpdfsdk/pdfwindow/cpwl_font_map.h" +#include "fpdfsdk/pwl/cpwl_font_map.h" class CPDF_Dictionary; class CPDFSDK_Annot; diff --git a/fpdfsdk/formfiller/cffl_checkbox.cpp b/fpdfsdk/formfiller/cffl_checkbox.cpp index 4bab95a54e..1a3ccca547 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/cpwl_special_button.h" +#include "fpdfsdk/pwl/cpwl_special_button.h" #include "public/fpdf_fwlevent.h" CFFL_CheckBox::CFFL_CheckBox(CPDFSDK_FormFillEnvironment* pApp, diff --git a/fpdfsdk/formfiller/cffl_combobox.cpp b/fpdfsdk/formfiller/cffl_combobox.cpp index cbd00bc171..c4554c1173 100644 --- a/fpdfsdk/formfiller/cffl_combobox.cpp +++ b/fpdfsdk/formfiller/cffl_combobox.cpp @@ -12,7 +12,7 @@ #include "fpdfsdk/formfiller/cffl_formfiller.h" #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" #include "fpdfsdk/fsdk_common.h" -#include "fpdfsdk/pdfwindow/cpwl_combo_box.h" +#include "fpdfsdk/pwl/cpwl_combo_box.h" #include "third_party/base/ptr_util.h" CFFL_ComboBox::CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp, diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.h b/fpdfsdk/formfiller/cffl_interactiveformfiller.h index 744d522fbc..17e9407924 100644 --- a/fpdfsdk/formfiller/cffl_interactiveformfiller.h +++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.h @@ -14,7 +14,7 @@ #include "core/fxcrt/cfx_unowned_ptr.h" #include "fpdfsdk/cpdfsdk_annot.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/pdfwindow/cpwl_edit.h" +#include "fpdfsdk/pwl/cpwl_edit.h" class CFFL_FormFiller; class CPDFSDK_FormFillEnvironment; diff --git a/fpdfsdk/formfiller/cffl_listbox.cpp b/fpdfsdk/formfiller/cffl_listbox.cpp index 4a6264d6dc..ca983d88df 100644 --- a/fpdfsdk/formfiller/cffl_listbox.cpp +++ b/fpdfsdk/formfiller/cffl_listbox.cpp @@ -12,7 +12,7 @@ #include "fpdfsdk/formfiller/cffl_formfiller.h" #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" #include "fpdfsdk/fsdk_common.h" -#include "fpdfsdk/pdfwindow/cpwl_list_box.h" +#include "fpdfsdk/pwl/cpwl_list_box.h" #include "third_party/base/ptr_util.h" #define FFL_DEFAULTLISTBOXFONTSIZE 12.0f diff --git a/fpdfsdk/formfiller/cffl_pushbutton.cpp b/fpdfsdk/formfiller/cffl_pushbutton.cpp index d0d51b7b37..2f75f4c16b 100644 --- a/fpdfsdk/formfiller/cffl_pushbutton.cpp +++ b/fpdfsdk/formfiller/cffl_pushbutton.cpp @@ -7,7 +7,7 @@ #include "fpdfsdk/formfiller/cffl_pushbutton.h" #include "fpdfsdk/formfiller/cffl_formfiller.h" -#include "fpdfsdk/pdfwindow/cpwl_special_button.h" +#include "fpdfsdk/pwl/cpwl_special_button.h" CFFL_PushButton::CFFL_PushButton(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget) diff --git a/fpdfsdk/formfiller/cffl_radiobutton.cpp b/fpdfsdk/formfiller/cffl_radiobutton.cpp index e36e1f7554..6c8d5a3883 100644 --- a/fpdfsdk/formfiller/cffl_radiobutton.cpp +++ b/fpdfsdk/formfiller/cffl_radiobutton.cpp @@ -9,7 +9,7 @@ #include "fpdfsdk/cpdfsdk_formfillenvironment.h" #include "fpdfsdk/cpdfsdk_widget.h" #include "fpdfsdk/formfiller/cffl_formfiller.h" -#include "fpdfsdk/pdfwindow/cpwl_special_button.h" +#include "fpdfsdk/pwl/cpwl_special_button.h" #include "public/fpdf_fwlevent.h" CFFL_RadioButton::CFFL_RadioButton(CPDFSDK_FormFillEnvironment* pApp, diff --git a/fpdfsdk/fpdf_sysfontinfo.cpp b/fpdfsdk/fpdf_sysfontinfo.cpp index c424152326..5dca4814d4 100644 --- a/fpdfsdk/fpdf_sysfontinfo.cpp +++ b/fpdfsdk/fpdf_sysfontinfo.cpp @@ -14,7 +14,7 @@ #include "core/fxge/fx_font.h" #include "core/fxge/ifx_systemfontinfo.h" #include "fpdfsdk/fsdk_define.h" -#include "fpdfsdk/pdfwindow/cpwl_font_map.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"); diff --git a/fpdfsdk/javascript/color.h b/fpdfsdk/javascript/color.h index e67d4d5ad5..5d6a65790c 100644 --- a/fpdfsdk/javascript/color.h +++ b/fpdfsdk/javascript/color.h @@ -10,7 +10,7 @@ #include #include "fpdfsdk/javascript/JS_Define.h" -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" class color : public CJS_EmbedObj { public: diff --git a/fpdfsdk/pdfwindow/cpwl_appstream.cpp b/fpdfsdk/pdfwindow/cpwl_appstream.cpp deleted file mode 100644 index 23ebf4f6d5..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_appstream.cpp +++ /dev/null @@ -1,1992 +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_appstream.h" - -#include - -#include "core/fpdfapi/parser/cpdf_dictionary.h" -#include "core/fpdfapi/parser/cpdf_document.h" -#include "core/fpdfapi/parser/cpdf_name.h" -#include "core/fpdfapi/parser/cpdf_number.h" -#include "core/fpdfapi/parser/cpdf_reference.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "core/fpdfapi/parser/cpdf_string.h" -#include "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/pdfwindow/cpwl_edit.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_impl.h" -#include "fpdfsdk/pdfwindow/cpwl_icon.h" -#include "fpdfsdk/pdfwindow/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, - CFX_ByteString open, - CFX_ByteString close) - : stream_(stream), close_(close) { - *stream_ << open << "\n"; - } - - virtual ~AutoClosedCommand() { *stream_ << close_ << "\n"; } - - private: - std::ostringstream* stream_; - CFX_ByteString close_; -}; - -class AutoClosedQCommand : public AutoClosedCommand { - public: - explicit AutoClosedQCommand(std::ostringstream* stream) - : AutoClosedCommand(stream, kStateSaveOperator, kStateRestoreOperator) {} - ~AutoClosedQCommand() override {} -}; - -CFX_ByteString GetColorAppStream(const CFX_Color& color, - const bool& bFillOrStroke) { - std::ostringstream sColorStream; - - switch (color.nColorType) { - case COLORTYPE_RGB: - sColorStream << color.fColor1 << " " << color.fColor2 << " " - << color.fColor3 << " " - << (bFillOrStroke ? kSetRGBOperator : kSetRGBStrokedOperator) - << "\n"; - break; - case COLORTYPE_GRAY: - sColorStream << color.fColor1 << " " - << (bFillOrStroke ? kSetGrayOperator - : kSetGrayStrokedOperator) - << "\n"; - break; - case COLORTYPE_CMYK: - sColorStream << color.fColor1 << " " << color.fColor2 << " " - << color.fColor3 << " " << color.fColor4 << " " - << (bFillOrStroke ? kSetCMYKOperator - : kSetCMKYStrokedOperator) - << "\n"; - break; - } - - return CFX_ByteString(sColorStream); -} - -CFX_ByteString GetAP_Check(const CFX_FloatRect& crBBox) { - const float fWidth = crBBox.right - crBBox.left; - const float fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f), - CFX_PointF(0.29f, 0.40f)}, - {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f), - CFX_PointF(0.31f, 0.28f)}, - {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f), - CFX_PointF(0.77f, 0.67f)}, - {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f), - CFX_PointF(0.76f, 0.75f)}, - {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f), - CFX_PointF(0.68f, 0.75f)}, - {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f), - CFX_PointF(0.44f, 0.47f)}, - {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f), - CFX_PointF(0.41f, 0.58f)}, - {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f), - CFX_PointF(0.30f, 0.56f)}}; - - for (size_t i = 0; i < FX_ArraySize(pts); ++i) { - for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) { - pts[i][j].x = pts[i][j].x * fWidth + crBBox.left; - pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom; - } - } - - std::ostringstream csAP; - csAP << pts[0][0].x << " " << pts[0][0].y << " " << 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 CFX_ByteString(csAP); -} - -CFX_ByteString GetAP_Circle(const CFX_FloatRect& crBBox) { - std::ostringstream csAP; - - float fWidth = crBBox.right - crBBox.left; - float fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); - CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); - CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); - CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); - - csAP << pt1.x << " " << pt1.y << " " << 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 CFX_ByteString(csAP); -} - -CFX_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 CFX_ByteString(csAP); -} - -CFX_ByteString GetAP_Diamond(const CFX_FloatRect& crBBox) { - std::ostringstream csAP; - - float fWidth = crBBox.right - crBBox.left; - float fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); - CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); - CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); - CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); - - csAP << pt1.x << " " << pt1.y << " " << 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 CFX_ByteString(csAP); -} - -CFX_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 CFX_ByteString(csAP); -} - -CFX_ByteString GetAP_Star(const CFX_FloatRect& crBBox) { - std::ostringstream csAP; - - float fRadius = (crBBox.top - crBBox.bottom) / (1 + (float)cos(FX_PI / 5.0f)); - CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f, - (crBBox.top + crBBox.bottom) / 2.0f); - - float px[5]; - float py[5]; - float fAngel = FX_PI / 10.0f; - for (int32_t i = 0; i < 5; i++) { - px[i] = ptCenter.x + fRadius * (float)cos(fAngel); - py[i] = ptCenter.y + fRadius * (float)sin(fAngel); - fAngel += FX_PI * 2 / 5.0f; - } - - csAP << px[0] << " " << py[0] << " " << 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 CFX_ByteString(csAP); -} - -CFX_ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, float fRotate) { - std::ostringstream csAP; - - float fWidth = crBBox.right - crBBox.left; - float fHeight = crBBox.top - crBBox.bottom; - - CFX_PointF pt1(-fWidth / 2, 0); - CFX_PointF pt2(0, fHeight / 2); - CFX_PointF pt3(fWidth / 2, 0); - - float px; - float py; - - csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " " - << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " " - << crBBox.bottom + fHeight / 2 << " " << 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 CFX_ByteString(csAP); -} - -CFX_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 CFX_ByteString(sAP); -} - -CFX_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 CFX_ByteString(sAP); -} - -CFX_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 CFX_ByteString(sAP); -} - -CFX_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 CFX_ByteString(sAP); -} - -CFX_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 CFX_ByteString(sAP); -} - -CFX_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 CFX_ByteString(sAP); -} - -CFX_ByteString GetCircleFillAppStream(const CFX_FloatRect& rect, - const CFX_Color& color) { - std::ostringstream sAppStream; - CFX_ByteString sColor = GetColorAppStream(color, true); - if (sColor.GetLength() > 0) { - AutoClosedQCommand q(&sAppStream); - sAppStream << sColor << GetAP_Circle(rect) << kFillOperator << "\n"; - } - return CFX_ByteString(sAppStream); -} - -CFX_ByteString GetCircleBorderAppStream(const CFX_FloatRect& rect, - float fWidth, - const CFX_Color& color, - const CFX_Color& crLeftTop, - const CFX_Color& crRightBottom, - BorderStyle nStyle, - const CPWL_Dash& dash) { - std::ostringstream sAppStream; - CFX_ByteString sColor; - - if (fWidth > 0.0f) { - 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 CFX_ByteString(sAppStream); -} - -CFX_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.Scale(2.0f / 3.0f); - return GetAppStream_Circle(rcCenter, crText); - case CheckStyle::kCross: - return GetAppStream_Cross(rcCenter, crText); - case CheckStyle::kDiamond: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Diamond(rcCenter, crText); - case CheckStyle::kSquare: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Square(rcCenter, crText); - case CheckStyle::kStar: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Star(rcCenter, crText); - } -} - -CFX_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.Scale(1.0f / 2.0f); - return GetAppStream_Circle(rcCenter, crText); - case CheckStyle::kCross: - return GetAppStream_Cross(rcCenter, crText); - case CheckStyle::kDiamond: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Diamond(rcCenter, crText); - case CheckStyle::kSquare: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Square(rcCenter, crText); - case CheckStyle::kStar: - rcCenter.Scale(2.0f / 3.0f); - return GetAppStream_Star(rcCenter, crText); - } -} - -CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - float fFontSize) { - if (!pFontMap) - return CFX_ByteString(); - - CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); - if (sFontAlias.GetLength() <= 0 || fFontSize <= 0) - return CFX_ByteString(); - - std::ostringstream sRet; - sRet << "/" << sFontAlias << " " << fFontSize << " " - << kSetTextFontAndSizeOperator << "\n"; - return CFX_ByteString(sRet); -} - -CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) { - if (strWords.GetLength() > 0) { - return PDF_EncodeString(strWords, false) + " " + kShowTextOperator + "\n"; - } - return CFX_ByteString(); -} - -CFX_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(CFX_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(CFX_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(CFX_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 CFX_ByteString(sAppStream); -} - -CFX_ByteString GenerateIconAppStream(CPDF_IconFit& fit, - CPDF_Stream* pIconStream, - const CFX_FloatRect& rcIcon) { - if (rcIcon.IsEmpty() || !pIconStream) - return CFX_ByteString(); - - CPWL_Icon icon; - PWL_CREATEPARAM cp; - cp.dwFlags = PWS_VISIBLE; - icon.Create(cp); - icon.SetIconFit(&fit); - icon.SetPDFStream(pIconStream); - icon.Move(rcIcon, false, false); - - CFX_ByteString sAlias = icon.GetImageAlias(); - if (sAlias.GetLength() <= 0) - return CFX_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 CFX_ByteString(str); -} - -CFX_ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox, - IPVT_FontMap* pFontMap, - CPDF_Stream* pIconStream, - CPDF_IconFit& IconFit, - const CFX_WideString& sLabel, - const CFX_Color& crText, - float fFontSize, - ButtonStyle nLayOut) { - const float fAutoFontScale = 1.0f / 3.0f; - - auto pEdit = pdfium::MakeUnique(); - pEdit->SetFontMap(pFontMap); - pEdit->SetAlignmentH(1, true); - pEdit->SetAlignmentV(1, true); - pEdit->SetMultiLine(false, true); - pEdit->SetAutoReturn(false, true); - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - pEdit->SetText(sLabel); - - CFX_FloatRect rcLabelContent = pEdit->GetContentRect(); - 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); - CFX_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 CFX_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 CFX_ByteString(sAppStream); -} - -CFX_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; - CFX_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 CFX_ByteString(sAppStream); -} - -CFX_ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox) { - if (rcBBox.IsEmpty()) - return CFX_ByteString(); - - std::ostringstream sAppStream; - { - AutoClosedQCommand q(&sAppStream); - sAppStream << GetColorAppStream(CFX_Color(COLORTYPE_RGB, 220.0f / 255.0f, - 220.0f / 255.0f, 220.0f / 255.0f), - true) - << rcBBox.left << " " << rcBBox.bottom << " " - << rcBBox.right - rcBBox.left << " " - << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator - << " " << kFillOperator << "\n"; - } - - { - AutoClosedQCommand q(&sAppStream); - sAppStream << GetBorderAppStreamInternal( - rcBBox, 2, CFX_Color(COLORTYPE_GRAY, 0), CFX_Color(COLORTYPE_GRAY, 1), - CFX_Color(COLORTYPE_GRAY, 0.5), BorderStyle::BEVELED, - CPWL_Dash(3, 0, 0)); - } - - 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 CFX_ByteString(sAppStream); -} - -CFX_ByteString GetRectFillAppStream(const CFX_FloatRect& rect, - const CFX_Color& color) { - std::ostringstream sAppStream; - CFX_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 CFX_ByteString(sAppStream); -} - -} // namespace - -CPWL_AppStream::CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict) - : widget_(widget), dict_(dict) {} - -CPWL_AppStream::~CPWL_AppStream() {} - -void CPWL_AppStream::SetAsPushButton() { - CPDF_FormControl* pControl = widget_->GetFormControl(); - CFX_FloatRect rcWindow = widget_->GetRotatedRect(); - 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(widget_->GetBorderWidth()); - CPWL_Dash dsBorder(3, 0, 0); - CFX_Color crLeftTop; - CFX_Color crRightBottom; - - BorderStyle nBorderStyle = widget_->GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); - CFX_Color crText(COLORTYPE_GRAY, 0); - CFX_ByteString csNameTag; - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - float fFontSize = 12.0f; - if (da.HasFont()) - csNameTag = da.GetFont(&fFontSize); - - CFX_WideString csWCaption; - CFX_WideString csNormalCaption; - CFX_WideString csRolloverCaption; - CFX_WideString csDownCaption; - if (pControl->HasMKEntry("CA")) - csNormalCaption = pControl->GetNormalCaption(); - - if (pControl->HasMKEntry("RC")) - csRolloverCaption = pControl->GetRolloverCaption(); - - if (pControl->HasMKEntry("AC")) - csDownCaption = pControl->GetDownCaption(); - - CPDF_Stream* pNormalIcon = nullptr; - CPDF_Stream* pRolloverIcon = nullptr; - CPDF_Stream* pDownIcon = nullptr; - if (pControl->HasMKEntry("I")) - pNormalIcon = pControl->GetNormalIcon(); - - if (pControl->HasMKEntry("RI")) - pRolloverIcon = pControl->GetRolloverIcon(); - - if (pControl->HasMKEntry("IX")) - pDownIcon = pControl->GetDownIcon(); - - if (pNormalIcon) { - if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgA", false); - } - } - - if (pRolloverIcon) { - if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgB", false); - } - } - - if (pDownIcon) { - if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) { - if (pImageDict->GetStringFor("Name").IsEmpty()) - pImageDict->SetNewFor("Name", "ImgC", false); - } - } - - CPDF_IconFit iconFit = pControl->GetIconFit(); - - CBA_FontMap font_map( - widget_.Get(), - widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); - font_map.SetAPType("N"); - - CFX_ByteString csAP = - 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(COLORTYPE_GRAY, 0); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 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(widget_->GetBorderWidth()); - CPWL_Dash dsBorder(3, 0, 0); - CFX_Color crLeftTop, crRightBottom; - - BorderStyle nBorderStyle = widget_->GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcWindow = widget_->GetRotatedRect(); - CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - - CheckStyle nStyle = CheckStyle::kCheck; - CFX_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; - } - } - - CFX_ByteString csAP_N_ON = - GetRectFillAppStream(rcWindow, crBackground) + - GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, - crRightBottom, nBorderStyle, dsBorder); - - CFX_ByteString csAP_N_OFF = csAP_N_ON; - - switch (nBorderStyle) { - case BorderStyle::BEVELED: { - CFX_Color crTemp = crLeftTop; - crLeftTop = crRightBottom; - crRightBottom = crTemp; - break; - } - case BorderStyle::INSET: { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - break; - } - default: - break; - } - - CFX_ByteString csAP_D_ON = - GetRectFillAppStream(rcWindow, crBackground - 0.25f) + - GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, - crRightBottom, nBorderStyle, dsBorder); - - CFX_ByteString csAP_D_OFF = csAP_D_ON; - - csAP_N_ON += GetCheckBoxAppStream(rcClient, nStyle, crText); - csAP_D_ON += GetCheckBoxAppStream(rcClient, nStyle, crText); - - Write("N", csAP_N_ON, pControl->GetCheckedAPState()); - Write("N", csAP_N_OFF, "Off"); - - Write("D", csAP_D_ON, pControl->GetCheckedAPState()); - Write("D", csAP_D_OFF, "Off"); - - CFX_ByteString csAS = widget_->GetAppState(); - if (csAS.IsEmpty()) - widget_->SetAppState("Off"); -} - -void CPWL_AppStream::SetAsRadioButton() { - CPDF_FormControl* pControl = widget_->GetFormControl(); - CFX_Color crBackground; - CFX_Color crBorder; - CFX_Color crText; - int iColorType; - float fc[4]; - - pControl->GetOriginalBackgroundColor(iColorType, fc); - if (iColorType > 0) - crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - pControl->GetOriginalBorderColor(iColorType, fc); - if (iColorType > 0) - crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - - float fBorderWidth = static_cast(widget_->GetBorderWidth()); - CPWL_Dash dsBorder(3, 0, 0); - CFX_Color crLeftTop; - CFX_Color crRightBottom; - BorderStyle nBorderStyle = widget_->GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - CFX_FloatRect rcWindow = widget_->GetRotatedRect(); - CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); - CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); - if (da.HasColor()) { - da.GetColor(iColorType, fc); - crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); - } - - CheckStyle nStyle = CheckStyle::kCircle; - CFX_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; - } - } - - CFX_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(COLORTYPE_GRAY, 1); - crRightBottom = crBackground - 0.25f; - } else if (nBorderStyle == BorderStyle::INSET) { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5f); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75f); - } - - csAP_N_ON = - GetCircleFillAppStream(rcCenter, crBackground) + - GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop, - crRightBottom, nBorderStyle, dsBorder); - } else { - csAP_N_ON = - GetRectFillAppStream(rcWindow, crBackground) + - GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, - crRightBottom, nBorderStyle, dsBorder); - } - - CFX_ByteString csAP_N_OFF = csAP_N_ON; - - switch (nBorderStyle) { - case BorderStyle::BEVELED: { - CFX_Color crTemp = crLeftTop; - crLeftTop = crRightBottom; - crRightBottom = crTemp; - break; - } - case BorderStyle::INSET: { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - break; - } - default: - break; - } - - CFX_ByteString csAP_D_ON; - - if (nStyle == CheckStyle::kCircle) { - CFX_Color crBK = crBackground - 0.25f; - if (nBorderStyle == BorderStyle::BEVELED) { - crLeftTop = crBackground - 0.25f; - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - crBK = crBackground; - } else if (nBorderStyle == BorderStyle::INSET) { - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); - } - - csAP_D_ON = - GetCircleFillAppStream(rcCenter, crBK) + - GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop, - crRightBottom, nBorderStyle, dsBorder); - } else { - csAP_D_ON = - GetRectFillAppStream(rcWindow, crBackground - 0.25f) + - GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, - crRightBottom, nBorderStyle, dsBorder); - } - - CFX_ByteString csAP_D_OFF = csAP_D_ON; - - csAP_N_ON += GetRadioButtonAppStream(rcClient, nStyle, crText); - csAP_D_ON += GetRadioButtonAppStream(rcClient, nStyle, crText); - - Write("N", csAP_N_ON, pControl->GetCheckedAPState()); - Write("N", csAP_N_OFF, "Off"); - - Write("D", csAP_D_ON, pControl->GetCheckedAPState()); - Write("D", csAP_D_OFF, "Off"); - - CFX_ByteString csAS = widget_->GetAppState(); - if (csAS.IsEmpty()) - widget_->SetAppState("Off"); -} - -void CPWL_AppStream::SetAsComboBox(const CFX_WideString* sValue) { - CPDF_FormControl* pControl = widget_->GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - std::ostringstream sBody; - - CFX_FloatRect rcClient = widget_->GetClientRect(); - CFX_FloatRect rcButton = rcClient; - rcButton.left = rcButton.right - 13; - rcButton.Normalize(); - - auto pEdit = pdfium::MakeUnique(); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map( - widget_.Get(), - widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - - CFX_FloatRect rcEdit = rcClient; - rcEdit.right = rcButton.left; - rcEdit.Normalize(); - - pEdit->SetPlateRect(rcEdit); - pEdit->SetAlignmentV(1, true); - - float fFontSize = widget_->GetFontSize(); - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - - if (sValue) { - pEdit->SetText(*sValue); - } else { - int32_t nCurSel = pField->GetSelectedIndex(0); - if (nCurSel < 0) - pEdit->SetText(pField->GetValue()); - else - pEdit->SetText(pField->GetOptionLabel(nCurSel)); - } - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - CFX_ByteString sEdit = 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() + CFX_ByteString(sBody), - ""); -} - -void CPWL_AppStream::SetAsListBox() { - CPDF_FormControl* pControl = widget_->GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - CFX_FloatRect rcClient = widget_->GetClientRect(); - std::ostringstream sBody; - - auto pEdit = pdfium::MakeUnique(); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map( - widget_.Get(), - widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f)); - - float fFontSize = widget_->GetFontSize(); - pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); - pEdit->Initialize(); - - std::ostringstream sList; - float fy = rcClient.top; - - int32_t nTop = pField->GetTopVisibleIndex(); - int32_t nCount = pField->CountOptions(); - int32_t nSelCount = pField->CountSelectedItems(); - - for (int32_t i = nTop; i < nCount; ++i) { - bool bSelected = false; - for (int32_t j = 0; j < nSelCount; ++j) { - if (pField->GetSelectedIndex(j) == i) { - bSelected = true; - break; - } - } - - pEdit->SetText(pField->GetOptionLabel(i)); - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - float fItemHeight = rcContent.Height(); - - if (bSelected) { - CFX_FloatRect rcItem = - CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy); - { - AutoClosedQCommand q(&sList); - sList << GetColorAppStream(CFX_Color(COLORTYPE_RGB, 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(COLORTYPE_GRAY, 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() + CFX_ByteString(sBody), - ""); -} - -void CPWL_AppStream::SetAsTextField(const CFX_WideString* sValue) { - CPDF_FormControl* pControl = widget_->GetFormControl(); - CPDF_FormField* pField = pControl->GetField(); - std::ostringstream sBody; - std::ostringstream sLines; - - auto pEdit = pdfium::MakeUnique(); - pEdit->EnableRefresh(false); - - CBA_FontMap font_map( - widget_.Get(), - widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); - pEdit->SetFontMap(&font_map); - - CFX_FloatRect rcClient = widget_->GetClientRect(); - pEdit->SetPlateRect(rcClient); - pEdit->SetAlignmentH(pControl->GetControlAlignment(), true); - - uint32_t dwFieldFlags = pField->GetFieldFlags(); - bool bMultiLine = (dwFieldFlags >> 12) & 1; - if (bMultiLine) { - pEdit->SetMultiLine(true, true); - pEdit->SetAutoReturn(true, true); - } else { - pEdit->SetAlignmentV(1, true); - } - - uint16_t subWord = 0; - if ((dwFieldFlags >> 13) & 1) { - subWord = '*'; - pEdit->SetPasswordChar(subWord, true); - } - - int nMaxLen = pField->GetMaxLen(); - bool bCharArray = (dwFieldFlags >> 24) & 1; - float fFontSize = widget_->GetFontSize(); - -#ifdef PDF_ENABLE_XFA - CFX_WideString sValueTmp; - if (!sValue && widget_->GetMixXFAWidget()) { - sValueTmp = widget_->GetValue(true); - sValue = &sValueTmp; - } -#endif // PDF_ENABLE_XFA - - if (nMaxLen > 0) { - if (bCharArray) { - pEdit->SetCharArray(nMaxLen); - - if (IsFloatZero(fFontSize)) { - fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0), - rcClient, nMaxLen); - } - } else { - if (sValue) - nMaxLen = sValue->GetLength(); - pEdit->SetLimitChar(nMaxLen); - } - } - - if (IsFloatZero(fFontSize)) - pEdit->SetAutoFontSize(true, true); - else - pEdit->SetFontSize(fFontSize); - - pEdit->Initialize(); - pEdit->SetText(sValue ? *sValue : pField->GetValue()); - - CFX_FloatRect rcContent = pEdit->GetContentRect(); - CFX_ByteString sEdit = - 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: { - CFX_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: { - CFX_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() + - CFX_ByteString(sLines) + CFX_ByteString(sBody), - ""); -} - -void CPWL_AppStream::AddImage(const CFX_ByteString& sAPType, - CPDF_Stream* pImage) { - CPDF_Stream* pStream = dict_->GetStreamFor(sAPType); - CPDF_Dictionary* pStreamDict = pStream->GetDict(); - CFX_ByteString sImageAlias = "IMG"; - - if (CPDF_Dictionary* pImageDict = pImage->GetDict()) { - sImageAlias = pImageDict->GetStringFor("Name"); - if (sImageAlias.IsEmpty()) - sImageAlias = "IMG"; - } - - CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); - if (!pStreamResList) - pStreamResList = pStreamDict->SetNewFor("Resources"); - - CPDF_Dictionary* pXObject = - pStreamResList->SetNewFor("XObject"); - pXObject->SetNewFor(sImageAlias, - widget_->GetPageView()->GetPDFDocument(), - pImage->GetObjNum()); -} - -void CPWL_AppStream::Write(const CFX_ByteString& sAPType, - const CFX_ByteString& sContents, - const CFX_ByteString& sAPState) { - CPDF_Stream* pStream = nullptr; - CPDF_Dictionary* pParentDict = nullptr; - if (sAPState.IsEmpty()) { - pParentDict = dict_.Get(); - pStream = dict_->GetStreamFor(sAPType); - } else { - CPDF_Dictionary* pAPTypeDict = dict_->GetDictFor(sAPType); - if (!pAPTypeDict) - pAPTypeDict = dict_->SetNewFor(sAPType); - - pParentDict = pAPTypeDict; - pStream = pAPTypeDict->GetStreamFor(sAPState); - } - - if (!pStream) { - CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument(); - pStream = doc->NewIndirect(); - pParentDict->SetNewFor(sAPType, doc, pStream->GetObjNum()); - } - - CPDF_Dictionary* pStreamDict = pStream->GetDict(); - if (!pStreamDict) { - auto pNewDict = pdfium::MakeUnique( - widget_->GetPDFAnnot()->GetDocument()->GetByteStringPool()); - pStreamDict = pNewDict.get(); - pStreamDict->SetNewFor("Type", "XObject"); - pStreamDict->SetNewFor("Subtype", "Form"); - pStreamDict->SetNewFor("FormType", 1); - pStream->InitStream(nullptr, 0, std::move(pNewDict)); - } - pStreamDict->SetMatrixFor("Matrix", widget_->GetMatrix()); - pStreamDict->SetRectFor("BBox", widget_->GetRotatedRect()); - pStream->SetData((uint8_t*)(sContents.c_str()), sContents.GetLength()); -} - -void CPWL_AppStream::Remove(const CFX_ByteString& sAPType) { - dict_->RemoveFor(sAPType); -} - -CFX_ByteString CPWL_AppStream::GetBackgroundAppStream() const { - CFX_Color crBackground = widget_->GetFillPWLColor(); - if (crBackground.nColorType != COLORTYPE_TRANSPARENT) - return GetRectFillAppStream(widget_->GetRotatedRect(), crBackground); - - return CFX_ByteString(); -} - -CFX_ByteString CPWL_AppStream::GetBorderAppStream() const { - CFX_FloatRect rcWindow = widget_->GetRotatedRect(); - CFX_Color crBorder = widget_->GetBorderPWLColor(); - CFX_Color crBackground = widget_->GetFillPWLColor(); - CFX_Color crLeftTop; - CFX_Color crRightBottom; - - float fBorderWidth = static_cast(widget_->GetBorderWidth()); - CPWL_Dash dsBorder(3, 0, 0); - - BorderStyle nBorderStyle = widget_->GetBorderStyle(); - switch (nBorderStyle) { - case BorderStyle::DASH: - dsBorder = CPWL_Dash(3, 3, 0); - break; - case BorderStyle::BEVELED: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); - crRightBottom = crBackground / 2.0f; - break; - case BorderStyle::INSET: - fBorderWidth *= 2; - crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); - crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); - break; - default: - break; - } - - return GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, - crRightBottom, nBorderStyle, dsBorder); -} diff --git a/fpdfsdk/pdfwindow/cpwl_appstream.h b/fpdfsdk/pdfwindow/cpwl_appstream.h deleted file mode 100644 index 56137864ec..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_appstream.h +++ /dev/null @@ -1,43 +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_APPSTREAM_H_ -#define FPDFSDK_PDFWINDOW_CPWL_APPSTREAM_H_ - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxcrt/fx_string.h" - -class CPDFSDK_Widget; -class CPDF_Dictionary; -class CPDF_Stream; - -class CPWL_AppStream { - public: - CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict); - ~CPWL_AppStream(); - - void SetAsPushButton(); - void SetAsCheckBox(); - void SetAsRadioButton(); - void SetAsComboBox(const CFX_WideString* sValue); - void SetAsListBox(); - void SetAsTextField(const CFX_WideString* sValue); - - private: - void AddImage(const CFX_ByteString& sAPType, CPDF_Stream* pImage); - void Write(const CFX_ByteString& sAPType, - const CFX_ByteString& sContents, - const CFX_ByteString& sAPState); - void Remove(const CFX_ByteString& sAPType); - - CFX_ByteString GetBackgroundAppStream() const; - CFX_ByteString GetBorderAppStream() const; - - CFX_UnownedPtr widget_; - CFX_UnownedPtr dict_; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_APPSTREAM_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_button.cpp b/fpdfsdk/pdfwindow/cpwl_button.cpp deleted file mode 100644 index fad3632875..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_button.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 "fpdfsdk/pdfwindow/cpwl_button.h" -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" - -CPWL_Button::CPWL_Button() : m_bMouseDown(false) {} - -CPWL_Button::~CPWL_Button() {} - -CFX_ByteString CPWL_Button::GetClassName() const { - return "CPWL_Button"; -} - -void CPWL_Button::OnCreate(PWL_CREATEPARAM& cp) { - cp.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/cpwl_button.h b/fpdfsdk/pdfwindow/cpwl_button.h deleted file mode 100644 index 9f4a47733e..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_button.h +++ /dev/null @@ -1,27 +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_CPWL_BUTTON_H_ -#define FPDFSDK_PDFWINDOW_CPWL_BUTTON_H_ - -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" - -class CPWL_Button : public CPWL_Wnd { - public: - CPWL_Button(); - ~CPWL_Button() override; - - // CPWL_Wnd - CFX_ByteString GetClassName() const override; - void OnCreate(PWL_CREATEPARAM& cp) override; - bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - - protected: - bool m_bMouseDown; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_BUTTON_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_caret.cpp b/fpdfsdk/pdfwindow/cpwl_caret.cpp deleted file mode 100644 index a9a5b86099..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_caret.cpp +++ /dev/null @@ -1,114 +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/cpwl_caret.h" - -#include - -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/pdfwindow/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() {} - -CFX_ByteString CPWL_Caret::GetClassName() const { - return "CPWL_Caret"; -} - -void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - 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, pUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0), - FXFILL_ALTERNATE); -} - -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 = *pRect; - if (!rcRefresh.IsEmpty()) { - rcRefresh.Inflate(0.5f, 0.5f); - rcRefresh.Normalize(); - } - rcRefresh.top += 1; - rcRefresh.bottom -= 1; - CPWL_Wnd::InvalidateRect(&rcRefresh); - } else { - CPWL_Wnd::InvalidateRect(pRect); - } -} diff --git a/fpdfsdk/pdfwindow/cpwl_caret.h b/fpdfsdk/pdfwindow/cpwl_caret.h deleted file mode 100644 index 6d6dcd557e..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_caret.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_PDFWINDOW_CPWL_CARET_H_ -#define FPDFSDK_PDFWINDOW_CPWL_CARET_H_ - -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" - -class CPWL_Caret : public CPWL_Wnd { - public: - CPWL_Caret(); - ~CPWL_Caret() override; - - // CPWL_Wnd - CFX_ByteString GetClassName() const 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); - 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_PDFWINDOW_CPWL_CARET_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_combo_box.cpp b/fpdfsdk/pdfwindow/cpwl_combo_box.cpp deleted file mode 100644 index 90c8cc6dc0..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_combo_box.cpp +++ /dev/null @@ -1,541 +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/cpwl_combo_box.h" - -#include -#include - -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/pdfwindow/cpwl_edit.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_ctrl.h" -#include "fpdfsdk/pdfwindow/cpwl_list_box.h" -#include "fpdfsdk/pdfwindow/cpwl_list_impl.h" -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" -#include "public/fpdf_fwlevent.h" - -namespace { - -constexpr float kDefaultFontSize = 12.0f; -constexpr float kTriangleHalfLength = 3.0f; - -} // 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, - CFX_Matrix* pUser2Device) { - CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); - - CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect(); - - if (!IsVisible() || rectWnd.IsEmpty()) - return; - - CFX_PointF ptCenter = GetCenterPoint(); - - CFX_PointF pt1(ptCenter.x - kTriangleHalfLength, - ptCenter.y + kTriangleHalfLength * 0.5f); - CFX_PointF pt2(ptCenter.x + kTriangleHalfLength, - ptCenter.y + kTriangleHalfLength * 0.5f); - CFX_PointF pt3(ptCenter.x, ptCenter.y - kTriangleHalfLength * 0.5f); - - if (IsFloatBigger(rectWnd.right - rectWnd.left, kTriangleHalfLength * 2) && - IsFloatBigger(rectWnd.top - rectWnd.bottom, kTriangleHalfLength)) { - 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->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() {} - -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::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() { - SetPopup(false); - CPWL_Wnd::KillFocus(); -} - -CFX_WideString CPWL_ComboBox::GetSelectedText() { - if (m_pEdit) - return m_pEdit->GetSelectedText(); - - return CFX_WideString(); -} - -void CPWL_ComboBox::DeleteSelectedText() { - if (m_pEdit) - m_pEdit->DeleteSelectedText(); -} - -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::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 PWL_CREATEPARAM& cp) { - CreateEdit(cp); - CreateButton(cp); - CreateListBox(cp); -} - -void CPWL_ComboBox::CreateEdit(const PWL_CREATEPARAM& cp) { - if (m_pEdit) - return; - - m_pEdit = new CPWL_Edit(); - m_pEdit->AttachFFLData(m_pFormFiller.Get()); - - 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(); - ecp.dwBorderWidth = 0; - ecp.nBorderStyle = BorderStyle::SOLID; - m_pEdit->Create(ecp); -} - -void CPWL_ComboBox::CreateButton(const PWL_CREATEPARAM& cp) { - if (m_pButton) - return; - - m_pButton = new CPWL_CBButton; - - PWL_CREATEPARAM bcp = cp; - bcp.pParentWnd = this; - bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND; - bcp.sBackgroundColor = CFX_Color(COLORTYPE_RGB, 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 PWL_CREATEPARAM& cp) { - if (m_pList) - return; - - m_pList = new CPWL_CBListBox(); - m_pList->AttachFFLData(m_pFormFiller.Get()); - - 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(); - - if (cp.dwFlags & PWS_AUTOFONTSIZE) - lcp.fFontSize = kDefaultFontSize; - 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() { - 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 - PWL_COMBOBOX_BUTTON_WIDTH, 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 (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); - } - return; - } - - CFX_FloatRect rcButton = rcClient; - rcButton.left = - std::max(rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH, rcClient.left); - - if (m_pButton) - m_pButton->Move(rcButton, true, 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 (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; - float fListHeight = m_pList->GetContentRect().Height(); - if (!IsFloatBigger(fListHeight, 0.0f)) - return; - - if (!bPopup) { - m_bPopup = bPopup; - Move(m_rcOldWindow, true, true); - return; - } - - if (!m_pFillerNotify) - return; - -#ifdef PDF_ENABLE_XFA - if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), 0)) - return; -#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; - - 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; - - Move(rcWindow, true, true); -#ifdef PDF_ENABLE_XFA - m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), 0); -#endif // PDF_ENABLE_XFA -} - -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); -} - -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); -} - -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/cpwl_combo_box.h b/fpdfsdk/pdfwindow/cpwl_combo_box.h deleted file mode 100644 index 530ff0a07e..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_combo_box.h +++ /dev/null @@ -1,103 +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_CPWL_COMBO_BOX_H_ -#define FPDFSDK_PDFWINDOW_CPWL_COMBO_BOX_H_ - -#include - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "fpdfsdk/pdfwindow/cpwl_edit.h" -#include "fpdfsdk/pdfwindow/cpwl_list_box.h" -#include "fpdfsdk/pdfwindow/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); -}; - -#define PWL_COMBOBOX_BUTTON_WIDTH 13 - -class CPWL_CBButton : public CPWL_Wnd { - public: - CPWL_CBButton() {} - ~CPWL_CBButton() override {} - - // CPWL_Wnd - 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.Get(); } - - // CPWL_Wnd: - CFX_ByteString GetClassName() const override; - void OnCreate(PWL_CREATEPARAM& cp) 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 PWL_CREATEPARAM& cp) override; - void RePosChildWnd() override; - CFX_FloatRect GetFocusRect() const override; - void SetFocus() override; - void KillFocus() override; - CFX_WideString GetSelectedText() override; - void DeleteSelectedText() 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 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 PWL_CREATEPARAM& cp); - void CreateButton(const PWL_CREATEPARAM& cp); - void CreateListBox(const PWL_CREATEPARAM& cp); - void SetPopup(bool bPopup); - - CFX_UnownedPtr m_pEdit; - CFX_UnownedPtr m_pButton; - CFX_UnownedPtr m_pList; - CFX_FloatRect m_rcOldWindow; - bool m_bPopup = false; - bool m_bBottom = true; - int32_t m_nSelectItem = -1; - CFX_UnownedPtr m_pFillerNotify; - CFX_UnownedPtr m_pFormFiller; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_COMBO_BOX_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_combo_box_embeddertest.cpp b/fpdfsdk/pdfwindow/cpwl_combo_box_embeddertest.cpp deleted file mode 100644 index 3224284ee2..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_combo_box_embeddertest.cpp +++ /dev/null @@ -1,268 +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. - -#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/pdfwindow/cpwl_combo_box.h" -#include "fpdfsdk/pdfwindow/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(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(pWindow); - } - - 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()); - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE( - GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); - } - - 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()); -} - -TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEntireTextSelection) { - FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE( - GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); - } - - GetCPWLComboBox()->SetEditSelection(0, -1); - EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", - GetCPWLComboBox()->GetSelectedText().c_str()); - - GetCPWLComboBox()->DeleteSelectedText(); - EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty()); -} - -TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionMiddle) { - FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE( - GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); - } - - GetCPWLComboBox()->SetEditSelection(12, 23); - EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str()); - - GetCPWLComboBox()->DeleteSelectedText(); - EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", - GetCPWLComboBox()->GetText().c_str()); -} - -TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionLeft) { - FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE( - GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); - } - - GetCPWLComboBox()->SetEditSelection(0, 5); - EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str()); - - GetCPWLComboBox()->DeleteSelectedText(); - EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", - GetCPWLComboBox()->GetText().c_str()); -} - -TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionRight) { - FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE( - GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); - } - - GetCPWLComboBox()->SetEditSelection(45, 50); - EXPECT_STREQ(L"nopqr", GetCPWLComboBox()->GetSelectedText().c_str()); - - GetCPWLComboBox()->DeleteSelectedText(); - EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", - GetCPWLComboBox()->GetText().c_str()); -} - -TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEmptyTextSelection) { - FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE( - GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); - } - - GetCPWLComboBox()->DeleteSelectedText(); - EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", - GetCPWLComboBox()->GetText().c_str()); -} diff --git a/fpdfsdk/pdfwindow/cpwl_edit.cpp b/fpdfsdk/pdfwindow/cpwl_edit.cpp deleted file mode 100644 index 8588de73c6..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_edit.cpp +++ /dev/null @@ -1,709 +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/cpwl_edit.h" - -#include -#include -#include -#include - -#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/pdfwindow/cpwl_caret.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_ctrl.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_impl.h" -#include "fpdfsdk/pdfwindow/cpwl_font_map.h" -#include "fpdfsdk/pdfwindow/cpwl_scroll_bar.h" -#include "fpdfsdk/pdfwindow/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); -} - -CFX_ByteString CPWL_Edit::GetClassName() const { - return PWL_CLASSNAME_EDIT; -} - -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 pXML( - CXML_Element::Parse(sValue.c_str(), sValue.GetLength())); - if (!pXML) { - m_pEdit->SetText(swText); - return; - } - swText.clear(); - - bool bFirst = true; - int32_t nCount = pXML->CountChildren(); - for (int32_t i = 0; i < nCount; i++) { - CXML_Element* pSubElement = ToElement(pXML->GetChild(i)); - if (!pSubElement || !pSubElement->GetTagName().EqualNoCase("p")) - continue; - - CFX_WideString swSection; - int nSubChild = pSubElement->CountChildren(); - for (int32_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); -} - -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)) { - CFX_FloatRect rect = GetClientRect(); - if (!rect.IsEmpty()) { - // +1 for caret beside border - rect.Inflate(1.0f, 1.0f); - rect.Normalize(); - } - m_pEditCaret->SetClipRect(rect); - } - - CPWL_EditCtrl::RePosChildWnd(); -} - -CFX_FloatRect CPWL_Edit::GetClientRect() const { - float width = static_cast(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::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->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->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()); - 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, - CFX_Matrix* pUser2Device) { - CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); - - 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, pUser2Device, &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, 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(); - CPWL_EditImpl::DrawEdit(pDevice, pUser2Device, 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(); - - 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() { - CPWL_ScrollBar* pScroll = GetVScrollBar(); - if (pScroll && pScroll->IsVisible()) { - pScroll->SetVisible(false); - Move(m_rcOldWindow, true, true); - } - - m_pEdit->SelectNone(); - SetCaret(false, CFX_PointF(), CFX_PointF()); - 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()) { - 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); - } - - return CPVT_WordRange(); -} - -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()) { - 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; - } - - 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()) { - 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->ClearSelection(); - m_pEdit->InsertText(wsText, FX_CHARSET_Default); -} - -CFX_FloatRect CPWL_Edit::GetFocusRect() const { - return CFX_FloatRect(); -} - -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) { - CFX_WideString strChange; - CFX_WideString strChangeEx; - - int nSelStart = 0; - int nSelEnd = 0; - GetSelection(nSelStart, nSelEnd); - - if (nSelStart == nSelEnd) - nSelEnd = nSelStart + 1; - - bool bRC; - bool bExit; - std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke( - GetAttachedData(), strChange, strChangeEx, nSelStart, nSelEnd, true, - 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; - 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; - } - - CFX_WideString strChangeEx; - std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke( - GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, true, - nFlag); - } - } - - 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)) { - 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) { - 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); -} - -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; - - 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/pdfwindow/cpwl_edit.h b/fpdfsdk/pdfwindow/cpwl_edit.h deleted file mode 100644 index 366d085fdd..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_edit.h +++ /dev/null @@ -1,129 +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_CPWL_EDIT_H_ -#define FPDFSDK_PDFWINDOW_CPWL_EDIT_H_ - -#include - -#include "core/fpdfdoc/cpvt_wordrange.h" -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxcrt/fx_basic.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_ctrl.h" - -class IPWL_Filler_Notify { - public: - virtual ~IPWL_Filler_Notify() {} - - // Must write to |bBottom| and |fPopupRet|. - virtual void QueryWherePopup(void* pPrivateData, - float fPopupMin, - float fPopupMax, - bool* bBottom, - float* fPopupRet) = 0; - virtual std::pair OnBeforeKeyStroke( - void* pPrivateData, - CFX_WideString& strChange, - const CFX_WideString& strChangeEx, - int nSelStart, - int nSelEnd, - bool bKeyDown, - uint32_t nFlag) = 0; -#ifdef PDF_ENABLE_XFA - virtual bool OnPopupPreOpen(void* pPrivateData, uint32_t nFlag) = 0; - virtual bool OnPopupPostOpen(void* pPrivateData, 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 OnCreated() override; - void RePosChildWnd() override; - CFX_FloatRect GetClientRect() const 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(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); - - 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; - } - - 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; - 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 GetArabicWordsRange(const CPVT_WordPlace& place) const; - CPVT_WordRange GetSameWordsRange(const CPVT_WordPlace& place, - bool bLatin, - bool bArabic) const; - - bool m_bFocus; - CFX_FloatRect m_rcOldWindow; - CFX_UnownedPtr m_pFillerNotify; - CFX_UnownedPtr m_pFormFiller; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_EDIT_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_edit_ctrl.cpp b/fpdfsdk/pdfwindow/cpwl_edit_ctrl.cpp deleted file mode 100644 index a3aac19e20..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_edit_ctrl.cpp +++ /dev/null @@ -1,420 +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/cpwl_edit_ctrl.h" - -#include "core/fpdfdoc/cpvt_section.h" -#include "core/fpdfdoc/cpvt_word.h" -#include "core/fxge/fx_font.h" -#include "fpdfsdk/pdfwindow/cpwl_caret.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_impl.h" -#include "fpdfsdk/pdfwindow/cpwl_font_map.h" -#include "fpdfsdk/pdfwindow/cpwl_scroll_bar.h" -#include "fpdfsdk/pdfwindow/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(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); - } - } -} - -CFX_WideString CPWL_EditCtrl::GetSelectedText() { - if (m_pEdit) - return m_pEdit->GetSelectedText(); - - return CFX_WideString(); -} - -void CPWL_EditCtrl::DeleteSelectedText() { - if (m_pEdit) - m_pEdit->ClearSelection(); -} - -void CPWL_EditCtrl::RePosChildWnd() { - m_pEdit->SetPlateRect(GetClientRect()); -} - -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 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(); - - 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(); - - 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); -} - -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; - } -} - -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::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/pdfwindow/cpwl_edit_ctrl.h b/fpdfsdk/pdfwindow/cpwl_edit_ctrl.h deleted file mode 100644 index 30c2d63419..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_edit_ctrl.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_PDFWINDOW_CPWL_EDIT_CTRL_H_ -#define FPDFSDK_PDFWINDOW_CPWL_EDIT_CTRL_H_ - -#include - -#include "core/fxcrt/fx_string.h" -#include "fpdfsdk/pdfwindow/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; - - CFX_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(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 SetScrollInfo(const PWL_SCROLL_INFO& info) override; - void SetScrollPosition(float pos) override; - void ScrollWindowVertically(float pos) override; - void CreateChildWnd(const PWL_CREATEPARAM& cp) override; - void RePosChildWnd() override; - void SetFontSize(float fFontSize) override; - float GetFontSize() const override; - void SetCursor() override; - CFX_WideString GetSelectedText() override; - void DeleteSelectedText() override; - - void 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 m_pEdit; - CPWL_Caret* m_pEditCaret; - bool m_bMouseDown; - - private: - void CreateEditCaret(const PWL_CREATEPARAM& cp); - - int32_t m_nCharSet; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_EDIT_CTRL_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_edit_embeddertest.cpp b/fpdfsdk/pdfwindow/cpwl_edit_embeddertest.cpp deleted file mode 100644 index 2b1bbd4445..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_edit_embeddertest.cpp +++ /dev/null @@ -1,187 +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. - -#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/pdfwindow/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.pdf")); - m_page = LoadPage(0); - ASSERT_TRUE(m_page); - - CPDFSDK_FormFillEnvironment* pFormFillEnv = - static_cast(form_handle()); - - { - CBA_AnnotIterator iter(pFormFillEnv->GetPageView(0), - CPDF_Annot::Subtype::WIDGET); - m_pAnnot = iter.GetFirstAnnot(); - CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot(); - ASSERT_EQ(m_pAnnot, pLastAnnot); - ASSERT_TRUE(m_pAnnot); - ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnot->GetAnnotSubtype()); - } - - CFFL_InteractiveFormFiller* pInteractiveFormFiller = - pFormFillEnv->GetInteractiveFormFiller(); - { - CPDFSDK_Annot::ObservedPtr pObserved(m_pAnnot); - EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0)); - } - - m_pFormFiller = pInteractiveFormFiller->GetFormFiller(m_pAnnot, false); - ASSERT_TRUE(m_pFormFiller); - - CPWL_Wnd* pWindow = - m_pFormFiller->GetPDFWindow(pFormFillEnv->GetPageView(0), false); - ASSERT_TRUE(pWindow); - ASSERT_EQ(PWL_CLASSNAME_EDIT, pWindow->GetClassName()); - - m_pEdit = static_cast(pWindow); - } - - FPDF_PAGE GetPage() { return m_page; } - CPWL_Edit* GetCPWLEdit() { return m_pEdit; } - CFFL_FormFiller* GetCFFLFormFiller() { return m_pFormFiller; } - CPDFSDK_Annot* GetCPDFSDKAnnot() { return m_pAnnot; } - - private: - FPDF_PAGE m_page; - CPWL_Edit* m_pEdit; - CFFL_FormFiller* m_pFormFiller; - CPDFSDK_Annot* m_pAnnot; -}; - -TEST_F(CPWLEditEmbeddertest, TypeText) { - 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) { - // 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) { - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); - } - - 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()); -} - -TEST_F(CPWLEditEmbeddertest, DeleteEntireTextSelection) { - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); - } - - GetCPWLEdit()->SetSelection(0, -1); - EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", - GetCPWLEdit()->GetSelectedText().c_str()); - - GetCPWLEdit()->DeleteSelectedText(); - EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty()); -} - -TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionMiddle) { - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); - } - - GetCPWLEdit()->SetSelection(12, 23); - EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); - - GetCPWLEdit()->DeleteSelectedText(); - EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", - GetCPWLEdit()->GetText().c_str()); -} - -TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionLeft) { - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); - } - - GetCPWLEdit()->SetSelection(0, 5); - EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str()); - - GetCPWLEdit()->DeleteSelectedText(); - EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", - GetCPWLEdit()->GetText().c_str()); -} - -TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionRight) { - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); - } - - GetCPWLEdit()->SetSelection(45, 50); - EXPECT_STREQ(L"nopqr", GetCPWLEdit()->GetSelectedText().c_str()); - - GetCPWLEdit()->DeleteSelectedText(); - EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", - GetCPWLEdit()->GetText().c_str()); -} - -TEST_F(CPWLEditEmbeddertest, DeleteEmptyTextSelection) { - for (int i = 0; i < 50; ++i) { - EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); - } - - GetCPWLEdit()->DeleteSelectedText(); - EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", - GetCPWLEdit()->GetText().c_str()); -} diff --git a/fpdfsdk/pdfwindow/cpwl_edit_impl.cpp b/fpdfsdk/pdfwindow/cpwl_edit_impl.cpp deleted file mode 100644 index 0f5cf05b10..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_edit_impl.cpp +++ /dev/null @@ -1,2053 +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/cpwl_edit_impl.h" - -#include -#include -#include -#include - -#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/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/pdfwindow/cpwl_edit.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_ctrl.h" -#include "fpdfsdk/pdfwindow/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, - 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 = CPDF_RenderOptions::kNormal; - - 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 = CPDF_RenderOptions::kNormal; - - CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize, - pUser2Device, 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->GetAt(); -} - -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.Add(linerange, rect); -} - -void CPWL_EditImpl_Refresh::NoAnalyse() { - { - for (int32_t i = 0, sz = m_OldLineRects.GetSize(); i < sz; i++) - if (CPWL_EditImpl_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 (CPWL_EditImpl_LineRect* pNewRect = m_NewLineRects.GetAt(i)) - m_RefreshRects.Add(pNewRect->m_rcLine); - } -} - -const CPWL_EditImpl_RectArray* CPWL_EditImpl_Refresh::GetRefreshRects() const { - return &m_RefreshRects; -} - -void CPWL_EditImpl_Refresh::EndRefresh() { - m_RefreshRects.Clear(); -} - -CPWL_EditImpl_Undo::CPWL_EditImpl_Undo(int32_t nBufsize) - : m_nCurUndoPos(0), m_nBufSize(nBufsize), m_bWorking(false) {} - -CPWL_EditImpl_Undo::~CPWL_EditImpl_Undo() { - Reset(); -} - -bool CPWL_EditImpl_Undo::CanUndo() const { - return m_nCurUndoPos > 0; -} - -void CPWL_EditImpl_Undo::Undo() { - m_bWorking = true; - if (m_nCurUndoPos > 0) { - 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 (m_nCurUndoPos < m_UndoItemStack.size()) { - m_UndoItemStack[m_nCurUndoPos]->Redo(); - m_nCurUndoPos++; - } - m_bWorking = false; -} - -void CPWL_EditImpl_Undo::AddItem(std::unique_ptr 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_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 (m_UndoItemStack.size() > m_nCurUndoPos) - m_UndoItemStack.pop_back(); -} - -void CPWL_EditImpl_Undo::Reset() { - m_UndoItemStack.clear(); - m_nCurUndoPos = 0; -} - -CPWL_EditImpl_UndoItem::CPWL_EditImpl_UndoItem() - : m_bFirst(true), m_bLast(true) {} - -CPWL_EditImpl_UndoItem::~CPWL_EditImpl_UndoItem() {} - -CFX_WideString CPWL_EditImpl_UndoItem::GetUndoTitle() const { - return CFX_WideString(); -} - -void CPWL_EditImpl_UndoItem::SetFirst(bool bFirst) { - m_bFirst = bFirst; -} - -void CPWL_EditImpl_UndoItem::SetLast(bool bLast) { - m_bLast = bLast; -} - -bool CPWL_EditImpl_UndoItem::IsLast() { - return m_bLast; -} - -CFXEU_InsertWord::CFXEU_InsertWord(CPWL_EditImpl* 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(CPWL_EditImpl* 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(CPWL_EditImpl* 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) - return; - - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpOld); - m_pEdit->Backspace(false, true); -} - -void CFXEU_Backspace::Undo() { - if (!m_pEdit) - return; - - m_pEdit->SelectNone(); - m_pEdit->SetCaret(m_wpNew); - if (m_wpNew.nSecIndex != m_wpOld.nSecIndex) - 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(CPWL_EditImpl* 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(CPWL_EditImpl* 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->SetSelection(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, 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 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->SetSelection(m_wpOld, m_wpNew); - m_pEdit->Clear(false, true); - } -} - -// static -void CPWL_EditImpl::DrawEdit(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - 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; - const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255); - 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()) { - CFX_FloatRect rcTemp = rcClip; - pUser2Device->TransformRect(rcTemp); - pDevice->SetClip_Rect(rcTemp.ToFxRect()); - } - - CPWL_EditImpl_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 > 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, pUser2Device, 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, pUser2Device, - CFX_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, pUser2Device, - 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, pUser2Device, - CFX_ByteString(sTextBuf), crOldFill, nHorzScale); - } - } -} - -CPWL_EditImpl::CPWL_EditImpl() - : 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) {} - -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(pFontMap); - m_pVT->SetProvider(m_pVTProvider.get()); -} - -void CPWL_EditImpl::SetNotify(CPWL_EditCtrl* pNotify) { - m_pNotify = pNotify; -} - -void CPWL_EditImpl::SetOprNotify(CPWL_Edit* pOprNotify) { - m_pOprNotify = pOprNotify; -} - -CPWL_EditImpl_Iterator* CPWL_EditImpl::GetIterator() { - if (!m_pIterator) { - m_pIterator = - pdfium::MakeUnique(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; -} - -CFX_WideString CPWL_EditImpl::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.nSecIndex != place.nSecIndex) - swRet += L"\r\n"; - oldplace = place; - } - return swRet; -} - -CFX_WideString CPWL_EditImpl::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 > wrTemp.EndPos) - break; - if (pIterator->GetWord(wordinfo)) - swRet += wordinfo.Word; - if (oldplace.nSecIndex != place.nSecIndex) - swRet += L"\r\n"; - oldplace = place; - } - return swRet; -} - -CFX_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 CFX_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, nullptr, true, true); -} - -bool CPWL_EditImpl::InsertReturn() { - return InsertReturn(nullptr, nullptr, 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 CFX_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; - - CFX_AutoRestorer 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) { - CFX_AutoRestorer 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) { - CFX_AutoRestorer restorer(&m_bNotifyFlag); - m_bNotifyFlag = true; - if (const CPWL_EditImpl_RectArray* pRects = - m_Refresh.GetRefreshRects()) { - for (int32_t i = 0, sz = pRects->GetSize(); i < sz; i++) - m_pNotify->InvalidateRect(pRects->GetAt(i)); - } - } - } - - 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->GetAt(); - 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) { - CFX_AutoRestorer 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) { - CFX_AutoRestorer 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; - } - - CFX_AutoRestorer 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, - 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( - 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 CPWL_EditImpl::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( - 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 CPWL_EditImpl::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.nSecIndex != m_wpOldCaret.nSecIndex) { - AddEditUndoItem(pdfium::MakeUnique( - this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, - section.SecProps, section.WordProps)); - } else { - AddEditUndoItem(pdfium::MakeUnique( - 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 CPWL_EditImpl::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( - this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, - section.SecProps, section.WordProps, bSecEnd)); - } else { - AddEditUndoItem(pdfium::MakeUnique( - 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 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(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_bOprNotify && m_pOprNotify) - m_pOprNotify->OnClear(m_wpCaret, m_wpOldCaret); - - return true; -} - -bool CPWL_EditImpl::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( - 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 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; -} - -void CPWL_EditImpl::EnableOprNotify(bool bNotify) { - m_bOprNotify = bNotify; -} - -CPVT_WordPlace CPWL_EditImpl::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 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 pEditUndoItem) { - m_Undo.AddItem(std::move(pEditUndoItem)); -} - -CFX_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 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; -} - -CPWL_EditImpl_LineRectArray::CPWL_EditImpl_LineRectArray() {} - -CPWL_EditImpl_LineRectArray::~CPWL_EditImpl_LineRectArray() {} - -void CPWL_EditImpl_LineRectArray::operator=( - CPWL_EditImpl_LineRectArray&& that) { - m_LineRects = std::move(that.m_LineRects); -} - -void CPWL_EditImpl_LineRectArray::Add(const CPVT_WordRange& wrLine, - const CFX_FloatRect& rcLine) { - m_LineRects.push_back( - pdfium::MakeUnique(wrLine, rcLine)); -} - -int32_t CPWL_EditImpl_LineRectArray::GetSize() const { - return pdfium::CollectionSize(m_LineRects); -} - -CPWL_EditImpl_LineRect* CPWL_EditImpl_LineRectArray::GetAt( - int32_t nIndex) const { - if (nIndex < 0 || nIndex >= GetSize()) - return nullptr; - - return m_LineRects[nIndex].get(); -} - -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; -} - -CPWL_EditImpl_RectArray::CPWL_EditImpl_RectArray() {} - -CPWL_EditImpl_RectArray::~CPWL_EditImpl_RectArray() {} - -void CPWL_EditImpl_RectArray::Clear() { - m_Rects.clear(); -} - -void CPWL_EditImpl_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(rect)); -} - -int32_t CPWL_EditImpl_RectArray::GetSize() const { - return pdfium::CollectionSize(m_Rects); -} - -CFX_FloatRect* CPWL_EditImpl_RectArray::GetAt(int32_t nIndex) const { - if (nIndex < 0 || nIndex >= GetSize()) - return nullptr; - - return m_Rects[nIndex].get(); -} diff --git a/fpdfsdk/pdfwindow/cpwl_edit_impl.h b/fpdfsdk/pdfwindow/cpwl_edit_impl.h deleted file mode 100644 index 53ed8da0c2..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_edit_impl.h +++ /dev/null @@ -1,515 +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_CPWL_EDIT_IMPL_H_ -#define FPDFSDK_PDFWINDOW_CPWL_EDIT_IMPL_H_ - -#include -#include -#include - -#include "core/fpdfdoc/cpvt_secprops.h" -#include "core/fpdfdoc/cpvt_wordprops.h" -#include "core/fxcrt/cfx_unowned_ptr.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_LineRectArray { - public: - CPWL_EditImpl_LineRectArray(); - ~CPWL_EditImpl_LineRectArray(); - - void operator=(CPWL_EditImpl_LineRectArray&& rects); - void Add(const CPVT_WordRange& wrLine, const CFX_FloatRect& rcLine); - - int32_t GetSize() const; - CPWL_EditImpl_LineRect* GetAt(int32_t nIndex) const; - - private: - std::vector> m_LineRects; -}; - -class CPWL_EditImpl_RectArray { - public: - CPWL_EditImpl_RectArray(); - ~CPWL_EditImpl_RectArray(); - - void Clear(); - void Add(const CFX_FloatRect& rect); - - int32_t GetSize() const; - CFX_FloatRect* GetAt(int32_t nIndex) const; - - private: - std::vector> m_Rects; -}; - -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(); - const CPWL_EditImpl_RectArray* GetRefreshRects() const; - void EndRefresh(); - - private: - CPWL_EditImpl_LineRectArray m_NewLineRects; - CPWL_EditImpl_LineRectArray m_OldLineRects; - CPWL_EditImpl_RectArray 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: - explicit CPWL_EditImpl_Undo(int32_t nBufsize); - ~CPWL_EditImpl_Undo(); - - void AddItem(std::unique_ptr pItem); - void Undo(); - void Redo(); - bool CanUndo() const; - bool CanRedo() const; - void Reset(); - - private: - void RemoveHeads(); - void RemoveTails(); - - std::deque> m_UndoItemStack; - size_t m_nCurUndoPos; - size_t m_nBufSize; - 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 CPWL_EditImpl_UndoItem : public IFX_Edit_UndoItem { - public: - CPWL_EditImpl_UndoItem(); - ~CPWL_EditImpl_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 CFXEU_InsertWord : public CPWL_EditImpl_UndoItem { - public: - CFXEU_InsertWord(CPWL_EditImpl* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - uint16_t word, - int32_t charset, - const CPVT_WordProps* pWordProps); - ~CFXEU_InsertWord() override; - - // CPWL_EditImpl_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_UnownedPtr 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 CPWL_EditImpl_UndoItem { - public: - CFXEU_InsertReturn(CPWL_EditImpl* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - const CPVT_SecProps* pSecProps, - const CPVT_WordProps* pWordProps); - ~CFXEU_InsertReturn() override; - - // CPWL_EditImpl_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_UnownedPtr m_pEdit; - - CPVT_WordPlace m_wpOld; - CPVT_WordPlace m_wpNew; - CPVT_SecProps m_SecProps; - CPVT_WordProps m_WordProps; -}; - -class CFXEU_Backspace : public CPWL_EditImpl_UndoItem { - public: - CFXEU_Backspace(CPWL_EditImpl* 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; - - // CPWL_EditImpl_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_UnownedPtr 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 CPWL_EditImpl_UndoItem { - public: - CFXEU_Delete(CPWL_EditImpl* 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; - - // CPWL_EditImpl_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_UnownedPtr 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 CPWL_EditImpl_UndoItem { - public: - CFXEU_Clear(CPWL_EditImpl* pEdit, - const CPVT_WordRange& wrSel, - const CFX_WideString& swText); - ~CFXEU_Clear() override; - - // CPWL_EditImpl_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_UnownedPtr m_pEdit; - - CPVT_WordRange m_wrSel; - CFX_WideString m_swText; -}; - -class CFXEU_InsertText : public CPWL_EditImpl_UndoItem { - public: - CFXEU_InsertText(CPWL_EditImpl* pEdit, - const CPVT_WordPlace& wpOldPlace, - const CPVT_WordPlace& wpNewPlace, - const CFX_WideString& swText, - int32_t charset); - ~CFXEU_InsertText() override; - - // CPWL_EditImpl_UndoItem - void Redo() override; - void Undo() override; - - private: - CFX_UnownedPtr m_pEdit; - - CPVT_WordPlace m_wpOld; - CPVT_WordPlace m_wpNew; - CFX_WideString m_swText; - int32_t m_nCharset; -}; - -class CPWL_EditImpl { - public: - static void DrawEdit(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device, - 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 SetOprNotify(CPWL_Edit* pOprNotify); - - // 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 CFX_WideString& sText); - bool InsertWord(uint16_t word, int32_t charset); - bool InsertReturn(); - bool Backspace(); - bool Delete(); - bool ClearSelection(); - bool InsertText(const CFX_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; - CFX_WideString GetSelectedText() const; - CFX_WideString GetText() const; - 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; - 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); - 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; - - CFX_ByteString GetPDFWordString(int32_t nFontIndex, - uint16_t Word, - uint16_t SubWord); - - private: - friend class CPWL_EditImpl_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 SetSelection(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); - - void RearrangeAll(); - void RearrangePart(const CPVT_WordRange& range); - void ScrollToCaret(); - void SetScrollInfo(); - void SetScrollPosX(float fx); - void SetScrollPosY(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 pEditUndoItem); - - private: - std::unique_ptr m_pVT; - CFX_UnownedPtr m_pNotify; - CFX_UnownedPtr m_pOprNotify; - std::unique_ptr 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 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; - bool m_bOprNotify; -}; - -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: - CFX_UnownedPtr 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_PDFWINDOW_CPWL_EDIT_IMPL_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_font_map.cpp b/fpdfsdk/pdfwindow/cpwl_font_map.cpp deleted file mode 100644 index f0c74ba0ce..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_font_map.cpp +++ /dev/null @@ -1,413 +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/cpwl_font_map.h" - -#include - -#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/pdfwindow/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(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; -} - -CFX_ByteString CPWL_FontMap::GetPDFFontAlias(int32_t nFontIndex) { - if (pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex]) - return m_Data[nFontIndex]->sFontName; - - return CFX_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; -} - -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(); - 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 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 == FX_CHARSET_Default || 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 = bFind ? FindFontSameCharset(&sAlias, nCharset) : nullptr; - 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(); - pNewData->pFont = pFont; - pNewData->sFontName = sFontAlias; - pNewData->nCharset = nCharset; - m_Data.push_back(std::move(pNewData)); - return pdfium::CollectionSize(m_Data) - 1; -} - -void CPWL_FontMap::AddedFont(CPDF_Font* pFont, - const CFX_ByteString& sFontAlias) {} - -CFX_ByteString CPWL_FontMap::GetNativeFont(int32_t nCharset) { - if (nCharset == FX_CHARSET_Default) - 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 == FX_CHARSET_Default) - 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 { - 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 _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - {FX_CHARSET_MSWin_EasternEuropean, "Arial"}, -#else - {FX_CHARSET_MSWin_EasternEuropean, "Tahoma"}, -#endif - {FX_CHARSET_MSWin_Arabic, "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 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/pdfwindow/cpwl_font_map.h b/fpdfsdk/pdfwindow/cpwl_font_map.h deleted file mode 100644 index e1a3edeb79..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_font_map.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_CPWL_FONT_MAP_H_ -#define FPDFSDK_PDFWINDOW_CPWL_FONT_MAP_H_ - -#include -#include - -#include "core/fpdfdoc/ipvt_fontmap.h" -#include "core/fxcrt/fx_codepage.h" -#include "core/fxge/fx_font.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 = FX_CHARSET_Default); - - CFX_ByteString EncodeFontAlias(const CFX_ByteString& sFontName, - int32_t nCharset); - CFX_ByteString EncodeFontAlias(const CFX_ByteString& sFontName); - - std::vector> m_Data; - std::vector> m_NativeFont; - - private: - int32_t FindFont(const CFX_ByteString& sFontName, - int32_t nCharset = FX_CHARSET_Default); - - 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 m_pPDFDoc; - CFX_UnownedPtr const m_pSystemHandler; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_FONT_MAP_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_icon.cpp b/fpdfsdk/pdfwindow/cpwl_icon.cpp deleted file mode 100644 index 4de3e7080d..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_icon.cpp +++ /dev/null @@ -1,131 +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/cpwl_icon.h" - -#include -#include - -#include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_stream.h" -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" - -CPWL_Icon::CPWL_Icon() : m_pPDFStream(nullptr), m_pIconFit(nullptr) {} - -CPWL_Icon::~CPWL_Icon() {} - -std::pair 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(); -} - -CFX_ByteString CPWL_Icon::GetImageAlias() { - if (!m_pPDFStream) - return CFX_ByteString(); - if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) - return pDict->GetStringFor("Name"); - return CFX_ByteString(); -} - -std::pair 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 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 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/pdfwindow/cpwl_icon.h b/fpdfsdk/pdfwindow/cpwl_icon.h deleted file mode 100644 index e97c540bf6..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_icon.h +++ /dev/null @@ -1,44 +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_CPWL_ICON_H_ -#define FPDFSDK_PDFWINDOW_CPWL_ICON_H_ - -#include - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxcrt/fx_string.h" -#include "fpdfsdk/pdfwindow/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 GetScale(); - - // x, y - std::pair GetImageOffset(); - - CFX_Matrix GetImageMatrix(); - CFX_ByteString GetImageAlias(); - - private: - // left, bottom - std::pair GetIconPosition(); - - // width, height - std::pair GetImageSize(); - - CFX_UnownedPtr m_pPDFStream; - CFX_UnownedPtr m_pIconFit; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_ICON_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_list_box.cpp b/fpdfsdk/pdfwindow/cpwl_list_box.cpp deleted file mode 100644 index 7e820bfbfa..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_list_box.cpp +++ /dev/null @@ -1,375 +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/cpwl_list_box.h" - -#include - -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/pdfwindow/cpwl_edit.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_ctrl.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_impl.h" -#include "fpdfsdk/pdfwindow/cpwl_list_impl.h" -#include "fpdfsdk/pdfwindow/cpwl_scroll_bar.h" -#include "fpdfsdk/pdfwindow/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); - - 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(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() {} - -CFX_ByteString CPWL_ListBox::GetClassName() const { - return "CPWL_ListBox"; -} - -void CPWL_ListBox::OnCreated() { - m_pList->SetFontMap(GetFontMap()); - m_pListNotify = pdfium::MakeUnique(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::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 (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, pUser2Device, m_pList->GetItemEdit(i), - GetTextColor().ToFXColor(255), rcList, ptOffset, - nullptr, pSysHandler, m_pFormFiller.Get()); - pSysHandler->OutputSelectedRect(m_pFormFiller.Get(), rcItem); - } else { - pDevice->DrawFillRect(pUser2Device, rcItem, - ArgbEncode(255, 0, 51, 113)); - CPWL_EditImpl::DrawEdit(pDevice, pUser2Device, 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, 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; - } - 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(); -} - -void CPWL_ListBox::RePosChildWnd() { - CPWL_Wnd::RePosChildWnd(); - - m_pList->SetPlateRect(GetListRect()); -} - -bool CPWL_ListBox::OnNotifySelectionChanged(bool bKeyDown, uint32_t nFlag) { - if (!m_pFillerNotify) - return false; - - CFX_WideString swChange = GetText(); - CFX_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); - 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 CFX_WideString& str) { - m_pList->AddString(str); -} - -CFX_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(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/pdfwindow/cpwl_list_box.h b/fpdfsdk/pdfwindow/cpwl_list_box.h deleted file mode 100644 index d76c7a5c5a..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_list_box.h +++ /dev/null @@ -1,110 +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_CPWL_LIST_BOX_H_ -#define FPDFSDK_PDFWINDOW_CPWL_LIST_BOX_H_ - -#include - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" - -class CPWL_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(float fPlateMin, - float fPlateMax, - float fContentMin, - float fContentMax, - float fSmallStep, - float fBigStep); - void IOnSetScrollPosY(float fy); - void IOnInvalidateRect(CFX_FloatRect* pRect); - - private: - CFX_UnownedPtr 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 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 SetScrollInfo(const PWL_SCROLL_INFO& info) override; - void SetScrollPosition(float pos) override; - void ScrollWindowVertically(float pos) override; - void RePosChildWnd() override; - CFX_FloatRect GetFocusRect() const override; - void SetFontSize(float fFontSize) override; - float GetFontSize() const override; - - virtual CFX_WideString GetText() const; - - bool OnNotifySelectionChanged(bool bKeyDown, 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, 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 m_pList; - std::unique_ptr m_pListNotify; - bool m_bMouseDown; - bool m_bHoverSel; - CFX_UnownedPtr m_pFillerNotify; - - private: - CFX_UnownedPtr m_pFormFiller; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_LIST_BOX_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_list_impl.cpp b/fpdfsdk/pdfwindow/cpwl_list_impl.cpp deleted file mode 100644 index 66b2e77747..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_list_impl.cpp +++ /dev/null @@ -1,637 +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/cpwl_list_impl.h" - -#include -#include - -#include "core/fpdfdoc/cpvt_word.h" -#include "core/fxcrt/fx_extension.h" -#include "fpdfsdk/pdfwindow/cpwl_edit_impl.h" -#include "fpdfsdk/pdfwindow/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 CFX_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; -} - -CFX_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 CFX_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(m_ListItems) - 1; - return -1; -} - -CFX_WideString CPWL_ListCtrl::GetText() const { - if (IsMultipleSel()) - return GetItemText(m_nCaretIndex); - return GetItemText(m_nSelItem); -} - -void CPWL_ListCtrl::AddItem(const CFX_WideString& str) { - auto pListItem = pdfium::MakeUnique(); - 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(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(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); -} - -CFX_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/pdfwindow/cpwl_list_impl.h b/fpdfsdk/pdfwindow/cpwl_list_impl.h deleted file mode 100644 index 167def057e..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_list_impl.h +++ /dev/null @@ -1,168 +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_CPWL_LIST_IMPL_H_ -#define FPDFSDK_PDFWINDOW_CPWL_LIST_IMPL_H_ - -#include -#include -#include - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxcrt/fx_coordinates.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::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 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 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) { 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 CFX_WideString& text); - void SetFontSize(float fFontSize); - CFX_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 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 CFX_WideString& str); - CFX_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; - CFX_UnownedPtr 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> m_ListItems; - float m_fFontSize; - CFX_UnownedPtr m_pFontMap; - bool m_bMultiple; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_LIST_IMPL_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_scroll_bar.cpp b/fpdfsdk/pdfwindow/cpwl_scroll_bar.cpp deleted file mode 100644 index c607ee795e..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_scroll_bar.cpp +++ /dev/null @@ -1,881 +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/cpwl_scroll_bar.h" - -#include -#include -#include - -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" - -namespace { - -constexpr float kButtonWidth = 9.0f; -constexpr float kPosButtonMinWidth = 2.0f; -constexpr float kTriangleHalfLength = 2.0f; - -} // namespace - -#define PWL_DEFAULT_HEAVYGRAYCOLOR CFX_Color(COLORTYPE_GRAY, 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() {} - -CFX_ByteString CPWL_SBButton::GetClassName() const { - return "CPWL_SBButton"; -} - -void CPWL_SBButton::OnCreate(PWL_CREATEPARAM& cp) { - cp.eCursorType = FXCT_ARROW; -} - -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(); - - if (m_eScrollBarType == SBT_HSCROLL) { - CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); - - CFX_PointF pt1; - CFX_PointF pt2; - CFX_PointF pt3; - if (m_eSBButtonType == PSBT_MIN) { - pt1 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f, ptCenter.y); - pt2 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f, - ptCenter.y + kTriangleHalfLength); - pt3 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f, - ptCenter.y - kTriangleHalfLength); - } else if (m_eSBButtonType == PSBT_MAX) { - pt1 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f, ptCenter.y); - pt2 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f, - ptCenter.y + kTriangleHalfLength); - pt3 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f, - ptCenter.y - kTriangleHalfLength); - } - - if (rectWnd.right - rectWnd.left > kTriangleHalfLength * 2 && - rectWnd.top - rectWnd.bottom > kTriangleHalfLength) { - 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); - } - return; - } - - // draw border - pDevice->DrawStrokeRect(pUser2Device, rectWnd, - ArgbEncode(nTransparency, 100, 100, 100), 0.0f); - pDevice->DrawStrokeRect(pUser2Device, rectWnd.GetDeflated(0.5f, 0.5f), - ArgbEncode(nTransparency, 255, 255, 255), 1.0f); - - if (m_eSBButtonType != PSBT_POS) { - // draw background - if (IsEnabled()) { - pDevice->DrawShadow(pUser2Device, true, false, - rectWnd.GetDeflated(1.0f, 1.0f), nTransparency, 80, - 220); - } else { - pDevice->DrawFillRect(pUser2Device, 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 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(pUser2Device, 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(pUser2Device, ptTop, ptBottom, ref, 1.0f); - - ptTop.x += 1.0f; - ptBottom.x += 1.0f; - } - } else { - pDevice->DrawFillRect(pUser2Device, 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(pUser2Device, 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() {} - -CFX_ByteString CPWL_ScrollBar::GetClassName() const { - return "CPWL_ScrollBar"; -} - -void CPWL_ScrollBar::OnCreate(PWL_CREATEPARAM& cp) { - cp.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(); -} - -void 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 { - SetVisible(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 { - 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::DrawThisAppearance(CFX_RenderDevice* pDevice, - CFX_Matrix* pUser2Device) { - CFX_FloatRect rectWnd = GetWindowRect(); - - if (IsVisible() && !rectWnd.IsEmpty()) { - pDevice->DrawFillRect(pUser2Device, rectWnd, GetBackgroundColor(), - GetTransparency()); - - pDevice->DrawStrokeLine( - 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); - - pDevice->DrawStrokeLine( - 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 + 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(); - 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::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 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); - } -} - -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) { - 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(float fPos) { - float fOldPos = m_sData.fScrollPos; - m_sData.SetPos(fPos); - if (!IsFloatEqual(m_sData.fScrollPos, fOldPos)) - MovePosButton(true); -} - -void CPWL_ScrollBar::SetScrollStep(float fBigStep, 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(); - - 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; - } - - 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) { - 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)) { - MovePosButton(true); - - 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 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/cpwl_scroll_bar.h b/fpdfsdk/pdfwindow/cpwl_scroll_bar.h deleted file mode 100644 index f9887e5610..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_scroll_bar.h +++ /dev/null @@ -1,184 +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_CPWL_SCROLL_BAR_H_ -#define FPDFSDK_PDFWINDOW_CPWL_SCROLL_BAR_H_ - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" - -class CPWL_SBButton; -class CPWL_ScrollBar; - -struct PWL_SCROLL_INFO { - public: - PWL_SCROLL_INFO() - : fContentMin(0.0f), - fContentMax(0.0f), - fPlateWidth(0.0f), - fBigStep(0.0f), - fSmallStep(0.0f) {} - - bool operator==(const PWL_SCROLL_INFO& that) const { - return fContentMin == that.fContentMin && fContentMax == that.fContentMax && - fPlateWidth == that.fPlateWidth && fBigStep == that.fBigStep && - fSmallStep == that.fSmallStep; - } - bool operator!=(const PWL_SCROLL_INFO& that) const { - return !(*this == that); - } - - float fContentMin; - float fContentMax; - float fPlateWidth; - float fBigStep; - float fSmallStep; -}; - -enum PWL_SCROLLBAR_TYPE { SBT_HSCROLL, SBT_VSCROLL }; - -enum PWL_SBBUTTON_TYPE { PSBT_MIN, PSBT_MAX, PSBT_POS }; - -class CPWL_SBButton : public CPWL_Wnd { - public: - CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType, - PWL_SBBUTTON_TYPE eButtonType); - ~CPWL_SBButton() override; - - // CPWL_Wnd - CFX_ByteString GetClassName() const override; - void OnCreate(PWL_CREATEPARAM& cp) 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; - bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override; - - protected: - PWL_SCROLLBAR_TYPE m_eScrollBarType; - PWL_SBBUTTON_TYPE m_eSBButtonType; - - bool m_bMouseDown; -}; - -struct PWL_FLOATRANGE { - public: - PWL_FLOATRANGE(); - PWL_FLOATRANGE(float min, float max); - - bool operator==(const PWL_FLOATRANGE& that) const { - return fMin == that.fMin && fMax == that.fMax; - } - bool operator!=(const PWL_FLOATRANGE& that) const { return !(*this == that); } - - void Default(); - void Set(float min, float max); - bool In(float x) const; - float GetWidth() const; - - float fMin; - float fMax; -}; - -struct PWL_SCROLL_PRIVATEDATA { - public: - PWL_SCROLL_PRIVATEDATA(); - - bool operator==(const PWL_SCROLL_PRIVATEDATA& that) const { - return ScrollRange == that.ScrollRange && - fClientWidth == that.fClientWidth && fScrollPos == that.fScrollPos && - fBigStep == that.fBigStep && fSmallStep == that.fSmallStep; - } - bool operator!=(const PWL_SCROLL_PRIVATEDATA& that) const { - return !(*this == that); - } - - void Default(); - 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(); - void AddBig(); - void SubBig(); - - PWL_FLOATRANGE ScrollRange; - float fClientWidth; - float fScrollPos; - float fBigStep; - float fSmallStep; -}; - -class CPWL_ScrollBar : public CPWL_Wnd { - public: - 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 OnDestroy() override; - void RePosChildWnd() 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; - 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 PWL_CREATEPARAM& cp) override; - void TimerProc() override; - - float GetScrollBarWidth() const; - PWL_SCROLLBAR_TYPE GetScrollBarType() const { return m_sbType; } - - void SetNotifyForever(bool bForever) { m_bNotifyForever = bForever; } - - protected: - void SetScrollRange(float fMin, float fMax, float fClientWidth); - void SetScrollPos(float fPos); - void MovePosButton(bool bRefresh); - void SetScrollStep(float fBigStep, float fSmallStep); - void NotifyScrollWindow(); - CFX_FloatRect GetScrollArea() const; - - private: - void CreateButtons(const PWL_CREATEPARAM& cp); - - void OnMinButtonLBDown(const CFX_PointF& point); - void OnMinButtonLBUp(const CFX_PointF& point); - void OnMinButtonMouseMove(const CFX_PointF& point); - - void OnMaxButtonLBDown(const CFX_PointF& point); - void OnMaxButtonLBUp(const CFX_PointF& point); - void OnMaxButtonMouseMove(const CFX_PointF& point); - - void OnPosButtonLBDown(const CFX_PointF& point); - void OnPosButtonLBUp(const CFX_PointF& point); - void OnPosButtonMouseMove(const CFX_PointF& point); - - float TrueToFace(float); - float FaceToTrue(float); - - PWL_SCROLLBAR_TYPE m_sbType; - PWL_SCROLL_INFO m_OriginInfo; - CFX_UnownedPtr m_pMinButton; - CFX_UnownedPtr m_pMaxButton; - CFX_UnownedPtr m_pPosButton; - PWL_SCROLL_PRIVATEDATA m_sData; - bool m_bMouseDown; - bool m_bMinOrMax; - bool m_bNotifyForever; - float m_nOldPos; - float m_fOldPosButton; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_SCROLL_BAR_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_special_button.cpp b/fpdfsdk/pdfwindow/cpwl_special_button.cpp deleted file mode 100644 index b911d5eb00..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_special_button.cpp +++ /dev/null @@ -1,80 +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/cpwl_special_button.h" -#include "fpdfsdk/pdfwindow/cpwl_button.h" -#include "fpdfsdk/pdfwindow/cpwl_wnd.h" - -CPWL_PushButton::CPWL_PushButton() {} - -CPWL_PushButton::~CPWL_PushButton() {} - -CFX_ByteString CPWL_PushButton::GetClassName() const { - return "CPWL_PushButton"; -} - -CFX_FloatRect CPWL_PushButton::GetFocusRect() const { - return GetWindowRect().GetDeflated(static_cast(GetBorderWidth()), - static_cast(GetBorderWidth())); -} - -CPWL_CheckBox::CPWL_CheckBox() : m_bChecked(false) {} - -CPWL_CheckBox::~CPWL_CheckBox() {} - -CFX_ByteString CPWL_CheckBox::GetClassName() const { - return "CPWL_CheckBox"; -} - -void CPWL_CheckBox::SetCheck(bool bCheck) { - m_bChecked = bCheck; -} - -bool CPWL_CheckBox::IsChecked() const { - return m_bChecked; -} - -bool CPWL_CheckBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - if (IsReadOnly()) - return false; - - SetCheck(!IsChecked()); - return true; -} - -bool CPWL_CheckBox::OnChar(uint16_t nChar, uint32_t nFlag) { - SetCheck(!IsChecked()); - return true; -} - -CPWL_RadioButton::CPWL_RadioButton() : m_bChecked(false) {} - -CPWL_RadioButton::~CPWL_RadioButton() {} - -CFX_ByteString CPWL_RadioButton::GetClassName() const { - return "CPWL_RadioButton"; -} - -bool CPWL_RadioButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { - if (IsReadOnly()) - return false; - - SetCheck(true); - return true; -} - -void CPWL_RadioButton::SetCheck(bool bCheck) { - m_bChecked = bCheck; -} - -bool CPWL_RadioButton::IsChecked() const { - return m_bChecked; -} - -bool CPWL_RadioButton::OnChar(uint16_t nChar, uint32_t nFlag) { - SetCheck(true); - return true; -} diff --git a/fpdfsdk/pdfwindow/cpwl_special_button.h b/fpdfsdk/pdfwindow/cpwl_special_button.h deleted file mode 100644 index ed80d31639..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_special_button.h +++ /dev/null @@ -1,56 +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_CPWL_SPECIAL_BUTTON_H_ -#define FPDFSDK_PDFWINDOW_CPWL_SPECIAL_BUTTON_H_ - -#include "fpdfsdk/pdfwindow/cpwl_button.h" - -class CPWL_PushButton : public CPWL_Button { - public: - CPWL_PushButton(); - ~CPWL_PushButton() override; - - // CPWL_Button - CFX_ByteString GetClassName() const override; - CFX_FloatRect GetFocusRect() const override; -}; - -class CPWL_CheckBox : public CPWL_Button { - public: - CPWL_CheckBox(); - ~CPWL_CheckBox() override; - - // CPWL_Button - CFX_ByteString GetClassName() const override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - bool OnChar(uint16_t nChar, uint32_t nFlag) override; - - void SetCheck(bool bCheck); - bool IsChecked() const; - - private: - bool m_bChecked; -}; - -class CPWL_RadioButton : public CPWL_Button { - public: - CPWL_RadioButton(); - ~CPWL_RadioButton() override; - - // CPWL_Button - CFX_ByteString GetClassName() const override; - bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; - bool OnChar(uint16_t nChar, uint32_t nFlag) override; - - void SetCheck(bool bCheck); - bool IsChecked() const; - - private: - bool m_bChecked; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_SPECIAL_BUTTON_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_timer.cpp b/fpdfsdk/pdfwindow/cpwl_timer.cpp deleted file mode 100644 index 03b183821f..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_timer.cpp +++ /dev/null @@ -1,62 +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_timer.h" - -#include - -#include "fpdfsdk/cfx_systemhandler.h" -#include "fpdfsdk/pdfwindow/cpwl_timer_handler.h" - -namespace { - -std::map& GetPWLTimeMap() { - // Leak the object at shutdown. - static auto* timeMap = new std::map; - 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/pdfwindow/cpwl_timer.h b/fpdfsdk/pdfwindow/cpwl_timer.h deleted file mode 100644 index 32a68fcbc2..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_timer.h +++ /dev/null @@ -1,32 +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_TIMER_H_ -#define FPDFSDK_PDFWINDOW_CPWL_TIMER_H_ - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxcrt/fx_basic.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; - CFX_UnownedPtr m_pAttached; - CFX_UnownedPtr m_pSystemHandler; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_TIMER_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_timer_handler.cpp b/fpdfsdk/pdfwindow/cpwl_timer_handler.cpp deleted file mode 100644 index 3edaa8d462..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_timer_handler.cpp +++ /dev/null @@ -1,27 +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_timer_handler.h" - -#include "fpdfsdk/pdfwindow/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(this, GetSystemHandler()); - m_pTimer->SetPWLTimer(nElapse); -} - -void CPWL_TimerHandler::EndTimer() { - if (m_pTimer) - m_pTimer->KillPWLTimer(); -} - -void CPWL_TimerHandler::TimerProc() {} diff --git a/fpdfsdk/pdfwindow/cpwl_timer_handler.h b/fpdfsdk/pdfwindow/cpwl_timer_handler.h deleted file mode 100644 index f6ffd44996..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_timer_handler.h +++ /dev/null @@ -1,32 +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_TIMER_HANDLER_H_ -#define FPDFSDK_PDFWINDOW_CPWL_TIMER_HANDLER_H_ - -#include - -#include "core/fxcrt/fx_basic.h" - -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 m_pTimer; -}; - -#endif // FPDFSDK_PDFWINDOW_CPWL_TIMER_HANDLER_H_ diff --git a/fpdfsdk/pdfwindow/cpwl_wnd.cpp b/fpdfsdk/pdfwindow/cpwl_wnd.cpp deleted file mode 100644 index 58824afdbd..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_wnd.cpp +++ /dev/null @@ -1,806 +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/cpwl_wnd.h" - -#include -#include -#include - -#include "core/fxge/cfx_renderdevice.h" -#include "fpdfsdk/pdfwindow/cpwl_scroll_bar.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -namespace { - -constexpr float kDefaultFontSize = 9.0f; -constexpr int kInvalidationInflate = 2; - -} // namespace - -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(kDefaultFontSize), - sDash(3, 0, 0), - pAttachedData(nullptr), - pParentWnd(nullptr), - pMsgControl(nullptr), - eCursorType(FXCT_ARROW) {} - -PWL_CREATEPARAM::PWL_CREATEPARAM(const PWL_CREATEPARAM& other) = default; - -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 m_aMousePath; - std::vector m_aKeyboardPath; - CFX_UnownedPtr m_pCreatedWnd; - CFX_UnownedPtr m_pMainMouseWnd; - CFX_UnownedPtr 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); -} - -CFX_ByteString CPWL_Wnd::GetClassName() const { - return "CPWL_Wnd"; -} - -void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) { - if (IsValid()) - return; - - m_sPrivateParam = cp; - OnCreate(m_sPrivateParam); - - m_sPrivateParam.rcRectWnd.Normalize(); - m_rcWindow = m_sPrivateParam.rcRectWnd; - m_rcClip = m_rcWindow; - if (!m_rcClip.IsEmpty()) { - m_rcClip.Inflate(1.0f, 1.0f); - m_rcClip.Normalize(); - } - CreateMsgControl(); - - if (m_sPrivateParam.pParentWnd) - m_sPrivateParam.pParentWnd->AddChild(this); - - PWL_CREATEPARAM ccp = m_sPrivateParam; - - ccp.dwFlags &= 0xFFFF0000L; // remove sub styles - 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) { - m_pVScrollBar = nullptr; - 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->RemoveChild(this); - - m_bCreated = false; - } - DestroyMsgControl(); - m_sPrivateParam.Reset(); - m_Children.clear(); -} - -void CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) { - if (!IsValid()) - return; - - 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) { - 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::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()) - return; - - if (HasFlag(PWS_BACKGROUND)) { - float width = static_cast(GetBorderWidth() + GetInnerBorderWidth()); - pDevice->DrawFillRect(pUser2Device, rectWnd.GetDeflated(width, width), - GetBackgroundColor(), GetTransparency()); - } - - if (HasFlag(PWS_BORDER)) { - pDevice->DrawBorder(pUser2Device, rectWnd, - static_cast(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()) - return; - - 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 -= kInvalidationInflate; - rcWin.top -= kInvalidationInflate; - rcWin.right += kInvalidationInflate; - rcWin.bottom += kInvalidationInflate; - - if (CFX_SystemHandler* pSH = GetSystemHandler()) { - if (CPDFSDK_Widget* widget = static_cast( - 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 (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 - -CFX_WideString CPWL_Wnd::GetSelectedText() { - return CFX_WideString(); -} - -void CPWL_Wnd::DeleteSelectedText() {} - -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) {} - -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(); - - float width = static_cast(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_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; -} - -CFX_Color CPWL_Wnd::GetBackgroundColor() const { - return m_sPrivateParam.sBackgroundColor; -} - -void CPWL_Wnd::SetBackgroundColor(const CFX_Color& color) { - m_sPrivateParam.sBackgroundColor = color; -} - -CFX_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 { - return HasFlag(PWS_BORDER) ? m_sPrivateParam.dwBorderWidth : 0; -} - -int32_t CPWL_Wnd::GetInnerBorderWidth() const { - return 0; -} - -CFX_Color CPWL_Wnd::GetBorderColor() const { - return HasFlag(PWS_BORDER) ? m_sPrivateParam.sBorderColor : CFX_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 { - return HasFlag(PWS_VSCROLL) ? m_pVScrollBar.Get() : 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)) - return; - - 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 (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_sPrivateParam.pParentWnd; - return pParent ? pParent->GetRootWnd() : this; -} - -void CPWL_Wnd::SetVisible(bool bVisible) { - if (!IsValid()) - return; - - for (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() { - CPWL_ScrollBar* pVSB = GetVScrollBar(); - if (!pVSB) - return; - - CFX_FloatRect rcContent = GetWindowRect(); - if (!rcContent.IsEmpty()) { - float width = static_cast(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); - 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() { - CPWL_MsgControl* pMsgControl = GetMsgControl(); - if (pMsgControl && 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 { - 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_sPrivateParam.fFontSize; -} - -void CPWL_Wnd::SetFontSize(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; -} - -CFX_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const { - switch (nBorderStyle) { - case BorderStyle::BEVELED: - return CFX_Color(COLORTYPE_GRAY, 1); - case BorderStyle::INSET: - return CFX_Color(COLORTYPE_GRAY, 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(COLORTYPE_GRAY, 0.75f); - default: - return CFX_Color(); - } -} - -int32_t CPWL_Wnd::GetTransparency() { - return m_sPrivateParam.nTransparency; -} - -void CPWL_Wnd::SetTransparency(int32_t nTransparency) { - for (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; - - 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; - CFX_FloatRect rc = rect; - mt.TransformRect(rc); - return rc; -} - -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_sPrivateParam.mtChild : CFX_Matrix(); -} - -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.Get() : 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/pdfwindow/cpwl_wnd.h b/fpdfsdk/pdfwindow/cpwl_wnd.h deleted file mode 100644 index d56369cb52..0000000000 --- a/fpdfsdk/pdfwindow/cpwl_wnd.h +++ /dev/null @@ -1,344 +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_CPWL_WND_H_ -#define FPDFSDK_PDFWINDOW_CPWL_WND_H_ - -#include -#include - -#include "core/fpdfdoc/cpdf_formcontrol.h" -#include "core/fxcrt/cfx_observable.h" -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxcrt/fx_basic.h" -#include "core/fxge/cfx_color.h" -#include "fpdfsdk/cpdfsdk_formfillenvironment.h" -#include "fpdfsdk/cpdfsdk_widget.h" -#include "fpdfsdk/pdfwindow/cpwl_timer.h" -#include "fpdfsdk/pdfwindow/cpwl_timer_handler.h" - -class CPWL_Edit; -class CPWL_MsgControl; -class CPWL_ScrollBar; -class CPWL_Wnd; -class CFX_SystemHandler; -class IPVT_FontMap; -class IPWL_Provider; -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 - -#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 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_SELBACKCOLOR \ - CFX_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f, 113.0f / 255.0f) -#define PWL_DEFAULT_BLACKCOLOR CFX_Color(COLORTYPE_GRAY, 0) -#define PWL_DEFAULT_WHITECOLOR CFX_Color(COLORTYPE_GRAY, 1) - -class IPWL_Provider : public CFX_Observable { - public: - virtual ~IPWL_Provider() {} - - // get a matrix which map user space to CWnd client space - virtual CFX_Matrix GetWindowMatrix(void* pAttachedData) = 0; -}; - -class IPWL_FocusHandler { - public: - virtual ~IPWL_FocusHandler() {} - virtual void OnSetFocus(CPWL_Edit* pEdit) = 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 - 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 - void* pAttachedData; // optional - CPWL_Wnd* pParentWnd; // ignore - CPWL_MsgControl* pMsgControl; // ignore - int32_t eCursorType; // ignore - CFX_Matrix mtChild; // ignore -}; - -class CPWL_Wnd : public CPWL_TimerHandler, public CFX_Observable { - 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 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(); - virtual void SetVisible(bool bVisible); - virtual void SetFontSize(float fFontSize); - virtual float GetFontSize() const; - - virtual CFX_WideString GetSelectedText(); - virtual void DeleteSelectedText(); - 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); - - 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; - 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 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 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; - - 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, 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 m_Children; - PWL_CREATEPARAM m_sPrivateParam; - CFX_UnownedPtr 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_CPWL_WND_H_ diff --git a/fpdfsdk/pwl/cpwl_appstream.cpp b/fpdfsdk/pwl/cpwl_appstream.cpp new file mode 100644 index 0000000000..fe401639da --- /dev/null +++ b/fpdfsdk/pwl/cpwl_appstream.cpp @@ -0,0 +1,1992 @@ +// 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 + +#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, + CFX_ByteString open, + CFX_ByteString close) + : stream_(stream), close_(close) { + *stream_ << open << "\n"; + } + + virtual ~AutoClosedCommand() { *stream_ << close_ << "\n"; } + + private: + std::ostringstream* stream_; + CFX_ByteString close_; +}; + +class AutoClosedQCommand : public AutoClosedCommand { + public: + explicit AutoClosedQCommand(std::ostringstream* stream) + : AutoClosedCommand(stream, kStateSaveOperator, kStateRestoreOperator) {} + ~AutoClosedQCommand() override {} +}; + +CFX_ByteString GetColorAppStream(const CFX_Color& color, + const bool& bFillOrStroke) { + std::ostringstream sColorStream; + + switch (color.nColorType) { + case COLORTYPE_RGB: + sColorStream << color.fColor1 << " " << color.fColor2 << " " + << color.fColor3 << " " + << (bFillOrStroke ? kSetRGBOperator : kSetRGBStrokedOperator) + << "\n"; + break; + case COLORTYPE_GRAY: + sColorStream << color.fColor1 << " " + << (bFillOrStroke ? kSetGrayOperator + : kSetGrayStrokedOperator) + << "\n"; + break; + case COLORTYPE_CMYK: + sColorStream << color.fColor1 << " " << color.fColor2 << " " + << color.fColor3 << " " << color.fColor4 << " " + << (bFillOrStroke ? kSetCMYKOperator + : kSetCMKYStrokedOperator) + << "\n"; + break; + } + + return CFX_ByteString(sColorStream); +} + +CFX_ByteString GetAP_Check(const CFX_FloatRect& crBBox) { + const float fWidth = crBBox.right - crBBox.left; + const float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f), + CFX_PointF(0.29f, 0.40f)}, + {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f), + CFX_PointF(0.31f, 0.28f)}, + {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f), + CFX_PointF(0.77f, 0.67f)}, + {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f), + CFX_PointF(0.76f, 0.75f)}, + {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f), + CFX_PointF(0.68f, 0.75f)}, + {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f), + CFX_PointF(0.44f, 0.47f)}, + {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f), + CFX_PointF(0.41f, 0.58f)}, + {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f), + CFX_PointF(0.30f, 0.56f)}}; + + for (size_t i = 0; i < FX_ArraySize(pts); ++i) { + for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) { + pts[i][j].x = pts[i][j].x * fWidth + crBBox.left; + pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom; + } + } + + std::ostringstream csAP; + csAP << pts[0][0].x << " " << pts[0][0].y << " " << 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 CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_Circle(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); + CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); + CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); + CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); + + csAP << pt1.x << " " << pt1.y << " " << 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 CFX_ByteString(csAP); +} + +CFX_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 CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_Diamond(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); + CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); + CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); + CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); + + csAP << pt1.x << " " << pt1.y << " " << 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 CFX_ByteString(csAP); +} + +CFX_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 CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_Star(const CFX_FloatRect& crBBox) { + std::ostringstream csAP; + + float fRadius = (crBBox.top - crBBox.bottom) / (1 + (float)cos(FX_PI / 5.0f)); + CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f, + (crBBox.top + crBBox.bottom) / 2.0f); + + float px[5]; + float py[5]; + float fAngel = FX_PI / 10.0f; + for (int32_t i = 0; i < 5; i++) { + px[i] = ptCenter.x + fRadius * (float)cos(fAngel); + py[i] = ptCenter.y + fRadius * (float)sin(fAngel); + fAngel += FX_PI * 2 / 5.0f; + } + + csAP << px[0] << " " << py[0] << " " << 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 CFX_ByteString(csAP); +} + +CFX_ByteString GetAP_HalfCircle(const CFX_FloatRect& crBBox, float fRotate) { + std::ostringstream csAP; + + float fWidth = crBBox.right - crBBox.left; + float fHeight = crBBox.top - crBBox.bottom; + + CFX_PointF pt1(-fWidth / 2, 0); + CFX_PointF pt2(0, fHeight / 2); + CFX_PointF pt3(fWidth / 2, 0); + + float px; + float py; + + csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " " + << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " " + << crBBox.bottom + fHeight / 2 << " " << 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 CFX_ByteString(csAP); +} + +CFX_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 CFX_ByteString(sAP); +} + +CFX_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 CFX_ByteString(sAP); +} + +CFX_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 CFX_ByteString(sAP); +} + +CFX_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 CFX_ByteString(sAP); +} + +CFX_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 CFX_ByteString(sAP); +} + +CFX_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 CFX_ByteString(sAP); +} + +CFX_ByteString GetCircleFillAppStream(const CFX_FloatRect& rect, + const CFX_Color& color) { + std::ostringstream sAppStream; + CFX_ByteString sColor = GetColorAppStream(color, true); + if (sColor.GetLength() > 0) { + AutoClosedQCommand q(&sAppStream); + sAppStream << sColor << GetAP_Circle(rect) << kFillOperator << "\n"; + } + return CFX_ByteString(sAppStream); +} + +CFX_ByteString GetCircleBorderAppStream(const CFX_FloatRect& rect, + float fWidth, + const CFX_Color& color, + const CFX_Color& crLeftTop, + const CFX_Color& crRightBottom, + BorderStyle nStyle, + const CPWL_Dash& dash) { + std::ostringstream sAppStream; + CFX_ByteString sColor; + + if (fWidth > 0.0f) { + 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 CFX_ByteString(sAppStream); +} + +CFX_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.Scale(2.0f / 3.0f); + return GetAppStream_Circle(rcCenter, crText); + case CheckStyle::kCross: + return GetAppStream_Cross(rcCenter, crText); + case CheckStyle::kDiamond: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Diamond(rcCenter, crText); + case CheckStyle::kSquare: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Square(rcCenter, crText); + case CheckStyle::kStar: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Star(rcCenter, crText); + } +} + +CFX_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.Scale(1.0f / 2.0f); + return GetAppStream_Circle(rcCenter, crText); + case CheckStyle::kCross: + return GetAppStream_Cross(rcCenter, crText); + case CheckStyle::kDiamond: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Diamond(rcCenter, crText); + case CheckStyle::kSquare: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Square(rcCenter, crText); + case CheckStyle::kStar: + rcCenter.Scale(2.0f / 3.0f); + return GetAppStream_Star(rcCenter, crText); + } +} + +CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap, + int32_t nFontIndex, + float fFontSize) { + if (!pFontMap) + return CFX_ByteString(); + + CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); + if (sFontAlias.GetLength() <= 0 || fFontSize <= 0) + return CFX_ByteString(); + + std::ostringstream sRet; + sRet << "/" << sFontAlias << " " << fFontSize << " " + << kSetTextFontAndSizeOperator << "\n"; + return CFX_ByteString(sRet); +} + +CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) { + if (strWords.GetLength() > 0) { + return PDF_EncodeString(strWords, false) + " " + kShowTextOperator + "\n"; + } + return CFX_ByteString(); +} + +CFX_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(CFX_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(CFX_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(CFX_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 CFX_ByteString(sAppStream); +} + +CFX_ByteString GenerateIconAppStream(CPDF_IconFit& fit, + CPDF_Stream* pIconStream, + const CFX_FloatRect& rcIcon) { + if (rcIcon.IsEmpty() || !pIconStream) + return CFX_ByteString(); + + CPWL_Icon icon; + PWL_CREATEPARAM cp; + cp.dwFlags = PWS_VISIBLE; + icon.Create(cp); + icon.SetIconFit(&fit); + icon.SetPDFStream(pIconStream); + icon.Move(rcIcon, false, false); + + CFX_ByteString sAlias = icon.GetImageAlias(); + if (sAlias.GetLength() <= 0) + return CFX_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 CFX_ByteString(str); +} + +CFX_ByteString GetPushButtonAppStream(const CFX_FloatRect& rcBBox, + IPVT_FontMap* pFontMap, + CPDF_Stream* pIconStream, + CPDF_IconFit& IconFit, + const CFX_WideString& sLabel, + const CFX_Color& crText, + float fFontSize, + ButtonStyle nLayOut) { + const float fAutoFontScale = 1.0f / 3.0f; + + auto pEdit = pdfium::MakeUnique(); + pEdit->SetFontMap(pFontMap); + pEdit->SetAlignmentH(1, true); + pEdit->SetAlignmentV(1, true); + pEdit->SetMultiLine(false, true); + pEdit->SetAutoReturn(false, true); + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + pEdit->SetText(sLabel); + + CFX_FloatRect rcLabelContent = pEdit->GetContentRect(); + 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); + CFX_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 CFX_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 CFX_ByteString(sAppStream); +} + +CFX_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; + CFX_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 CFX_ByteString(sAppStream); +} + +CFX_ByteString GetDropButtonAppStream(const CFX_FloatRect& rcBBox) { + if (rcBBox.IsEmpty()) + return CFX_ByteString(); + + std::ostringstream sAppStream; + { + AutoClosedQCommand q(&sAppStream); + sAppStream << GetColorAppStream(CFX_Color(COLORTYPE_RGB, 220.0f / 255.0f, + 220.0f / 255.0f, 220.0f / 255.0f), + true) + << rcBBox.left << " " << rcBBox.bottom << " " + << rcBBox.right - rcBBox.left << " " + << rcBBox.top - rcBBox.bottom << " " << kAppendRectOperator + << " " << kFillOperator << "\n"; + } + + { + AutoClosedQCommand q(&sAppStream); + sAppStream << GetBorderAppStreamInternal( + rcBBox, 2, CFX_Color(COLORTYPE_GRAY, 0), CFX_Color(COLORTYPE_GRAY, 1), + CFX_Color(COLORTYPE_GRAY, 0.5), BorderStyle::BEVELED, + CPWL_Dash(3, 0, 0)); + } + + 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 CFX_ByteString(sAppStream); +} + +CFX_ByteString GetRectFillAppStream(const CFX_FloatRect& rect, + const CFX_Color& color) { + std::ostringstream sAppStream; + CFX_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 CFX_ByteString(sAppStream); +} + +} // namespace + +CPWL_AppStream::CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict) + : widget_(widget), dict_(dict) {} + +CPWL_AppStream::~CPWL_AppStream() {} + +void CPWL_AppStream::SetAsPushButton() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + 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(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CFX_Color crText(COLORTYPE_GRAY, 0); + CFX_ByteString csNameTag; + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + float fFontSize = 12.0f; + if (da.HasFont()) + csNameTag = da.GetFont(&fFontSize); + + CFX_WideString csWCaption; + CFX_WideString csNormalCaption; + CFX_WideString csRolloverCaption; + CFX_WideString csDownCaption; + if (pControl->HasMKEntry("CA")) + csNormalCaption = pControl->GetNormalCaption(); + + if (pControl->HasMKEntry("RC")) + csRolloverCaption = pControl->GetRolloverCaption(); + + if (pControl->HasMKEntry("AC")) + csDownCaption = pControl->GetDownCaption(); + + CPDF_Stream* pNormalIcon = nullptr; + CPDF_Stream* pRolloverIcon = nullptr; + CPDF_Stream* pDownIcon = nullptr; + if (pControl->HasMKEntry("I")) + pNormalIcon = pControl->GetNormalIcon(); + + if (pControl->HasMKEntry("RI")) + pRolloverIcon = pControl->GetRolloverIcon(); + + if (pControl->HasMKEntry("IX")) + pDownIcon = pControl->GetDownIcon(); + + if (pNormalIcon) { + if (CPDF_Dictionary* pImageDict = pNormalIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgA", false); + } + } + + if (pRolloverIcon) { + if (CPDF_Dictionary* pImageDict = pRolloverIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgB", false); + } + } + + if (pDownIcon) { + if (CPDF_Dictionary* pImageDict = pDownIcon->GetDict()) { + if (pImageDict->GetStringFor("Name").IsEmpty()) + pImageDict->SetNewFor("Name", "ImgC", false); + } + } + + CPDF_IconFit iconFit = pControl->GetIconFit(); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + font_map.SetAPType("N"); + + CFX_ByteString csAP = + 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(COLORTYPE_GRAY, 0); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 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(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop, crRightBottom; + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + + CheckStyle nStyle = CheckStyle::kCheck; + CFX_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; + } + } + + CFX_ByteString csAP_N_ON = + GetRectFillAppStream(rcWindow, crBackground) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + + CFX_ByteString csAP_N_OFF = csAP_N_ON; + + switch (nBorderStyle) { + case BorderStyle::BEVELED: { + CFX_Color crTemp = crLeftTop; + crLeftTop = crRightBottom; + crRightBottom = crTemp; + break; + } + case BorderStyle::INSET: { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + break; + } + default: + break; + } + + CFX_ByteString csAP_D_ON = + GetRectFillAppStream(rcWindow, crBackground - 0.25f) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + + CFX_ByteString csAP_D_OFF = csAP_D_ON; + + csAP_N_ON += GetCheckBoxAppStream(rcClient, nStyle, crText); + csAP_D_ON += GetCheckBoxAppStream(rcClient, nStyle, crText); + + Write("N", csAP_N_ON, pControl->GetCheckedAPState()); + Write("N", csAP_N_OFF, "Off"); + + Write("D", csAP_D_ON, pControl->GetCheckedAPState()); + Write("D", csAP_D_OFF, "Off"); + + CFX_ByteString csAS = widget_->GetAppState(); + if (csAS.IsEmpty()) + widget_->SetAppState("Off"); +} + +void CPWL_AppStream::SetAsRadioButton() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CFX_Color crBackground; + CFX_Color crBorder; + CFX_Color crText; + int iColorType; + float fc[4]; + + pControl->GetOriginalBackgroundColor(iColorType, fc); + if (iColorType > 0) + crBackground = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + pControl->GetOriginalBorderColor(iColorType, fc); + if (iColorType > 0) + crBorder = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); + break; + default: + break; + } + + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_FloatRect rcClient = rcWindow.GetDeflated(fBorderWidth, fBorderWidth); + CPDF_DefaultAppearance da = pControl->GetDefaultAppearance(); + if (da.HasColor()) { + da.GetColor(iColorType, fc); + crText = CFX_Color(iColorType, fc[0], fc[1], fc[2], fc[3]); + } + + CheckStyle nStyle = CheckStyle::kCircle; + CFX_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; + } + } + + CFX_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(COLORTYPE_GRAY, 1); + crRightBottom = crBackground - 0.25f; + } else if (nBorderStyle == BorderStyle::INSET) { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5f); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75f); + } + + csAP_N_ON = + GetCircleFillAppStream(rcCenter, crBackground) + + GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } else { + csAP_N_ON = + GetRectFillAppStream(rcWindow, crBackground) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } + + CFX_ByteString csAP_N_OFF = csAP_N_ON; + + switch (nBorderStyle) { + case BorderStyle::BEVELED: { + CFX_Color crTemp = crLeftTop; + crLeftTop = crRightBottom; + crRightBottom = crTemp; + break; + } + case BorderStyle::INSET: { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + break; + } + default: + break; + } + + CFX_ByteString csAP_D_ON; + + if (nStyle == CheckStyle::kCircle) { + CFX_Color crBK = crBackground - 0.25f; + if (nBorderStyle == BorderStyle::BEVELED) { + crLeftTop = crBackground - 0.25f; + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + crBK = crBackground; + } else if (nBorderStyle == BorderStyle::INSET) { + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 1); + } + + csAP_D_ON = + GetCircleFillAppStream(rcCenter, crBK) + + GetCircleBorderAppStream(rcCenter, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } else { + csAP_D_ON = + GetRectFillAppStream(rcWindow, crBackground - 0.25f) + + GetBorderAppStreamInternal(rcWindow, fBorderWidth, crBorder, crLeftTop, + crRightBottom, nBorderStyle, dsBorder); + } + + CFX_ByteString csAP_D_OFF = csAP_D_ON; + + csAP_N_ON += GetRadioButtonAppStream(rcClient, nStyle, crText); + csAP_D_ON += GetRadioButtonAppStream(rcClient, nStyle, crText); + + Write("N", csAP_N_ON, pControl->GetCheckedAPState()); + Write("N", csAP_N_OFF, "Off"); + + Write("D", csAP_D_ON, pControl->GetCheckedAPState()); + Write("D", csAP_D_OFF, "Off"); + + CFX_ByteString csAS = widget_->GetAppState(); + if (csAS.IsEmpty()) + widget_->SetAppState("Off"); +} + +void CPWL_AppStream::SetAsComboBox(const CFX_WideString* sValue) { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + std::ostringstream sBody; + + CFX_FloatRect rcClient = widget_->GetClientRect(); + CFX_FloatRect rcButton = rcClient; + rcButton.left = rcButton.right - 13; + rcButton.Normalize(); + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + + CFX_FloatRect rcEdit = rcClient; + rcEdit.right = rcButton.left; + rcEdit.Normalize(); + + pEdit->SetPlateRect(rcEdit); + pEdit->SetAlignmentV(1, true); + + float fFontSize = widget_->GetFontSize(); + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + + if (sValue) { + pEdit->SetText(*sValue); + } else { + int32_t nCurSel = pField->GetSelectedIndex(0); + if (nCurSel < 0) + pEdit->SetText(pField->GetValue()); + else + pEdit->SetText(pField->GetOptionLabel(nCurSel)); + } + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + CFX_ByteString sEdit = 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() + CFX_ByteString(sBody), + ""); +} + +void CPWL_AppStream::SetAsListBox() { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + CFX_FloatRect rcClient = widget_->GetClientRect(); + std::ostringstream sBody; + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + pEdit->SetPlateRect(CFX_FloatRect(rcClient.left, 0.0f, rcClient.right, 0.0f)); + + float fFontSize = widget_->GetFontSize(); + pEdit->SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); + pEdit->Initialize(); + + std::ostringstream sList; + float fy = rcClient.top; + + int32_t nTop = pField->GetTopVisibleIndex(); + int32_t nCount = pField->CountOptions(); + int32_t nSelCount = pField->CountSelectedItems(); + + for (int32_t i = nTop; i < nCount; ++i) { + bool bSelected = false; + for (int32_t j = 0; j < nSelCount; ++j) { + if (pField->GetSelectedIndex(j) == i) { + bSelected = true; + break; + } + } + + pEdit->SetText(pField->GetOptionLabel(i)); + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + float fItemHeight = rcContent.Height(); + + if (bSelected) { + CFX_FloatRect rcItem = + CFX_FloatRect(rcClient.left, fy - fItemHeight, rcClient.right, fy); + { + AutoClosedQCommand q(&sList); + sList << GetColorAppStream(CFX_Color(COLORTYPE_RGB, 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(COLORTYPE_GRAY, 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() + CFX_ByteString(sBody), + ""); +} + +void CPWL_AppStream::SetAsTextField(const CFX_WideString* sValue) { + CPDF_FormControl* pControl = widget_->GetFormControl(); + CPDF_FormField* pField = pControl->GetField(); + std::ostringstream sBody; + std::ostringstream sLines; + + auto pEdit = pdfium::MakeUnique(); + pEdit->EnableRefresh(false); + + CBA_FontMap font_map( + widget_.Get(), + widget_->GetInterForm()->GetFormFillEnv()->GetSysHandler()); + pEdit->SetFontMap(&font_map); + + CFX_FloatRect rcClient = widget_->GetClientRect(); + pEdit->SetPlateRect(rcClient); + pEdit->SetAlignmentH(pControl->GetControlAlignment(), true); + + uint32_t dwFieldFlags = pField->GetFieldFlags(); + bool bMultiLine = (dwFieldFlags >> 12) & 1; + if (bMultiLine) { + pEdit->SetMultiLine(true, true); + pEdit->SetAutoReturn(true, true); + } else { + pEdit->SetAlignmentV(1, true); + } + + uint16_t subWord = 0; + if ((dwFieldFlags >> 13) & 1) { + subWord = '*'; + pEdit->SetPasswordChar(subWord, true); + } + + int nMaxLen = pField->GetMaxLen(); + bool bCharArray = (dwFieldFlags >> 24) & 1; + float fFontSize = widget_->GetFontSize(); + +#ifdef PDF_ENABLE_XFA + CFX_WideString sValueTmp; + if (!sValue && widget_->GetMixXFAWidget()) { + sValueTmp = widget_->GetValue(true); + sValue = &sValueTmp; + } +#endif // PDF_ENABLE_XFA + + if (nMaxLen > 0) { + if (bCharArray) { + pEdit->SetCharArray(nMaxLen); + + if (IsFloatZero(fFontSize)) { + fFontSize = CPWL_Edit::GetCharArrayAutoFontSize(font_map.GetPDFFont(0), + rcClient, nMaxLen); + } + } else { + if (sValue) + nMaxLen = sValue->GetLength(); + pEdit->SetLimitChar(nMaxLen); + } + } + + if (IsFloatZero(fFontSize)) + pEdit->SetAutoFontSize(true, true); + else + pEdit->SetFontSize(fFontSize); + + pEdit->Initialize(); + pEdit->SetText(sValue ? *sValue : pField->GetValue()); + + CFX_FloatRect rcContent = pEdit->GetContentRect(); + CFX_ByteString sEdit = + 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: { + CFX_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: { + CFX_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() + + CFX_ByteString(sLines) + CFX_ByteString(sBody), + ""); +} + +void CPWL_AppStream::AddImage(const CFX_ByteString& sAPType, + CPDF_Stream* pImage) { + CPDF_Stream* pStream = dict_->GetStreamFor(sAPType); + CPDF_Dictionary* pStreamDict = pStream->GetDict(); + CFX_ByteString sImageAlias = "IMG"; + + if (CPDF_Dictionary* pImageDict = pImage->GetDict()) { + sImageAlias = pImageDict->GetStringFor("Name"); + if (sImageAlias.IsEmpty()) + sImageAlias = "IMG"; + } + + CPDF_Dictionary* pStreamResList = pStreamDict->GetDictFor("Resources"); + if (!pStreamResList) + pStreamResList = pStreamDict->SetNewFor("Resources"); + + CPDF_Dictionary* pXObject = + pStreamResList->SetNewFor("XObject"); + pXObject->SetNewFor(sImageAlias, + widget_->GetPageView()->GetPDFDocument(), + pImage->GetObjNum()); +} + +void CPWL_AppStream::Write(const CFX_ByteString& sAPType, + const CFX_ByteString& sContents, + const CFX_ByteString& sAPState) { + CPDF_Stream* pStream = nullptr; + CPDF_Dictionary* pParentDict = nullptr; + if (sAPState.IsEmpty()) { + pParentDict = dict_.Get(); + pStream = dict_->GetStreamFor(sAPType); + } else { + CPDF_Dictionary* pAPTypeDict = dict_->GetDictFor(sAPType); + if (!pAPTypeDict) + pAPTypeDict = dict_->SetNewFor(sAPType); + + pParentDict = pAPTypeDict; + pStream = pAPTypeDict->GetStreamFor(sAPState); + } + + if (!pStream) { + CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument(); + pStream = doc->NewIndirect(); + pParentDict->SetNewFor(sAPType, doc, pStream->GetObjNum()); + } + + CPDF_Dictionary* pStreamDict = pStream->GetDict(); + if (!pStreamDict) { + auto pNewDict = pdfium::MakeUnique( + widget_->GetPDFAnnot()->GetDocument()->GetByteStringPool()); + pStreamDict = pNewDict.get(); + pStreamDict->SetNewFor("Type", "XObject"); + pStreamDict->SetNewFor("Subtype", "Form"); + pStreamDict->SetNewFor("FormType", 1); + pStream->InitStream(nullptr, 0, std::move(pNewDict)); + } + pStreamDict->SetMatrixFor("Matrix", widget_->GetMatrix()); + pStreamDict->SetRectFor("BBox", widget_->GetRotatedRect()); + pStream->SetData((uint8_t*)(sContents.c_str()), sContents.GetLength()); +} + +void CPWL_AppStream::Remove(const CFX_ByteString& sAPType) { + dict_->RemoveFor(sAPType); +} + +CFX_ByteString CPWL_AppStream::GetBackgroundAppStream() const { + CFX_Color crBackground = widget_->GetFillPWLColor(); + if (crBackground.nColorType != COLORTYPE_TRANSPARENT) + return GetRectFillAppStream(widget_->GetRotatedRect(), crBackground); + + return CFX_ByteString(); +} + +CFX_ByteString CPWL_AppStream::GetBorderAppStream() const { + CFX_FloatRect rcWindow = widget_->GetRotatedRect(); + CFX_Color crBorder = widget_->GetBorderPWLColor(); + CFX_Color crBackground = widget_->GetFillPWLColor(); + CFX_Color crLeftTop; + CFX_Color crRightBottom; + + float fBorderWidth = static_cast(widget_->GetBorderWidth()); + CPWL_Dash dsBorder(3, 0, 0); + + BorderStyle nBorderStyle = widget_->GetBorderStyle(); + switch (nBorderStyle) { + case BorderStyle::DASH: + dsBorder = CPWL_Dash(3, 3, 0); + break; + case BorderStyle::BEVELED: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 1); + crRightBottom = crBackground / 2.0f; + break; + case BorderStyle::INSET: + fBorderWidth *= 2; + crLeftTop = CFX_Color(COLORTYPE_GRAY, 0.5); + crRightBottom = CFX_Color(COLORTYPE_GRAY, 0.75); + break; + default: + break; + } + + return 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 0000000000..2043c7b0d7 --- /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/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_string.h" + +class CPDFSDK_Widget; +class CPDF_Dictionary; +class CPDF_Stream; + +class CPWL_AppStream { + public: + CPWL_AppStream(CPDFSDK_Widget* widget, CPDF_Dictionary* dict); + ~CPWL_AppStream(); + + void SetAsPushButton(); + void SetAsCheckBox(); + void SetAsRadioButton(); + void SetAsComboBox(const CFX_WideString* sValue); + void SetAsListBox(); + void SetAsTextField(const CFX_WideString* sValue); + + private: + void AddImage(const CFX_ByteString& sAPType, CPDF_Stream* pImage); + void Write(const CFX_ByteString& sAPType, + const CFX_ByteString& sContents, + const CFX_ByteString& sAPState); + void Remove(const CFX_ByteString& sAPType); + + CFX_ByteString GetBackgroundAppStream() const; + CFX_ByteString GetBorderAppStream() const; + + CFX_UnownedPtr widget_; + CFX_UnownedPtr dict_; +}; + +#endif // FPDFSDK_PWL_CPWL_APPSTREAM_H_ diff --git a/fpdfsdk/pwl/cpwl_button.cpp b/fpdfsdk/pwl/cpwl_button.cpp new file mode 100644 index 0000000000..525148a767 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_button.cpp @@ -0,0 +1,38 @@ +// 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_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 { + return "CPWL_Button"; +} + +void CPWL_Button::OnCreate(PWL_CREATEPARAM& cp) { + cp.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/pwl/cpwl_button.h b/fpdfsdk/pwl/cpwl_button.h new file mode 100644 index 0000000000..44cc1e2cfd --- /dev/null +++ b/fpdfsdk/pwl/cpwl_button.h @@ -0,0 +1,27 @@ +// 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_BUTTON_H_ +#define FPDFSDK_PWL_CPWL_BUTTON_H_ + +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_Button : public CPWL_Wnd { + public: + CPWL_Button(); + ~CPWL_Button() override; + + // CPWL_Wnd + CFX_ByteString GetClassName() const override; + void OnCreate(PWL_CREATEPARAM& cp) override; + bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag) override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + + protected: + bool m_bMouseDown; +}; + +#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 0000000000..d309d2743b --- /dev/null +++ b/fpdfsdk/pwl/cpwl_caret.cpp @@ -0,0 +1,114 @@ +// 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 + +#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() {} + +CFX_ByteString CPWL_Caret::GetClassName() const { + return "CPWL_Caret"; +} + +void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice, + CFX_Matrix* pUser2Device) { + 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, pUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0), + FXFILL_ALTERNATE); +} + +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 = *pRect; + if (!rcRefresh.IsEmpty()) { + rcRefresh.Inflate(0.5f, 0.5f); + rcRefresh.Normalize(); + } + rcRefresh.top += 1; + rcRefresh.bottom -= 1; + CPWL_Wnd::InvalidateRect(&rcRefresh); + } else { + CPWL_Wnd::InvalidateRect(pRect); + } +} diff --git a/fpdfsdk/pwl/cpwl_caret.h b/fpdfsdk/pwl/cpwl_caret.h new file mode 100644 index 0000000000..a8ae5a3b74 --- /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 + CFX_ByteString GetClassName() const 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); + 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 0000000000..9514e55646 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_combo_box.cpp @@ -0,0 +1,541 @@ +// 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 +#include + +#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 kDefaultFontSize = 12.0f; +constexpr float kTriangleHalfLength = 3.0f; + +} // 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, + CFX_Matrix* pUser2Device) { + CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); + + CFX_FloatRect rectWnd = CPWL_Wnd::GetWindowRect(); + + if (!IsVisible() || rectWnd.IsEmpty()) + return; + + CFX_PointF ptCenter = GetCenterPoint(); + + CFX_PointF pt1(ptCenter.x - kTriangleHalfLength, + ptCenter.y + kTriangleHalfLength * 0.5f); + CFX_PointF pt2(ptCenter.x + kTriangleHalfLength, + ptCenter.y + kTriangleHalfLength * 0.5f); + CFX_PointF pt3(ptCenter.x, ptCenter.y - kTriangleHalfLength * 0.5f); + + if (IsFloatBigger(rectWnd.right - rectWnd.left, kTriangleHalfLength * 2) && + IsFloatBigger(rectWnd.top - rectWnd.bottom, kTriangleHalfLength)) { + 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->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() {} + +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::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() { + SetPopup(false); + CPWL_Wnd::KillFocus(); +} + +CFX_WideString CPWL_ComboBox::GetSelectedText() { + if (m_pEdit) + return m_pEdit->GetSelectedText(); + + return CFX_WideString(); +} + +void CPWL_ComboBox::DeleteSelectedText() { + if (m_pEdit) + m_pEdit->DeleteSelectedText(); +} + +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::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 PWL_CREATEPARAM& cp) { + CreateEdit(cp); + CreateButton(cp); + CreateListBox(cp); +} + +void CPWL_ComboBox::CreateEdit(const PWL_CREATEPARAM& cp) { + if (m_pEdit) + return; + + m_pEdit = new CPWL_Edit(); + m_pEdit->AttachFFLData(m_pFormFiller.Get()); + + 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(); + ecp.dwBorderWidth = 0; + ecp.nBorderStyle = BorderStyle::SOLID; + m_pEdit->Create(ecp); +} + +void CPWL_ComboBox::CreateButton(const PWL_CREATEPARAM& cp) { + if (m_pButton) + return; + + m_pButton = new CPWL_CBButton; + + PWL_CREATEPARAM bcp = cp; + bcp.pParentWnd = this; + bcp.dwFlags = PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND; + bcp.sBackgroundColor = CFX_Color(COLORTYPE_RGB, 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 PWL_CREATEPARAM& cp) { + if (m_pList) + return; + + m_pList = new CPWL_CBListBox(); + m_pList->AttachFFLData(m_pFormFiller.Get()); + + 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(); + + if (cp.dwFlags & PWS_AUTOFONTSIZE) + lcp.fFontSize = kDefaultFontSize; + 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() { + 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 - PWL_COMBOBOX_BUTTON_WIDTH, 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 (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); + } + return; + } + + CFX_FloatRect rcButton = rcClient; + rcButton.left = + std::max(rcButton.right - PWL_COMBOBOX_BUTTON_WIDTH, rcClient.left); + + if (m_pButton) + m_pButton->Move(rcButton, true, 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 (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; + float fListHeight = m_pList->GetContentRect().Height(); + if (!IsFloatBigger(fListHeight, 0.0f)) + return; + + if (!bPopup) { + m_bPopup = bPopup; + Move(m_rcOldWindow, true, true); + return; + } + + if (!m_pFillerNotify) + return; + +#ifdef PDF_ENABLE_XFA + if (m_pFillerNotify->OnPopupPreOpen(GetAttachedData(), 0)) + return; +#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; + + 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; + + Move(rcWindow, true, true); +#ifdef PDF_ENABLE_XFA + m_pFillerNotify->OnPopupPostOpen(GetAttachedData(), 0); +#endif // PDF_ENABLE_XFA +} + +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); +} + +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); +} + +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 0000000000..a50c4cee37 --- /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 + +#include "core/fxcrt/cfx_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); +}; + +#define PWL_COMBOBOX_BUTTON_WIDTH 13 + +class CPWL_CBButton : public CPWL_Wnd { + public: + CPWL_CBButton() {} + ~CPWL_CBButton() override {} + + // CPWL_Wnd + 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.Get(); } + + // CPWL_Wnd: + CFX_ByteString GetClassName() const override; + void OnCreate(PWL_CREATEPARAM& cp) 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 PWL_CREATEPARAM& cp) override; + void RePosChildWnd() override; + CFX_FloatRect GetFocusRect() const override; + void SetFocus() override; + void KillFocus() override; + CFX_WideString GetSelectedText() override; + void DeleteSelectedText() 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 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 PWL_CREATEPARAM& cp); + void CreateButton(const PWL_CREATEPARAM& cp); + void CreateListBox(const PWL_CREATEPARAM& cp); + void SetPopup(bool bPopup); + + CFX_UnownedPtr m_pEdit; + CFX_UnownedPtr m_pButton; + CFX_UnownedPtr m_pList; + CFX_FloatRect m_rcOldWindow; + bool m_bPopup = false; + bool m_bBottom = true; + int32_t m_nSelectItem = -1; + CFX_UnownedPtr m_pFillerNotify; + CFX_UnownedPtr 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 0000000000..afca67fd62 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp @@ -0,0 +1,268 @@ +// 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(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(pWindow); + } + + 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()); + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); + } + + 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()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEntireTextSelection) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); + } + + GetCPWLComboBox()->SetEditSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->DeleteSelectedText(); + EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); + } + + GetCPWLComboBox()->SetEditSelection(12, 23); + EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->DeleteSelectedText(); + EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); + } + + GetCPWLComboBox()->SetEditSelection(0, 5); + EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->DeleteSelectedText(); + EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); + } + + GetCPWLComboBox()->SetEditSelection(45, 50); + EXPECT_STREQ(L"nopqr", GetCPWLComboBox()->GetSelectedText().c_str()); + + GetCPWLComboBox()->DeleteSelectedText(); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", + GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEmptyTextSelection) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE( + GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), i + 'A', 0)); + } + + GetCPWLComboBox()->DeleteSelectedText(); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLComboBox()->GetText().c_str()); +} diff --git a/fpdfsdk/pwl/cpwl_edit.cpp b/fpdfsdk/pwl/cpwl_edit.cpp new file mode 100644 index 0000000000..4a19e70eb6 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit.cpp @@ -0,0 +1,709 @@ +// 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 +#include +#include +#include + +#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); +} + +CFX_ByteString CPWL_Edit::GetClassName() const { + return PWL_CLASSNAME_EDIT; +} + +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 pXML( + CXML_Element::Parse(sValue.c_str(), sValue.GetLength())); + if (!pXML) { + m_pEdit->SetText(swText); + return; + } + swText.clear(); + + bool bFirst = true; + int32_t nCount = pXML->CountChildren(); + for (int32_t i = 0; i < nCount; i++) { + CXML_Element* pSubElement = ToElement(pXML->GetChild(i)); + if (!pSubElement || !pSubElement->GetTagName().EqualNoCase("p")) + continue; + + CFX_WideString swSection; + int nSubChild = pSubElement->CountChildren(); + for (int32_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); +} + +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)) { + CFX_FloatRect rect = GetClientRect(); + if (!rect.IsEmpty()) { + // +1 for caret beside border + rect.Inflate(1.0f, 1.0f); + rect.Normalize(); + } + m_pEditCaret->SetClipRect(rect); + } + + CPWL_EditCtrl::RePosChildWnd(); +} + +CFX_FloatRect CPWL_Edit::GetClientRect() const { + float width = static_cast(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::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->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->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()); + 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, + CFX_Matrix* pUser2Device) { + CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); + + 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, pUser2Device, &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, 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(); + CPWL_EditImpl::DrawEdit(pDevice, pUser2Device, 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(); + + 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() { + CPWL_ScrollBar* pScroll = GetVScrollBar(); + if (pScroll && pScroll->IsVisible()) { + pScroll->SetVisible(false); + Move(m_rcOldWindow, true, true); + } + + m_pEdit->SelectNone(); + SetCaret(false, CFX_PointF(), CFX_PointF()); + 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()) { + 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); + } + + return CPVT_WordRange(); +} + +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()) { + 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; + } + + 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()) { + 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->ClearSelection(); + m_pEdit->InsertText(wsText, FX_CHARSET_Default); +} + +CFX_FloatRect CPWL_Edit::GetFocusRect() const { + return CFX_FloatRect(); +} + +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) { + CFX_WideString strChange; + CFX_WideString strChangeEx; + + int nSelStart = 0; + int nSelEnd = 0; + GetSelection(nSelStart, nSelEnd); + + if (nSelStart == nSelEnd) + nSelEnd = nSelStart + 1; + + bool bRC; + bool bExit; + std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke( + GetAttachedData(), strChange, strChangeEx, nSelStart, nSelEnd, true, + 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; + 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; + } + + CFX_WideString strChangeEx; + std::tie(bRC, bExit) = m_pFillerNotify->OnBeforeKeyStroke( + GetAttachedData(), swChange, strChangeEx, nSelStart, nSelEnd, true, + nFlag); + } + } + + 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)) { + 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) { + 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); +} + +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; + + 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 0000000000..2e92ed2ae7 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit.h @@ -0,0 +1,129 @@ +// 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 + +#include "core/fpdfdoc/cpvt_wordrange.h" +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_basic.h" +#include "fpdfsdk/pwl/cpwl_edit_ctrl.h" + +class IPWL_Filler_Notify { + public: + virtual ~IPWL_Filler_Notify() {} + + // Must write to |bBottom| and |fPopupRet|. + virtual void QueryWherePopup(void* pPrivateData, + float fPopupMin, + float fPopupMax, + bool* bBottom, + float* fPopupRet) = 0; + virtual std::pair OnBeforeKeyStroke( + void* pPrivateData, + CFX_WideString& strChange, + const CFX_WideString& strChangeEx, + int nSelStart, + int nSelEnd, + bool bKeyDown, + uint32_t nFlag) = 0; +#ifdef PDF_ENABLE_XFA + virtual bool OnPopupPreOpen(void* pPrivateData, uint32_t nFlag) = 0; + virtual bool OnPopupPostOpen(void* pPrivateData, 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 OnCreated() override; + void RePosChildWnd() override; + CFX_FloatRect GetClientRect() const 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(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); + + 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; + } + + 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; + 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 GetArabicWordsRange(const CPVT_WordPlace& place) const; + CPVT_WordRange GetSameWordsRange(const CPVT_WordPlace& place, + bool bLatin, + bool bArabic) const; + + bool m_bFocus; + CFX_FloatRect m_rcOldWindow; + CFX_UnownedPtr m_pFillerNotify; + CFX_UnownedPtr 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 0000000000..a852cb6231 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp @@ -0,0 +1,420 @@ +// 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_section.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(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); + } + } +} + +CFX_WideString CPWL_EditCtrl::GetSelectedText() { + if (m_pEdit) + return m_pEdit->GetSelectedText(); + + return CFX_WideString(); +} + +void CPWL_EditCtrl::DeleteSelectedText() { + if (m_pEdit) + m_pEdit->ClearSelection(); +} + +void CPWL_EditCtrl::RePosChildWnd() { + m_pEdit->SetPlateRect(GetClientRect()); +} + +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 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(); + + 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(); + + 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); +} + +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; + } +} + +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::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 0000000000..4fb86fab62 --- /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 + +#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; + + CFX_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(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 SetScrollInfo(const PWL_SCROLL_INFO& info) override; + void SetScrollPosition(float pos) override; + void ScrollWindowVertically(float pos) override; + void CreateChildWnd(const PWL_CREATEPARAM& cp) override; + void RePosChildWnd() override; + void SetFontSize(float fFontSize) override; + float GetFontSize() const override; + void SetCursor() override; + CFX_WideString GetSelectedText() override; + void DeleteSelectedText() override; + + void 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 m_pEdit; + CPWL_Caret* m_pEditCaret; + bool m_bMouseDown; + + private: + void CreateEditCaret(const PWL_CREATEPARAM& 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 0000000000..e41d9b0636 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp @@ -0,0 +1,187 @@ +// 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.pdf")); + m_page = LoadPage(0); + ASSERT_TRUE(m_page); + + CPDFSDK_FormFillEnvironment* pFormFillEnv = + static_cast(form_handle()); + + { + CBA_AnnotIterator iter(pFormFillEnv->GetPageView(0), + CPDF_Annot::Subtype::WIDGET); + m_pAnnot = iter.GetFirstAnnot(); + CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot(); + ASSERT_EQ(m_pAnnot, pLastAnnot); + ASSERT_TRUE(m_pAnnot); + ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnot->GetAnnotSubtype()); + } + + CFFL_InteractiveFormFiller* pInteractiveFormFiller = + pFormFillEnv->GetInteractiveFormFiller(); + { + CPDFSDK_Annot::ObservedPtr pObserved(m_pAnnot); + EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0)); + } + + m_pFormFiller = pInteractiveFormFiller->GetFormFiller(m_pAnnot, false); + ASSERT_TRUE(m_pFormFiller); + + CPWL_Wnd* pWindow = + m_pFormFiller->GetPDFWindow(pFormFillEnv->GetPageView(0), false); + ASSERT_TRUE(pWindow); + ASSERT_EQ(PWL_CLASSNAME_EDIT, pWindow->GetClassName()); + + m_pEdit = static_cast(pWindow); + } + + FPDF_PAGE GetPage() { return m_page; } + CPWL_Edit* GetCPWLEdit() { return m_pEdit; } + CFFL_FormFiller* GetCFFLFormFiller() { return m_pFormFiller; } + CPDFSDK_Annot* GetCPDFSDKAnnot() { return m_pAnnot; } + + private: + FPDF_PAGE m_page; + CPWL_Edit* m_pEdit; + CFFL_FormFiller* m_pFormFiller; + CPDFSDK_Annot* m_pAnnot; +}; + +TEST_F(CPWLEditEmbeddertest, TypeText) { + 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) { + // 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) { + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); + } + + 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()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteEntireTextSelection) { + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); + } + + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->DeleteSelectedText(); + EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionMiddle) { + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); + } + + GetCPWLEdit()->SetSelection(12, 23); + EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->DeleteSelectedText(); + EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionLeft) { + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); + } + + GetCPWLEdit()->SetSelection(0, 5); + EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->DeleteSelectedText(); + EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionRight) { + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); + } + + GetCPWLEdit()->SetSelection(45, 50); + EXPECT_STREQ(L"nopqr", GetCPWLEdit()->GetSelectedText().c_str()); + + GetCPWLEdit()->DeleteSelectedText(); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", + GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, DeleteEmptyTextSelection) { + for (int i = 0; i < 50; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), i + 'A', 0)); + } + + GetCPWLEdit()->DeleteSelectedText(); + EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", + 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 0000000000..c59a74068d --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_impl.cpp @@ -0,0 +1,2053 @@ +// 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 +#include +#include +#include + +#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/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, + 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 = CPDF_RenderOptions::kNormal; + + 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 = CPDF_RenderOptions::kNormal; + + CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, fFontSize, + pUser2Device, 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->GetAt(); +} + +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.Add(linerange, rect); +} + +void CPWL_EditImpl_Refresh::NoAnalyse() { + { + for (int32_t i = 0, sz = m_OldLineRects.GetSize(); i < sz; i++) + if (CPWL_EditImpl_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 (CPWL_EditImpl_LineRect* pNewRect = m_NewLineRects.GetAt(i)) + m_RefreshRects.Add(pNewRect->m_rcLine); + } +} + +const CPWL_EditImpl_RectArray* CPWL_EditImpl_Refresh::GetRefreshRects() const { + return &m_RefreshRects; +} + +void CPWL_EditImpl_Refresh::EndRefresh() { + m_RefreshRects.Clear(); +} + +CPWL_EditImpl_Undo::CPWL_EditImpl_Undo(int32_t nBufsize) + : m_nCurUndoPos(0), m_nBufSize(nBufsize), m_bWorking(false) {} + +CPWL_EditImpl_Undo::~CPWL_EditImpl_Undo() { + Reset(); +} + +bool CPWL_EditImpl_Undo::CanUndo() const { + return m_nCurUndoPos > 0; +} + +void CPWL_EditImpl_Undo::Undo() { + m_bWorking = true; + if (m_nCurUndoPos > 0) { + 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 (m_nCurUndoPos < m_UndoItemStack.size()) { + m_UndoItemStack[m_nCurUndoPos]->Redo(); + m_nCurUndoPos++; + } + m_bWorking = false; +} + +void CPWL_EditImpl_Undo::AddItem(std::unique_ptr 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_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 (m_UndoItemStack.size() > m_nCurUndoPos) + m_UndoItemStack.pop_back(); +} + +void CPWL_EditImpl_Undo::Reset() { + m_UndoItemStack.clear(); + m_nCurUndoPos = 0; +} + +CPWL_EditImpl_UndoItem::CPWL_EditImpl_UndoItem() + : m_bFirst(true), m_bLast(true) {} + +CPWL_EditImpl_UndoItem::~CPWL_EditImpl_UndoItem() {} + +CFX_WideString CPWL_EditImpl_UndoItem::GetUndoTitle() const { + return CFX_WideString(); +} + +void CPWL_EditImpl_UndoItem::SetFirst(bool bFirst) { + m_bFirst = bFirst; +} + +void CPWL_EditImpl_UndoItem::SetLast(bool bLast) { + m_bLast = bLast; +} + +bool CPWL_EditImpl_UndoItem::IsLast() { + return m_bLast; +} + +CFXEU_InsertWord::CFXEU_InsertWord(CPWL_EditImpl* 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(CPWL_EditImpl* 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(CPWL_EditImpl* 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) + return; + + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpOld); + m_pEdit->Backspace(false, true); +} + +void CFXEU_Backspace::Undo() { + if (!m_pEdit) + return; + + m_pEdit->SelectNone(); + m_pEdit->SetCaret(m_wpNew); + if (m_wpNew.nSecIndex != m_wpOld.nSecIndex) + 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(CPWL_EditImpl* 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(CPWL_EditImpl* 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->SetSelection(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, 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 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->SetSelection(m_wpOld, m_wpNew); + m_pEdit->Clear(false, true); + } +} + +// static +void CPWL_EditImpl::DrawEdit(CFX_RenderDevice* pDevice, + CFX_Matrix* pUser2Device, + 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; + const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255); + 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()) { + CFX_FloatRect rcTemp = rcClip; + pUser2Device->TransformRect(rcTemp); + pDevice->SetClip_Rect(rcTemp.ToFxRect()); + } + + CPWL_EditImpl_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 > 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, pUser2Device, 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, pUser2Device, + CFX_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, pUser2Device, + 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, pUser2Device, + CFX_ByteString(sTextBuf), crOldFill, nHorzScale); + } + } +} + +CPWL_EditImpl::CPWL_EditImpl() + : 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) {} + +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(pFontMap); + m_pVT->SetProvider(m_pVTProvider.get()); +} + +void CPWL_EditImpl::SetNotify(CPWL_EditCtrl* pNotify) { + m_pNotify = pNotify; +} + +void CPWL_EditImpl::SetOprNotify(CPWL_Edit* pOprNotify) { + m_pOprNotify = pOprNotify; +} + +CPWL_EditImpl_Iterator* CPWL_EditImpl::GetIterator() { + if (!m_pIterator) { + m_pIterator = + pdfium::MakeUnique(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; +} + +CFX_WideString CPWL_EditImpl::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.nSecIndex != place.nSecIndex) + swRet += L"\r\n"; + oldplace = place; + } + return swRet; +} + +CFX_WideString CPWL_EditImpl::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 > wrTemp.EndPos) + break; + if (pIterator->GetWord(wordinfo)) + swRet += wordinfo.Word; + if (oldplace.nSecIndex != place.nSecIndex) + swRet += L"\r\n"; + oldplace = place; + } + return swRet; +} + +CFX_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 CFX_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, nullptr, true, true); +} + +bool CPWL_EditImpl::InsertReturn() { + return InsertReturn(nullptr, nullptr, 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 CFX_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; + + CFX_AutoRestorer 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) { + CFX_AutoRestorer 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) { + CFX_AutoRestorer restorer(&m_bNotifyFlag); + m_bNotifyFlag = true; + if (const CPWL_EditImpl_RectArray* pRects = + m_Refresh.GetRefreshRects()) { + for (int32_t i = 0, sz = pRects->GetSize(); i < sz; i++) + m_pNotify->InvalidateRect(pRects->GetAt(i)); + } + } + } + + 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->GetAt(); + 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) { + CFX_AutoRestorer 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) { + CFX_AutoRestorer 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; + } + + CFX_AutoRestorer 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, + 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( + 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 CPWL_EditImpl::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( + 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 CPWL_EditImpl::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.nSecIndex != m_wpOldCaret.nSecIndex) { + AddEditUndoItem(pdfium::MakeUnique( + this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, + section.SecProps, section.WordProps)); + } else { + AddEditUndoItem(pdfium::MakeUnique( + 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 CPWL_EditImpl::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( + this, m_wpOldCaret, m_wpCaret, word.Word, word.nCharset, + section.SecProps, section.WordProps, bSecEnd)); + } else { + AddEditUndoItem(pdfium::MakeUnique( + 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 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(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_bOprNotify && m_pOprNotify) + m_pOprNotify->OnClear(m_wpCaret, m_wpOldCaret); + + return true; +} + +bool CPWL_EditImpl::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( + 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 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; +} + +void CPWL_EditImpl::EnableOprNotify(bool bNotify) { + m_bOprNotify = bNotify; +} + +CPVT_WordPlace CPWL_EditImpl::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 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 pEditUndoItem) { + m_Undo.AddItem(std::move(pEditUndoItem)); +} + +CFX_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 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; +} + +CPWL_EditImpl_LineRectArray::CPWL_EditImpl_LineRectArray() {} + +CPWL_EditImpl_LineRectArray::~CPWL_EditImpl_LineRectArray() {} + +void CPWL_EditImpl_LineRectArray::operator=( + CPWL_EditImpl_LineRectArray&& that) { + m_LineRects = std::move(that.m_LineRects); +} + +void CPWL_EditImpl_LineRectArray::Add(const CPVT_WordRange& wrLine, + const CFX_FloatRect& rcLine) { + m_LineRects.push_back( + pdfium::MakeUnique(wrLine, rcLine)); +} + +int32_t CPWL_EditImpl_LineRectArray::GetSize() const { + return pdfium::CollectionSize(m_LineRects); +} + +CPWL_EditImpl_LineRect* CPWL_EditImpl_LineRectArray::GetAt( + int32_t nIndex) const { + if (nIndex < 0 || nIndex >= GetSize()) + return nullptr; + + return m_LineRects[nIndex].get(); +} + +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; +} + +CPWL_EditImpl_RectArray::CPWL_EditImpl_RectArray() {} + +CPWL_EditImpl_RectArray::~CPWL_EditImpl_RectArray() {} + +void CPWL_EditImpl_RectArray::Clear() { + m_Rects.clear(); +} + +void CPWL_EditImpl_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(rect)); +} + +int32_t CPWL_EditImpl_RectArray::GetSize() const { + return pdfium::CollectionSize(m_Rects); +} + +CFX_FloatRect* CPWL_EditImpl_RectArray::GetAt(int32_t nIndex) const { + if (nIndex < 0 || nIndex >= GetSize()) + return nullptr; + + return m_Rects[nIndex].get(); +} diff --git a/fpdfsdk/pwl/cpwl_edit_impl.h b/fpdfsdk/pwl/cpwl_edit_impl.h new file mode 100644 index 0000000000..697ca84994 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_edit_impl.h @@ -0,0 +1,515 @@ +// 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 +#include +#include + +#include "core/fpdfdoc/cpvt_secprops.h" +#include "core/fpdfdoc/cpvt_wordprops.h" +#include "core/fxcrt/cfx_unowned_ptr.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_LineRectArray { + public: + CPWL_EditImpl_LineRectArray(); + ~CPWL_EditImpl_LineRectArray(); + + void operator=(CPWL_EditImpl_LineRectArray&& rects); + void Add(const CPVT_WordRange& wrLine, const CFX_FloatRect& rcLine); + + int32_t GetSize() const; + CPWL_EditImpl_LineRect* GetAt(int32_t nIndex) const; + + private: + std::vector> m_LineRects; +}; + +class CPWL_EditImpl_RectArray { + public: + CPWL_EditImpl_RectArray(); + ~CPWL_EditImpl_RectArray(); + + void Clear(); + void Add(const CFX_FloatRect& rect); + + int32_t GetSize() const; + CFX_FloatRect* GetAt(int32_t nIndex) const; + + private: + std::vector> m_Rects; +}; + +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(); + const CPWL_EditImpl_RectArray* GetRefreshRects() const; + void EndRefresh(); + + private: + CPWL_EditImpl_LineRectArray m_NewLineRects; + CPWL_EditImpl_LineRectArray m_OldLineRects; + CPWL_EditImpl_RectArray 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: + explicit CPWL_EditImpl_Undo(int32_t nBufsize); + ~CPWL_EditImpl_Undo(); + + void AddItem(std::unique_ptr pItem); + void Undo(); + void Redo(); + bool CanUndo() const; + bool CanRedo() const; + void Reset(); + + private: + void RemoveHeads(); + void RemoveTails(); + + std::deque> m_UndoItemStack; + size_t m_nCurUndoPos; + size_t m_nBufSize; + 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 CPWL_EditImpl_UndoItem : public IFX_Edit_UndoItem { + public: + CPWL_EditImpl_UndoItem(); + ~CPWL_EditImpl_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 CFXEU_InsertWord : public CPWL_EditImpl_UndoItem { + public: + CFXEU_InsertWord(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + uint16_t word, + int32_t charset, + const CPVT_WordProps* pWordProps); + ~CFXEU_InsertWord() override; + + // CPWL_EditImpl_UndoItem + void Redo() override; + void Undo() override; + + private: + CFX_UnownedPtr 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 CPWL_EditImpl_UndoItem { + public: + CFXEU_InsertReturn(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + const CPVT_SecProps* pSecProps, + const CPVT_WordProps* pWordProps); + ~CFXEU_InsertReturn() override; + + // CPWL_EditImpl_UndoItem + void Redo() override; + void Undo() override; + + private: + CFX_UnownedPtr m_pEdit; + + CPVT_WordPlace m_wpOld; + CPVT_WordPlace m_wpNew; + CPVT_SecProps m_SecProps; + CPVT_WordProps m_WordProps; +}; + +class CFXEU_Backspace : public CPWL_EditImpl_UndoItem { + public: + CFXEU_Backspace(CPWL_EditImpl* 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; + + // CPWL_EditImpl_UndoItem + void Redo() override; + void Undo() override; + + private: + CFX_UnownedPtr 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 CPWL_EditImpl_UndoItem { + public: + CFXEU_Delete(CPWL_EditImpl* 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; + + // CPWL_EditImpl_UndoItem + void Redo() override; + void Undo() override; + + private: + CFX_UnownedPtr 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 CPWL_EditImpl_UndoItem { + public: + CFXEU_Clear(CPWL_EditImpl* pEdit, + const CPVT_WordRange& wrSel, + const CFX_WideString& swText); + ~CFXEU_Clear() override; + + // CPWL_EditImpl_UndoItem + void Redo() override; + void Undo() override; + + private: + CFX_UnownedPtr m_pEdit; + + CPVT_WordRange m_wrSel; + CFX_WideString m_swText; +}; + +class CFXEU_InsertText : public CPWL_EditImpl_UndoItem { + public: + CFXEU_InsertText(CPWL_EditImpl* pEdit, + const CPVT_WordPlace& wpOldPlace, + const CPVT_WordPlace& wpNewPlace, + const CFX_WideString& swText, + int32_t charset); + ~CFXEU_InsertText() override; + + // CPWL_EditImpl_UndoItem + void Redo() override; + void Undo() override; + + private: + CFX_UnownedPtr m_pEdit; + + CPVT_WordPlace m_wpOld; + CPVT_WordPlace m_wpNew; + CFX_WideString m_swText; + int32_t m_nCharset; +}; + +class CPWL_EditImpl { + public: + static void DrawEdit(CFX_RenderDevice* pDevice, + CFX_Matrix* pUser2Device, + 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 SetOprNotify(CPWL_Edit* pOprNotify); + + // 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 CFX_WideString& sText); + bool InsertWord(uint16_t word, int32_t charset); + bool InsertReturn(); + bool Backspace(); + bool Delete(); + bool ClearSelection(); + bool InsertText(const CFX_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; + CFX_WideString GetSelectedText() const; + CFX_WideString GetText() const; + 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; + 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); + 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; + + CFX_ByteString GetPDFWordString(int32_t nFontIndex, + uint16_t Word, + uint16_t SubWord); + + private: + friend class CPWL_EditImpl_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 SetSelection(const CPVT_WordPlace& begin, const CPVT_WordPlace& end); + + void RearrangeAll(); + void RearrangePart(const CPVT_WordRange& range); + void ScrollToCaret(); + void SetScrollInfo(); + void SetScrollPosX(float fx); + void SetScrollPosY(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 pEditUndoItem); + + private: + std::unique_ptr m_pVT; + CFX_UnownedPtr m_pNotify; + CFX_UnownedPtr m_pOprNotify; + std::unique_ptr 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 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; + bool m_bOprNotify; +}; + +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: + CFX_UnownedPtr 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 0000000000..862973541a --- /dev/null +++ b/fpdfsdk/pwl/cpwl_font_map.cpp @@ -0,0 +1,413 @@ +// 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 + +#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(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; +} + +CFX_ByteString CPWL_FontMap::GetPDFFontAlias(int32_t nFontIndex) { + if (pdfium::IndexInBounds(m_Data, nFontIndex) && m_Data[nFontIndex]) + return m_Data[nFontIndex]->sFontName; + + return CFX_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; +} + +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(); + 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 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 == FX_CHARSET_Default || 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 = bFind ? FindFontSameCharset(&sAlias, nCharset) : nullptr; + 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(); + pNewData->pFont = pFont; + pNewData->sFontName = sFontAlias; + pNewData->nCharset = nCharset; + m_Data.push_back(std::move(pNewData)); + return pdfium::CollectionSize(m_Data) - 1; +} + +void CPWL_FontMap::AddedFont(CPDF_Font* pFont, + const CFX_ByteString& sFontAlias) {} + +CFX_ByteString CPWL_FontMap::GetNativeFont(int32_t nCharset) { + if (nCharset == FX_CHARSET_Default) + 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 == FX_CHARSET_Default) + 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 { + 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 _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || \ + _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + {FX_CHARSET_MSWin_EasternEuropean, "Arial"}, +#else + {FX_CHARSET_MSWin_EasternEuropean, "Tahoma"}, +#endif + {FX_CHARSET_MSWin_Arabic, "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 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 0000000000..9872779c95 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_font_map.h @@ -0,0 +1,95 @@ +// 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 +#include + +#include "core/fpdfdoc/ipvt_fontmap.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/fx_font.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 = FX_CHARSET_Default); + + CFX_ByteString EncodeFontAlias(const CFX_ByteString& sFontName, + int32_t nCharset); + CFX_ByteString EncodeFontAlias(const CFX_ByteString& sFontName); + + std::vector> m_Data; + std::vector> m_NativeFont; + + private: + int32_t FindFont(const CFX_ByteString& sFontName, + int32_t nCharset = FX_CHARSET_Default); + + 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 m_pPDFDoc; + CFX_UnownedPtr 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 0000000000..8a2e31da6a --- /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 +#include + +#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 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(); +} + +CFX_ByteString CPWL_Icon::GetImageAlias() { + if (!m_pPDFStream) + return CFX_ByteString(); + if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict()) + return pDict->GetStringFor("Name"); + return CFX_ByteString(); +} + +std::pair 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 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 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 0000000000..2607e56890 --- /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 + +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_string.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 GetScale(); + + // x, y + std::pair GetImageOffset(); + + CFX_Matrix GetImageMatrix(); + CFX_ByteString GetImageAlias(); + + private: + // left, bottom + std::pair GetIconPosition(); + + // width, height + std::pair GetImageSize(); + + CFX_UnownedPtr m_pPDFStream; + CFX_UnownedPtr 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 0000000000..060b3f6ee3 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_list_box.cpp @@ -0,0 +1,375 @@ +// 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 + +#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); + + 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(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() {} + +CFX_ByteString CPWL_ListBox::GetClassName() const { + return "CPWL_ListBox"; +} + +void CPWL_ListBox::OnCreated() { + m_pList->SetFontMap(GetFontMap()); + m_pListNotify = pdfium::MakeUnique(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::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 (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, pUser2Device, m_pList->GetItemEdit(i), + GetTextColor().ToFXColor(255), rcList, ptOffset, + nullptr, pSysHandler, m_pFormFiller.Get()); + pSysHandler->OutputSelectedRect(m_pFormFiller.Get(), rcItem); + } else { + pDevice->DrawFillRect(pUser2Device, rcItem, + ArgbEncode(255, 0, 51, 113)); + CPWL_EditImpl::DrawEdit(pDevice, pUser2Device, 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, 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; + } + 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(); +} + +void CPWL_ListBox::RePosChildWnd() { + CPWL_Wnd::RePosChildWnd(); + + m_pList->SetPlateRect(GetListRect()); +} + +bool CPWL_ListBox::OnNotifySelectionChanged(bool bKeyDown, uint32_t nFlag) { + if (!m_pFillerNotify) + return false; + + CFX_WideString swChange = GetText(); + CFX_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); + 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 CFX_WideString& str) { + m_pList->AddString(str); +} + +CFX_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(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 0000000000..8938f243d5 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_list_box.h @@ -0,0 +1,110 @@ +// 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 + +#include "core/fxcrt/cfx_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_SecProps; +struct CPVT_WordPlace; +struct CPVT_WordProps; + +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: + CFX_UnownedPtr 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 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 SetScrollInfo(const PWL_SCROLL_INFO& info) override; + void SetScrollPosition(float pos) override; + void ScrollWindowVertically(float pos) override; + void RePosChildWnd() override; + CFX_FloatRect GetFocusRect() const override; + void SetFontSize(float fFontSize) override; + float GetFontSize() const override; + + virtual CFX_WideString GetText() const; + + bool OnNotifySelectionChanged(bool bKeyDown, 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, 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 m_pList; + std::unique_ptr m_pListNotify; + bool m_bMouseDown; + bool m_bHoverSel; + CFX_UnownedPtr m_pFillerNotify; + + private: + CFX_UnownedPtr 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 0000000000..94e0606941 --- /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 +#include + +#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 CFX_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; +} + +CFX_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 CFX_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(m_ListItems) - 1; + return -1; +} + +CFX_WideString CPWL_ListCtrl::GetText() const { + if (IsMultipleSel()) + return GetItemText(m_nCaretIndex); + return GetItemText(m_nSelItem); +} + +void CPWL_ListCtrl::AddItem(const CFX_WideString& str) { + auto pListItem = pdfium::MakeUnique(); + 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(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(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); +} + +CFX_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 0000000000..ca159b7e5e --- /dev/null +++ b/fpdfsdk/pwl/cpwl_list_impl.h @@ -0,0 +1,168 @@ +// 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 +#include +#include + +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_coordinates.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::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 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 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) { 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 CFX_WideString& text); + void SetFontSize(float fFontSize); + CFX_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 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 CFX_WideString& str); + CFX_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; + CFX_UnownedPtr 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> m_ListItems; + float m_fFontSize; + CFX_UnownedPtr 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 0000000000..19e4bc8b5f --- /dev/null +++ b/fpdfsdk/pwl/cpwl_scroll_bar.cpp @@ -0,0 +1,881 @@ +// 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 +#include +#include + +#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 kTriangleHalfLength = 2.0f; + +} // namespace + +#define PWL_DEFAULT_HEAVYGRAYCOLOR CFX_Color(COLORTYPE_GRAY, 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() {} + +CFX_ByteString CPWL_SBButton::GetClassName() const { + return "CPWL_SBButton"; +} + +void CPWL_SBButton::OnCreate(PWL_CREATEPARAM& cp) { + cp.eCursorType = FXCT_ARROW; +} + +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(); + + if (m_eScrollBarType == SBT_HSCROLL) { + CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device); + + CFX_PointF pt1; + CFX_PointF pt2; + CFX_PointF pt3; + if (m_eSBButtonType == PSBT_MIN) { + pt1 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f, ptCenter.y); + pt2 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f, + ptCenter.y + kTriangleHalfLength); + pt3 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f, + ptCenter.y - kTriangleHalfLength); + } else if (m_eSBButtonType == PSBT_MAX) { + pt1 = CFX_PointF(ptCenter.x + kTriangleHalfLength * 0.5f, ptCenter.y); + pt2 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f, + ptCenter.y + kTriangleHalfLength); + pt3 = CFX_PointF(ptCenter.x - kTriangleHalfLength * 0.5f, + ptCenter.y - kTriangleHalfLength); + } + + if (rectWnd.right - rectWnd.left > kTriangleHalfLength * 2 && + rectWnd.top - rectWnd.bottom > kTriangleHalfLength) { + 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); + } + return; + } + + // draw border + pDevice->DrawStrokeRect(pUser2Device, rectWnd, + ArgbEncode(nTransparency, 100, 100, 100), 0.0f); + pDevice->DrawStrokeRect(pUser2Device, rectWnd.GetDeflated(0.5f, 0.5f), + ArgbEncode(nTransparency, 255, 255, 255), 1.0f); + + if (m_eSBButtonType != PSBT_POS) { + // draw background + if (IsEnabled()) { + pDevice->DrawShadow(pUser2Device, true, false, + rectWnd.GetDeflated(1.0f, 1.0f), nTransparency, 80, + 220); + } else { + pDevice->DrawFillRect(pUser2Device, 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 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(pUser2Device, 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(pUser2Device, ptTop, ptBottom, ref, 1.0f); + + ptTop.x += 1.0f; + ptBottom.x += 1.0f; + } + } else { + pDevice->DrawFillRect(pUser2Device, 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(pUser2Device, 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() {} + +CFX_ByteString CPWL_ScrollBar::GetClassName() const { + return "CPWL_ScrollBar"; +} + +void CPWL_ScrollBar::OnCreate(PWL_CREATEPARAM& cp) { + cp.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(); +} + +void 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 { + SetVisible(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 { + 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::DrawThisAppearance(CFX_RenderDevice* pDevice, + CFX_Matrix* pUser2Device) { + CFX_FloatRect rectWnd = GetWindowRect(); + + if (IsVisible() && !rectWnd.IsEmpty()) { + pDevice->DrawFillRect(pUser2Device, rectWnd, GetBackgroundColor(), + GetTransparency()); + + pDevice->DrawStrokeLine( + 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); + + pDevice->DrawStrokeLine( + 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 + 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(); + 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::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 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); + } +} + +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) { + 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(float fPos) { + float fOldPos = m_sData.fScrollPos; + m_sData.SetPos(fPos); + if (!IsFloatEqual(m_sData.fScrollPos, fOldPos)) + MovePosButton(true); +} + +void CPWL_ScrollBar::SetScrollStep(float fBigStep, 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(); + + 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; + } + + 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) { + 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)) { + MovePosButton(true); + + 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 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/pwl/cpwl_scroll_bar.h b/fpdfsdk/pwl/cpwl_scroll_bar.h new file mode 100644 index 0000000000..c78b6e36f8 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_scroll_bar.h @@ -0,0 +1,184 @@ +// 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_SCROLL_BAR_H_ +#define FPDFSDK_PWL_CPWL_SCROLL_BAR_H_ + +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "fpdfsdk/pwl/cpwl_wnd.h" + +class CPWL_SBButton; +class CPWL_ScrollBar; + +struct PWL_SCROLL_INFO { + public: + PWL_SCROLL_INFO() + : fContentMin(0.0f), + fContentMax(0.0f), + fPlateWidth(0.0f), + fBigStep(0.0f), + fSmallStep(0.0f) {} + + bool operator==(const PWL_SCROLL_INFO& that) const { + return fContentMin == that.fContentMin && fContentMax == that.fContentMax && + fPlateWidth == that.fPlateWidth && fBigStep == that.fBigStep && + fSmallStep == that.fSmallStep; + } + bool operator!=(const PWL_SCROLL_INFO& that) const { + return !(*this == that); + } + + float fContentMin; + float fContentMax; + float fPlateWidth; + float fBigStep; + float fSmallStep; +}; + +enum PWL_SCROLLBAR_TYPE { SBT_HSCROLL, SBT_VSCROLL }; + +enum PWL_SBBUTTON_TYPE { PSBT_MIN, PSBT_MAX, PSBT_POS }; + +class CPWL_SBButton : public CPWL_Wnd { + public: + CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType, + PWL_SBBUTTON_TYPE eButtonType); + ~CPWL_SBButton() override; + + // CPWL_Wnd + CFX_ByteString GetClassName() const override; + void OnCreate(PWL_CREATEPARAM& cp) 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; + bool OnMouseMove(const CFX_PointF& point, uint32_t nFlag) override; + + protected: + PWL_SCROLLBAR_TYPE m_eScrollBarType; + PWL_SBBUTTON_TYPE m_eSBButtonType; + + bool m_bMouseDown; +}; + +struct PWL_FLOATRANGE { + public: + PWL_FLOATRANGE(); + PWL_FLOATRANGE(float min, float max); + + bool operator==(const PWL_FLOATRANGE& that) const { + return fMin == that.fMin && fMax == that.fMax; + } + bool operator!=(const PWL_FLOATRANGE& that) const { return !(*this == that); } + + void Default(); + void Set(float min, float max); + bool In(float x) const; + float GetWidth() const; + + float fMin; + float fMax; +}; + +struct PWL_SCROLL_PRIVATEDATA { + public: + PWL_SCROLL_PRIVATEDATA(); + + bool operator==(const PWL_SCROLL_PRIVATEDATA& that) const { + return ScrollRange == that.ScrollRange && + fClientWidth == that.fClientWidth && fScrollPos == that.fScrollPos && + fBigStep == that.fBigStep && fSmallStep == that.fSmallStep; + } + bool operator!=(const PWL_SCROLL_PRIVATEDATA& that) const { + return !(*this == that); + } + + void Default(); + 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(); + void AddBig(); + void SubBig(); + + PWL_FLOATRANGE ScrollRange; + float fClientWidth; + float fScrollPos; + float fBigStep; + float fSmallStep; +}; + +class CPWL_ScrollBar : public CPWL_Wnd { + public: + 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 OnDestroy() override; + void RePosChildWnd() 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; + 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 PWL_CREATEPARAM& cp) override; + void TimerProc() override; + + float GetScrollBarWidth() const; + PWL_SCROLLBAR_TYPE GetScrollBarType() const { return m_sbType; } + + void SetNotifyForever(bool bForever) { m_bNotifyForever = bForever; } + + protected: + void SetScrollRange(float fMin, float fMax, float fClientWidth); + void SetScrollPos(float fPos); + void MovePosButton(bool bRefresh); + void SetScrollStep(float fBigStep, float fSmallStep); + void NotifyScrollWindow(); + CFX_FloatRect GetScrollArea() const; + + private: + void CreateButtons(const PWL_CREATEPARAM& cp); + + void OnMinButtonLBDown(const CFX_PointF& point); + void OnMinButtonLBUp(const CFX_PointF& point); + void OnMinButtonMouseMove(const CFX_PointF& point); + + void OnMaxButtonLBDown(const CFX_PointF& point); + void OnMaxButtonLBUp(const CFX_PointF& point); + void OnMaxButtonMouseMove(const CFX_PointF& point); + + void OnPosButtonLBDown(const CFX_PointF& point); + void OnPosButtonLBUp(const CFX_PointF& point); + void OnPosButtonMouseMove(const CFX_PointF& point); + + float TrueToFace(float); + float FaceToTrue(float); + + PWL_SCROLLBAR_TYPE m_sbType; + PWL_SCROLL_INFO m_OriginInfo; + CFX_UnownedPtr m_pMinButton; + CFX_UnownedPtr m_pMaxButton; + CFX_UnownedPtr m_pPosButton; + PWL_SCROLL_PRIVATEDATA m_sData; + bool m_bMouseDown; + bool m_bMinOrMax; + bool m_bNotifyForever; + float m_nOldPos; + float m_fOldPosButton; +}; + +#endif // FPDFSDK_PWL_CPWL_SCROLL_BAR_H_ diff --git a/fpdfsdk/pwl/cpwl_special_button.cpp b/fpdfsdk/pwl/cpwl_special_button.cpp new file mode 100644 index 0000000000..53f7f2c1d0 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_special_button.cpp @@ -0,0 +1,80 @@ +// 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_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 { + return "CPWL_PushButton"; +} + +CFX_FloatRect CPWL_PushButton::GetFocusRect() const { + return GetWindowRect().GetDeflated(static_cast(GetBorderWidth()), + static_cast(GetBorderWidth())); +} + +CPWL_CheckBox::CPWL_CheckBox() : m_bChecked(false) {} + +CPWL_CheckBox::~CPWL_CheckBox() {} + +CFX_ByteString CPWL_CheckBox::GetClassName() const { + return "CPWL_CheckBox"; +} + +void CPWL_CheckBox::SetCheck(bool bCheck) { + m_bChecked = bCheck; +} + +bool CPWL_CheckBox::IsChecked() const { + return m_bChecked; +} + +bool CPWL_CheckBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + if (IsReadOnly()) + return false; + + SetCheck(!IsChecked()); + return true; +} + +bool CPWL_CheckBox::OnChar(uint16_t nChar, uint32_t nFlag) { + SetCheck(!IsChecked()); + return true; +} + +CPWL_RadioButton::CPWL_RadioButton() : m_bChecked(false) {} + +CPWL_RadioButton::~CPWL_RadioButton() {} + +CFX_ByteString CPWL_RadioButton::GetClassName() const { + return "CPWL_RadioButton"; +} + +bool CPWL_RadioButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) { + if (IsReadOnly()) + return false; + + SetCheck(true); + return true; +} + +void CPWL_RadioButton::SetCheck(bool bCheck) { + m_bChecked = bCheck; +} + +bool CPWL_RadioButton::IsChecked() const { + return m_bChecked; +} + +bool CPWL_RadioButton::OnChar(uint16_t nChar, uint32_t nFlag) { + SetCheck(true); + return true; +} diff --git a/fpdfsdk/pwl/cpwl_special_button.h b/fpdfsdk/pwl/cpwl_special_button.h new file mode 100644 index 0000000000..b499542795 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_special_button.h @@ -0,0 +1,56 @@ +// 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_SPECIAL_BUTTON_H_ +#define FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_ + +#include "fpdfsdk/pwl/cpwl_button.h" + +class CPWL_PushButton : public CPWL_Button { + public: + CPWL_PushButton(); + ~CPWL_PushButton() override; + + // CPWL_Button + CFX_ByteString GetClassName() const override; + CFX_FloatRect GetFocusRect() const override; +}; + +class CPWL_CheckBox : public CPWL_Button { + public: + CPWL_CheckBox(); + ~CPWL_CheckBox() override; + + // CPWL_Button + CFX_ByteString GetClassName() const override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + bool OnChar(uint16_t nChar, uint32_t nFlag) override; + + void SetCheck(bool bCheck); + bool IsChecked() const; + + private: + bool m_bChecked; +}; + +class CPWL_RadioButton : public CPWL_Button { + public: + CPWL_RadioButton(); + ~CPWL_RadioButton() override; + + // CPWL_Button + CFX_ByteString GetClassName() const override; + bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override; + bool OnChar(uint16_t nChar, uint32_t nFlag) override; + + void SetCheck(bool bCheck); + bool IsChecked() const; + + private: + bool m_bChecked; +}; + +#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 0000000000..34f81fc433 --- /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 + +#include "fpdfsdk/cfx_systemhandler.h" +#include "fpdfsdk/pwl/cpwl_timer_handler.h" + +namespace { + +std::map& GetPWLTimeMap() { + // Leak the object at shutdown. + static auto* timeMap = new std::map; + 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 0000000000..6f76fe7eb0 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_timer.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_PWL_CPWL_TIMER_H_ +#define FPDFSDK_PWL_CPWL_TIMER_H_ + +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_basic.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; + CFX_UnownedPtr m_pAttached; + CFX_UnownedPtr 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 0000000000..33af306deb --- /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(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 0000000000..b65a5152be --- /dev/null +++ b/fpdfsdk/pwl/cpwl_timer_handler.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_PWL_CPWL_TIMER_HANDLER_H_ +#define FPDFSDK_PWL_CPWL_TIMER_HANDLER_H_ + +#include + +#include "core/fxcrt/fx_basic.h" + +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 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 0000000000..2269162260 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_wnd.cpp @@ -0,0 +1,806 @@ +// 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 +#include +#include + +#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; +constexpr int kInvalidationInflate = 2; + +} // namespace + +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(kDefaultFontSize), + sDash(3, 0, 0), + pAttachedData(nullptr), + pParentWnd(nullptr), + pMsgControl(nullptr), + eCursorType(FXCT_ARROW) {} + +PWL_CREATEPARAM::PWL_CREATEPARAM(const PWL_CREATEPARAM& other) = default; + +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 m_aMousePath; + std::vector m_aKeyboardPath; + CFX_UnownedPtr m_pCreatedWnd; + CFX_UnownedPtr m_pMainMouseWnd; + CFX_UnownedPtr 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); +} + +CFX_ByteString CPWL_Wnd::GetClassName() const { + return "CPWL_Wnd"; +} + +void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) { + if (IsValid()) + return; + + m_sPrivateParam = cp; + OnCreate(m_sPrivateParam); + + m_sPrivateParam.rcRectWnd.Normalize(); + m_rcWindow = m_sPrivateParam.rcRectWnd; + m_rcClip = m_rcWindow; + if (!m_rcClip.IsEmpty()) { + m_rcClip.Inflate(1.0f, 1.0f); + m_rcClip.Normalize(); + } + CreateMsgControl(); + + if (m_sPrivateParam.pParentWnd) + m_sPrivateParam.pParentWnd->AddChild(this); + + PWL_CREATEPARAM ccp = m_sPrivateParam; + + ccp.dwFlags &= 0xFFFF0000L; // remove sub styles + 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) { + m_pVScrollBar = nullptr; + 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->RemoveChild(this); + + m_bCreated = false; + } + DestroyMsgControl(); + m_sPrivateParam.Reset(); + m_Children.clear(); +} + +void CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) { + if (!IsValid()) + return; + + 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) { + 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::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()) + return; + + if (HasFlag(PWS_BACKGROUND)) { + float width = static_cast(GetBorderWidth() + GetInnerBorderWidth()); + pDevice->DrawFillRect(pUser2Device, rectWnd.GetDeflated(width, width), + GetBackgroundColor(), GetTransparency()); + } + + if (HasFlag(PWS_BORDER)) { + pDevice->DrawBorder(pUser2Device, rectWnd, + static_cast(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()) + return; + + 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 -= kInvalidationInflate; + rcWin.top -= kInvalidationInflate; + rcWin.right += kInvalidationInflate; + rcWin.bottom += kInvalidationInflate; + + if (CFX_SystemHandler* pSH = GetSystemHandler()) { + if (CPDFSDK_Widget* widget = static_cast( + 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 (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 + +CFX_WideString CPWL_Wnd::GetSelectedText() { + return CFX_WideString(); +} + +void CPWL_Wnd::DeleteSelectedText() {} + +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) {} + +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(); + + float width = static_cast(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_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; +} + +CFX_Color CPWL_Wnd::GetBackgroundColor() const { + return m_sPrivateParam.sBackgroundColor; +} + +void CPWL_Wnd::SetBackgroundColor(const CFX_Color& color) { + m_sPrivateParam.sBackgroundColor = color; +} + +CFX_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 { + return HasFlag(PWS_BORDER) ? m_sPrivateParam.dwBorderWidth : 0; +} + +int32_t CPWL_Wnd::GetInnerBorderWidth() const { + return 0; +} + +CFX_Color CPWL_Wnd::GetBorderColor() const { + return HasFlag(PWS_BORDER) ? m_sPrivateParam.sBorderColor : CFX_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 { + return HasFlag(PWS_VSCROLL) ? m_pVScrollBar.Get() : 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)) + return; + + 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 (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_sPrivateParam.pParentWnd; + return pParent ? pParent->GetRootWnd() : this; +} + +void CPWL_Wnd::SetVisible(bool bVisible) { + if (!IsValid()) + return; + + for (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() { + CPWL_ScrollBar* pVSB = GetVScrollBar(); + if (!pVSB) + return; + + CFX_FloatRect rcContent = GetWindowRect(); + if (!rcContent.IsEmpty()) { + float width = static_cast(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); + 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() { + CPWL_MsgControl* pMsgControl = GetMsgControl(); + if (pMsgControl && 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 { + 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_sPrivateParam.fFontSize; +} + +void CPWL_Wnd::SetFontSize(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; +} + +CFX_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const { + switch (nBorderStyle) { + case BorderStyle::BEVELED: + return CFX_Color(COLORTYPE_GRAY, 1); + case BorderStyle::INSET: + return CFX_Color(COLORTYPE_GRAY, 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(COLORTYPE_GRAY, 0.75f); + default: + return CFX_Color(); + } +} + +int32_t CPWL_Wnd::GetTransparency() { + return m_sPrivateParam.nTransparency; +} + +void CPWL_Wnd::SetTransparency(int32_t nTransparency) { + for (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; + + 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; + CFX_FloatRect rc = rect; + mt.TransformRect(rc); + return rc; +} + +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_sPrivateParam.mtChild : CFX_Matrix(); +} + +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.Get() : 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 0000000000..7c93216a58 --- /dev/null +++ b/fpdfsdk/pwl/cpwl_wnd.h @@ -0,0 +1,344 @@ +// 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 +#include + +#include "core/fpdfdoc/cpdf_formcontrol.h" +#include "core/fxcrt/cfx_observable.h" +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxcrt/fx_basic.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 CPWL_Wnd; +class CFX_SystemHandler; +class IPVT_FontMap; +class IPWL_Provider; +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 + +#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 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_SELBACKCOLOR \ + CFX_Color(COLORTYPE_RGB, 0, 51.0f / 255.0f, 113.0f / 255.0f) +#define PWL_DEFAULT_BLACKCOLOR CFX_Color(COLORTYPE_GRAY, 0) +#define PWL_DEFAULT_WHITECOLOR CFX_Color(COLORTYPE_GRAY, 1) + +class IPWL_Provider : public CFX_Observable { + public: + virtual ~IPWL_Provider() {} + + // get a matrix which map user space to CWnd client space + virtual CFX_Matrix GetWindowMatrix(void* pAttachedData) = 0; +}; + +class IPWL_FocusHandler { + public: + virtual ~IPWL_FocusHandler() {} + virtual void OnSetFocus(CPWL_Edit* pEdit) = 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 + 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 + void* pAttachedData; // optional + CPWL_Wnd* pParentWnd; // ignore + CPWL_MsgControl* pMsgControl; // ignore + int32_t eCursorType; // ignore + CFX_Matrix mtChild; // ignore +}; + +class CPWL_Wnd : public CPWL_TimerHandler, public CFX_Observable { + 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 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(); + virtual void SetVisible(bool bVisible); + virtual void SetFontSize(float fFontSize); + virtual float GetFontSize() const; + + virtual CFX_WideString GetSelectedText(); + virtual void DeleteSelectedText(); + 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); + + 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; + 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 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 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; + + 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, 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 m_Children; + PWL_CREATEPARAM m_sPrivateParam; + CFX_UnownedPtr 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_ -- cgit v1.2.3