Browse Source

PDFTool(Android) - 完善安全功能

liuxiaolong 1 year ago
parent
commit
e91ab1d185
48 changed files with 3279 additions and 713 deletions
  1. 55 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CFileUtils.java
  2. 0 13
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/window/CModeSwitchDialogFragment.java
  3. 1 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/directory/CFileDirectoryDialog.java
  4. 3 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/pdfstyle/CAnnotStyle.java
  5. 5 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/pdfstyle/CStyleFragmentDatas.java
  6. 5 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/pdfstyle/CStyleType.java
  7. 1 5
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPreviewMode.java
  8. 0 137
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/CSecurityToolBar.java
  9. 111 65
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/encryption/CDocumentEncryptionDialog.java
  10. 112 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/encryption/CEncryptAlgorithmSpinnerAdapter.java
  11. 15 2
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/encryption/CInputOwnerPwdDialog.java
  12. 0 128
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/encryption/CInputSaveNameDialog.java
  13. 166 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/CWatermarkEditDialog.java
  14. 66 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/CWatermarkToolBar.java
  15. 200 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/bean/WatermarkInfo.java
  16. 177 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/pdfproperties/CWatermarkTextStyleFragment.java
  17. 335 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/view/CWatermarkPageView.java
  18. 1126 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/view/WatermarkView.java
  19. 32 0
      ComPDFKit_Tools/src/main/res/drawable/ic_watermark_zoom.xml
  20. 7 0
      ComPDFKit_Tools/src/main/res/drawable/selector_radiobutton.xml
  21. 5 0
      ComPDFKit_Tools/src/main/res/drawable/tools_btn_eyes_visible_selector.xml
  22. 17 4
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_baseline_folder.xml
  23. 10 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_btn_eyes_invisible.xml
  24. 10 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_btn_eyes_visible.xml
  25. 13 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_watermark_control.xml
  26. 10 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_watermark_location_bottom.xml
  27. 10 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_watermark_location_top.xml
  28. 10 0
      ComPDFKit_Tools/src/main/res/drawable/tools_mode_switch_digital_signature.xml
  29. 5 0
      ComPDFKit_Tools/src/main/res/drawable/tools_selector_radiobutton_color.xml
  30. 18 5
      ComPDFKit_Tools/src/main/res/layout/tools_bota_bookmark_input_dialog.xml
  31. 248 198
      ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_document_encryption_dialog.xml
  32. 33 4
      ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_input_owner_pwd_dialog.xml
  33. 0 87
      ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_save_dialog.xml
  34. 49 0
      ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_watermark_edit_dialog.xml
  35. 35 0
      ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_watermark_page_fragment.xml
  36. 152 0
      ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_watermark_text_style_fragment.xml
  37. 129 0
      ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_watermark_tool_bar.xml
  38. 11 7
      ComPDFKit_Tools/src/main/res/layout/tools_file_directory_dialog.xml
  39. 4 12
      ComPDFKit_Tools/src/main/res/layout/tools_file_directory_list_item.xml
  40. 2 2
      ComPDFKit_Tools/src/main/res/layout/tools_file_directory_list_title_item.xml
  41. 1 1
      ComPDFKit_Tools/src/main/res/layout/tools_file_directory_list_title_separator_item.xml
  42. 1 9
      ComPDFKit_Tools/src/main/res/layout/tools_pdf_mode_switch_dialog_fragment.xml
  43. 23 1
      ComPDFKit_Tools/src/main/res/values/tools_attrs.xml
  44. 1 1
      ComPDFKit_Tools/src/main/res/values/tools_colors.xml
  45. 16 2
      ComPDFKit_Tools/src/main/res/values/tools_strings.xml
  46. 0 13
      PDFViewer/src/main/java/com/compdfkit/pdfviewer/CSampleScreenManager.java
  47. 49 10
      PDFViewer/src/main/java/com/compdfkit/pdfviewer/MainActivity.java
  48. 0 6
      PDFViewer/src/main/res/layout/pdf_sample_activity.xml

+ 55 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CFileUtils.java

@@ -362,4 +362,59 @@ public class CFileUtils {
         return filePath;
     }
 
+
+    public static String getFileNameNoExtension(final File file) {
+        if (file == null) {
+            return null;
+        }
+        return getFileNameNoExtension(file.getPath());
+    }
+    public static String getFileNameNoExtension(final String filePath) {
+        if (isSpace(filePath)) {
+            return filePath;
+        }
+        int lastPoi = filePath.lastIndexOf('.');
+        int lastSep = filePath.lastIndexOf(File.separator);
+        if (lastSep == -1) {
+            return (lastPoi == -1 ? filePath : filePath.substring(0, lastPoi));
+        }
+        if (lastPoi == -1 || lastSep > lastPoi) {
+            return filePath.substring(lastSep + 1);
+        }
+        return filePath.substring(lastSep + 1, lastPoi);
+    }
+
+    public static File renameNameSuffix(File file) {
+        if (file.exists()) {
+            String fileNameNotExtension = getFileNameNoExtension(file);
+            String extension = getFileExtension(file);
+
+            int index = 1;
+            File destFile;
+            do {
+                destFile = new File(file.getParentFile(), fileNameNotExtension + "(" + index++ + ")." + extension);
+            } while (destFile.exists());
+            return destFile;
+        }
+        return file;
+    }
+
+    public static String getFileExtension(final File file) {
+        if (file == null) {
+            return null;
+        }
+        return getFileExtension(file.getPath());
+    }
+
+    public static String getFileExtension(final String filePath) {
+        if (isSpace(filePath)) {
+            return filePath;
+        }
+        int lastPoi = filePath.lastIndexOf('.');
+        int lastSep = filePath.lastIndexOf(File.separator);
+        if (lastPoi == -1 || lastSep >= lastPoi) {
+            return "";
+        }
+        return filePath.substring(lastPoi + 1);
+    }
 }

+ 0 - 13
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/window/CModeSwitchDialogFragment.java

@@ -41,8 +41,6 @@ public class CModeSwitchDialogFragment extends CBasicBottomSheetDialogFragment
 
     private RadioButton rbSignature;
 
-    private RadioButton rbSecurity;
-
     private LinkedHashSet<CPreviewMode> previewModes = new LinkedHashSet<>();
 
     private CPreviewMode selectMode;
@@ -94,7 +92,6 @@ public class CModeSwitchDialogFragment extends CBasicBottomSheetDialogFragment
         rbForm = rootView.findViewById(R.id.r_btn_form_mode);
         rbPageEdit = rootView.findViewById(R.id.r_btn_page_edit_mode);
         rbSignature = rootView.findViewById(R.id.r_btn_signature_mode);
-        rbSecurity = rootView.findViewById(R.id.r_btn_security_mode);
     }
 
     @Override
@@ -140,9 +137,6 @@ public class CModeSwitchDialogFragment extends CBasicBottomSheetDialogFragment
             case Signature:
                 rbSignature.setChecked(true);
                 break;
-            case Security:
-                rbSecurity.setChecked(true);
-                break;
             default:break;
         }
         modifyPopupMenuStatus();
@@ -152,7 +146,6 @@ public class CModeSwitchDialogFragment extends CBasicBottomSheetDialogFragment
         rbForm.setOnClickListener(this);
         rbPageEdit.setOnClickListener(this);
         rbSignature.setOnClickListener(this);
-        rbSecurity.setOnClickListener(this);
     }
 
     @Override
@@ -175,9 +168,6 @@ public class CModeSwitchDialogFragment extends CBasicBottomSheetDialogFragment
         } else if (v.getId() == R.id.r_btn_signature_mode){
             rbSignature.setChecked(true);
             changeMode(CPreviewMode.Signature);
-        } else if (v.getId() == R.id.r_btn_security_mode){
-            rbSecurity.setChecked(true);
-            changeMode(CPreviewMode.Security);
         }
         dismiss();
     }
@@ -202,9 +192,6 @@ public class CModeSwitchDialogFragment extends CBasicBottomSheetDialogFragment
         if (rbSignature != null) {
             rbSignature.setVisibility(previewModes.contains(CPreviewMode.Signature) ? View.VISIBLE : View.GONE);
         }
-        if (rbSecurity != null){
-            rbSecurity.setVisibility(previewModes.contains(CPreviewMode.Security) ? View.VISIBLE : View.GONE);
-        }
     }
 
 

+ 1 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/directory/CFileDirectoryDialog.java

@@ -17,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView;
 
 import com.compdfkit.tools.R;
 import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.CPermissionUtil;
 import com.compdfkit.tools.common.utils.threadpools.SimpleBackgroundTask;
 import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
 import com.compdfkit.tools.common.views.CToolBar;

+ 3 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/pdfstyle/CAnnotStyle.java

@@ -593,6 +593,9 @@ public class CAnnotStyle implements Serializable {
             case FORM_PUSH_BUTTON:
                 titleResId = R.string.tools_push_button;
                 break;
+            case WATERMARK_TEXT:
+                titleResId = R.string.tools_watermark;
+                break;
             default:
                 titleResId = 0;
                 break;

+ 5 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/pdfstyle/CStyleFragmentDatas.java

@@ -32,6 +32,7 @@ import com.compdfkit.tools.forms.pdfproperties.pdflistbox.CListBoxStyleFragment;
 import com.compdfkit.tools.forms.pdfproperties.pdfpushbutton.CPushButtonStyleFragment;
 import com.compdfkit.tools.forms.pdfproperties.pdfradiobutton.CRadioButtonStyleFragment;
 import com.compdfkit.tools.forms.pdfproperties.pdftextfield.CTextFieldStyleFragment;
+import com.compdfkit.tools.security.watermark.pdfproperties.CWatermarkTextStyleFragment;
 
 
 public class CStyleFragmentDatas {
@@ -77,6 +78,10 @@ public class CStyleFragmentDatas {
                 return new CPropertiesFragmentBean(style.getAnnotTypeTitleResId(), ComboBoxStyleFragment.class);
             case FORM_PUSH_BUTTON:
                 return new CPropertiesFragmentBean(style.getAnnotTypeTitleResId(), CPushButtonStyleFragment.class);
+            case WATERMARK_TEXT:
+                return new CPropertiesFragmentBean(style.getAnnotTypeTitleResId(), CWatermarkTextStyleFragment.class);
+            case WATERMARK_IMAGE:
+                return null;
             default:
                 break;
         }

+ 5 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/pdfstyle/CStyleType.java

@@ -38,6 +38,10 @@ public enum CStyleType {
     FORM_COMBO_BOX,
     FORM_LIST_BOX,
     FORM_SIGNATURE_FIELDS,
-    FORM_UNKNOWN
+    FORM_UNKNOWN,
+
+    WATERMARK_TEXT,
+
+    WATERMARK_IMAGE;
 
 }

+ 1 - 5
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPreviewMode.java

@@ -9,9 +9,7 @@ public enum CPreviewMode {
     Form,
     PageEdit,
 
-    Signature,
-
-    Security;
+    Signature;
 
     public int getTitleByMode() {
         switch (this) {
@@ -25,8 +23,6 @@ public enum CPreviewMode {
                 return R.string.tools_form_mode;
             case Signature:
                 return R.string.tools_digital_signature;
-            case Security:
-                return R.string.tools_security;
             default:
                 return R.string.tools_pdf_viewer_mode;
         }

+ 0 - 137
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/CSecurityToolBar.java

@@ -1,137 +0,0 @@
-/**
- * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
- * <p>
- * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
- * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
- * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
- * This notice may not be removed from this file.
- */
-
-package com.compdfkit.tools.security;
-
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
-import androidx.constraintlayout.widget.ConstraintLayout;
-import androidx.fragment.app.FragmentActivity;
-
-import com.compdfkit.core.document.CPDFDocument;
-import com.compdfkit.tools.R;
-import com.compdfkit.tools.common.utils.CToastUtil;
-import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
-import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
-import com.compdfkit.tools.security.encryption.CDocumentEncryptionDialog;
-import com.compdfkit.tools.security.encryption.CInputOwnerPwdDialog;
-
-public class CSecurityToolBar extends FrameLayout {
-
-    private ConstraintLayout clAddSecurity;
-
-    private ConstraintLayout clAddWatermark;
-
-    private CPDFViewCtrl pdfView;
-
-    public void initWithPDFView(CPDFViewCtrl pdfView) {
-        this.pdfView = pdfView;
-    }
-
-    public CSecurityToolBar(@NonNull Context context) {
-        this(context, null);
-    }
-
-    public CSecurityToolBar(@NonNull Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CSecurityToolBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        initView(context);
-    }
-
-    private void initView(Context context) {
-        inflate(context, R.layout.tools_cpdf_security_tool_bar, this);
-        clAddSecurity = findViewById(R.id.cl_add_security);
-        clAddWatermark = findViewById(R.id.cl_add_watermark);
-        clAddSecurity.setOnClickListener(v -> {
-            if (pdfView.getCPdfReaderView().getPDFDocument() == null) {
-                return;
-            }
-            CPDFDocument.PDFDocumentPermissions permissions = pdfView.getCPdfReaderView().getPDFDocument().getPermissions();
-            CToastUtil.showLongToast(getContext(), permissions.name());
-            if (permissions == CPDFDocument.PDFDocumentPermissions.PDFDocumentPermissionsUser) {
-                // The current document does not have owner permissions.
-                // A pop-up window will appear prompting the user to enter owner permissions.
-                CInputOwnerPwdDialog ownerPwdDialog = CInputOwnerPwdDialog.newInstance();
-                ownerPwdDialog.setDocument(pdfView.getCPdfReaderView().getPDFDocument());
-                ownerPwdDialog.setCancelClickListener(view -> {
-                    ownerPwdDialog.dismiss();
-                });
-                ownerPwdDialog.setConfirmClickListener(password -> {
-                    // Reload the document using the owner password
-                    CPDFDocument.PDFDocumentError reloadResult = pdfView.getCPdfReaderView().getPDFDocument().reload(password);
-                    if (reloadResult == CPDFDocument.PDFDocumentError.PDFDocumentErrorSuccess) {
-                        // reload success
-                        CPDFDocument.PDFDocumentPermissions permissions1 = pdfView.getCPdfReaderView().getPDFDocument().getPermissions();
-                        CToastUtil.showLongToast(getContext(), permissions1.name());
-                        showSettingEncryptionDialog();
-                    }
-                    ownerPwdDialog.dismiss();
-                });
-                ownerPwdDialog.show(((FragmentActivity) pdfView.getCPdfReaderView().getContext()).getSupportFragmentManager(), "inputOwnerPwdDialog");
-            } else {
-                showSettingEncryptionDialog();
-            }
-
-        });
-        clAddWatermark.setOnClickListener(v -> {
-
-        });
-    }
-
-    private void showSettingEncryptionDialog() {
-        CDocumentEncryptionDialog documentEncryptionDialog = CDocumentEncryptionDialog.newInstance();
-        documentEncryptionDialog.setDocument(pdfView.getCPdfReaderView().getPDFDocument());
-        documentEncryptionDialog.setEncryptionResultListener((isRemoveSecurity, result, filePath, passowrd) -> {
-            documentEncryptionDialog.dismiss();
-            if (isRemoveSecurity) {
-                showResultTips(result ? R.string.tools_password_remove_success : R.string.tools_password_remove_fail);
-                pdfView.getCPdfReaderView().getPDFDocument().reload();
-            } else {
-                showResultTips(result ? R.string.tools_set_password_successfully : R.string.tools_set_password_failures);
-                pdfView.openPDF(filePath, passowrd);
-            }
-        });
-        if (pdfView.getCPdfReaderView().getContext() instanceof FragmentActivity) {
-            documentEncryptionDialog.show(((FragmentActivity) pdfView.getCPdfReaderView().getContext()).getSupportFragmentManager(), "documentEncryption");
-        }
-    }
-
-    /**
-     * Show pdf document saved results
-     */
-    private void showResultTips(@StringRes int tipsMessage) {
-        CAlertDialog alertDialog = CAlertDialog.newInstance("", getContext().getString(tipsMessage));
-        alertDialog.setCancelable(false);
-        alertDialog.setConfirmClickListener(v -> alertDialog.dismiss());
-        alertDialog.show(((FragmentActivity) pdfView.getCPdfReaderView().getContext()).getSupportFragmentManager(), "documentEncryption");
-    }
-
-    public View getAddSecurityButton() {
-        return clAddSecurity;
-    }
-
-    public ConstraintLayout getAddWatermarkButton() {
-        return clAddWatermark;
-    }
-
-    public void reset() {
-        clAddSecurity.setSelected(false);
-        clAddWatermark.setSelected(false);
-    }
-}

+ 111 - 65
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/encryption/CDocumentEncryptionDialog.java

@@ -1,33 +1,41 @@
 package com.compdfkit.tools.security.encryption;
 
+import android.Manifest;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.text.Editable;
+import android.text.InputType;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.view.View;
+import android.widget.AdapterView;
 import android.widget.CompoundButton;
+import android.widget.Spinner;
 import android.widget.Switch;
 import android.widget.TextView;
 
 import androidx.appcompat.widget.AppCompatButton;
 import androidx.appcompat.widget.AppCompatCheckBox;
 import androidx.appcompat.widget.AppCompatEditText;
+import androidx.appcompat.widget.AppCompatImageView;
 import androidx.appcompat.widget.AppCompatTextView;
 import androidx.core.content.ContextCompat;
 
-import com.compdfkit.core.common.CPDFDocumentException;
 import com.compdfkit.core.document.CPDFDocument;
 import com.compdfkit.core.document.CPDFDocumentPermissionInfo;
 import com.compdfkit.tools.R;
 import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
 import com.compdfkit.tools.common.utils.CFileUtils;
-import com.compdfkit.tools.common.utils.CLog;
+import com.compdfkit.tools.common.utils.CPermissionUtil;
 import com.compdfkit.tools.common.utils.CToastUtil;
-import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
+import com.compdfkit.tools.common.utils.activitycontracts.CMultiplePermissionResultLauncher;
 import com.compdfkit.tools.common.utils.threadpools.CThreadPoolUtils;
 import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
 import com.compdfkit.tools.common.views.CToolBar;
+import com.compdfkit.tools.common.views.directory.CFileDirectoryDialog;
+
+import java.io.File;
 
 /**
  * Document encryption related settings dialog
@@ -50,18 +58,24 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
 
     private AppCompatTextView tvEncryptsFollowsFunctions;
 
-    private AppCompatCheckBox cbPrint;
+    private AppCompatCheckBox cbRestrictPrint;
+
+    private AppCompatCheckBox cbRestrictCopy;
 
-    private AppCompatCheckBox cbCopy;
+    private AppCompatImageView ivUserPwdVisible;
 
-    private AppCompatTextView tvLevelTitle;
+    private AppCompatImageView ivOwnerPwdVisible;
 
-    private AppCompatTextView tvLevelValue;
+    private Spinner levelSpinner;
+
+    private CEncryptAlgorithmSpinnerAdapter algorithmSpinnerAdapter;
 
     private CPDFDocument document;
 
     private CEncryptionResultListener encryptionResultListener;
 
+    protected CMultiplePermissionResultLauncher multiplePermissionResultLauncher = new CMultiplePermissionResultLauncher(this);
+
     public void setDocument(CPDFDocument document) {
         this.document = document;
     }
@@ -102,19 +116,22 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
         swOwnerPassword = rootView.findViewById(R.id.sw_setting_permission_password);
         etOwnerPassword = rootView.findViewById(R.id.et_owner_password);
         tvEncryptsFollowsFunctions = rootView.findViewById(R.id.tv_owner_functions);
-        cbPrint = rootView.findViewById(R.id.cb_print);
-        cbCopy = rootView.findViewById(R.id.cb_copy);
-        tvLevelTitle = rootView.findViewById(R.id.tv_cryptographic_level);
-        tvLevelValue = rootView.findViewById(R.id.tv_cryptographic_level_value);
+        cbRestrictPrint = rootView.findViewById(R.id.cb_print);
+        cbRestrictCopy = rootView.findViewById(R.id.cb_copy);
+        levelSpinner = rootView.findViewById(R.id.spinner_cryptographic_level);
+        ivUserPwdVisible = rootView.findViewById(R.id.iv_user_pwd_show);
+        ivOwnerPwdVisible = rootView.findViewById(R.id.iv_owner_pwd_show);
     }
 
     @Override
     protected void onViewCreate() {
         initPermissionInfo();
-        toolBar.setOnClickListener(this);
+        toolBar.setBackBtnClickListener(this);
         btnDone.setOnClickListener(this);
-        swUserPassword.setOnCheckedChangeListener(this::onCheckedChanged);
-        swOwnerPassword.setOnCheckedChangeListener(this::onCheckedChanged);
+        ivUserPwdVisible.setOnClickListener(this);
+        ivOwnerPwdVisible.setOnClickListener(this);
+        swUserPassword.setOnCheckedChangeListener(this);
+        swOwnerPassword.setOnCheckedChangeListener(this);
         etOwnerPassword.addTextChangedListener(new TextWatcher() {
             @Override
             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@@ -130,6 +147,20 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
             @Override
             public void afterTextChanged(Editable s) {
 
+            }
+        });
+        algorithmSpinnerAdapter = new CEncryptAlgorithmSpinnerAdapter(getContext());
+        levelSpinner.setAdapter(algorithmSpinnerAdapter);
+
+        levelSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                algorithmSpinnerAdapter.setSelectEncrypt(algorithmSpinnerAdapter.list.get(position));
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+
             }
         });
     }
@@ -138,6 +169,7 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
         if (buttonView.getId() == swUserPassword.getId()) {
             setTextViewEnable(etUserPassword, isChecked);
+            ivUserPwdVisible.setEnabled(isChecked);
             if (isChecked) {
                 CViewUtils.showKeyboard(etUserPassword);
             } else {
@@ -145,6 +177,7 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
             }
         } else if (buttonView.getId() == swOwnerPassword.getId()) {
             setTextViewEnable(etOwnerPassword, isChecked);
+            ivOwnerPwdVisible.setEnabled(isChecked);
             updateEnablePermissionInfo();
             if (isChecked) {
                 CViewUtils.showKeyboard(etOwnerPassword);
@@ -159,35 +192,52 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
         if (v.getId() == toolBar.getIvToolBarBackBtn().getId()) {
             dismiss();
         } else if (v.getId() == R.id.btn_done) {
-            if (!swUserPassword.isChecked() && !swOwnerPassword.isChecked()){
-                encryptionDocument(null);
+            if (swUserPassword.isChecked() && TextUtils.isEmpty(etUserPassword.getText())){
+                CToastUtil.showLongToast(getContext(), R.string.tools_enter_password_can_not_be_empty);
+                return;
+            }
+            if (swOwnerPassword.isChecked() && TextUtils.isEmpty(etOwnerPassword.getText())){
+                CToastUtil.showLongToast(getContext(), R.string.tools_enter_password_can_not_be_empty);
                 return;
             }
-            CInputSaveNameDialog dialog = CInputSaveNameDialog.newInstance(document.getFileName());
-            dialog.setCancelClickListener(view -> {
-                dialog.dismiss();
-            });
-            dialog.setConfirmClickListener((filePath) -> {
-                encryptionDocument(filePath);
-                dialog.dismiss();
-            });
-            dialog.show(getChildFragmentManager(), "dialog");
+
+            // Check the storage permissions to ensure that
+            // you can select the directory and save to the corresponding directory normally.
+            if (CPermissionUtil.hasStoragePermissions(getContext())) {
+                showSelectDirDialog();
+            }else {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+                    CPermissionUtil.openManageAllFileAppSettings(getContext());
+                } else {
+                    multiplePermissionResultLauncher.launch(CPermissionUtil.STORAGE_PERMISSIONS, result -> {
+                        if (CPermissionUtil.hasStoragePermissions(getContext())) {
+                            showSelectDirDialog();
+                        } else {
+                            if (!CPermissionUtil.shouldShowRequestPermissionRationale(requireActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+                                CPermissionUtil.showPermissionsRequiredDialog(getChildFragmentManager(), getContext());
+                            }
+                        }
+                    });
+                }
+            }
+        } else if (v.getId() == R.id.iv_user_pwd_show) {
+            ivUserPwdVisible.setSelected(!ivUserPwdVisible.isSelected());
+            etUserPassword.setInputType(ivUserPwdVisible.isSelected() ? InputType.TYPE_CLASS_TEXT : InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+            etUserPassword.setSelection(etUserPassword.getText().length());
+        } else if (v.getId() == R.id.iv_owner_pwd_show) {
+            ivOwnerPwdVisible.setSelected(!ivOwnerPwdVisible.isSelected());
+            etOwnerPassword.setInputType(ivOwnerPwdVisible.isSelected() ? InputType.TYPE_CLASS_TEXT : InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+            etOwnerPassword.setSelection(etOwnerPassword.getText().length());
         }
     }
 
-    private void initPermissionInfo(){
+    private void initPermissionInfo() {
         if (document.getPermissions() == CPDFDocument.PDFDocumentPermissions.PDFDocumentPermissionsOwner) {
             swOwnerPassword.setChecked(true);
             etOwnerPassword.setEnabled(true);
             swUserPassword.setChecked(true);
             etUserPassword.setEnabled(true);
-            CPDFDocumentPermissionInfo permissionInfo = document.getPermissionsInfo();
-            if (permissionInfo != null) {
-                cbPrint.setChecked(permissionInfo.isAllowsPrinting());
-                cbCopy.setChecked(permissionInfo.isAllowsCopying());
-            }
         }
-        setLevelValue();
     }
 
     private void setTextViewEnable(TextView textView, boolean enable) {
@@ -197,41 +247,34 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
 
     private void updateEnablePermissionInfo() {
         boolean enable = swOwnerPassword.isChecked() && !TextUtils.isEmpty(etOwnerPassword.getText());
-        cbCopy.setEnabled(enable);
-        cbPrint.setEnabled(enable);
+        cbRestrictCopy.setEnabled(enable);
+        cbRestrictPrint.setEnabled(enable);
         if (!enable) {
-            cbCopy.setChecked(false);
-            cbPrint.setChecked(false);
+            cbRestrictCopy.setChecked(false);
+            cbRestrictPrint.setChecked(false);
         }
         setTextViewEnable(tvEncryptsFollowsFunctions, enable);
-        setTextViewEnable(cbCopy, enable);
-        setTextViewEnable(cbPrint, enable);
+        setTextViewEnable(cbRestrictCopy, enable);
+        setTextViewEnable(cbRestrictPrint, enable);
     }
 
-    private void setLevelValue(){
-        tvLevelValue.setText(getEncryptAlgorithmStr());
+    private void showSelectDirDialog(){
+        // Display the system folder directory and select a directory to save.
+        String rootDir = Environment.getExternalStorageDirectory().getAbsolutePath();
+        CFileDirectoryDialog directoryDialog = CFileDirectoryDialog.newInstance(rootDir, "", getString(R.string.tools_save_to_this_directory));
+        directoryDialog.setSelectFolderListener(dir -> {
+            File file = new File(dir, document.getFileName());
+            encryptionDocument(CFileUtils.renameNameSuffix(file).getAbsolutePath());
+        });
+        directoryDialog.show(getParentFragmentManager(), "dirDialog");
     }
 
-    private String getEncryptAlgorithmStr(){
-        switch (document.getEncryptAlgorithm()){
-            case PDFDocumentRC4:
-                return getString(R.string.tools_encryption_rc4);
-            case PDFDocumentAES128:
-                return getString(R.string.tools_encryption_128_aes);
-            case PDFDocumentAES256:
-                return getString(R.string.tools_encryption_256_aes);
-            case PDFDocumentNoEncryptAlgo:
-                return getString(R.string.tools_encryption_128_aes);
-            default:
-                return getString(R.string.tools_encryption_128_aes);
-        }
-    }
 
     private void encryptionDocument(String filePath) {
         if (document == null) {
             return;
         }
-        CThreadPoolUtils.getInstance().executeIO(()->{
+        CThreadPoolUtils.getInstance().executeIO(() -> {
             boolean removeUserPassword = false;
             boolean removeOwnerPassword = false;
             String userPassword = etUserPassword.getText().toString();
@@ -242,10 +285,13 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
                     // add user password
                     if (!TextUtils.isEmpty(userPassword)) {
                         document.setUserPassword(userPassword);
+                    }else {
+                        removeUserPassword = true;
+                        document.setUserPassword("");
                     }
                 } else {
-                    if (permissions== CPDFDocument.PDFDocumentPermissions.PDFDocumentPermissionsUser ||
-                    !TextUtils.isEmpty(document.getPassword())){
+                    if (permissions == CPDFDocument.PDFDocumentPermissions.PDFDocumentPermissionsUser ||
+                            !TextUtils.isEmpty(document.getPassword())) {
                         // remove user password
                         removeUserPassword = true;
                         document.setUserPassword("");
@@ -253,29 +299,29 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
                 }
                 if (swOwnerPassword.isChecked() && !TextUtils.isEmpty(ownerPassword)) {
                     CPDFDocumentPermissionInfo permissionInfo = document.getPermissionsInfo();
-                    permissionInfo.setAllowsPrinting(cbPrint.isChecked());
-                    permissionInfo.setAllowsCopying(cbCopy.isChecked());
+                    permissionInfo.setAllowsPrinting(!cbRestrictPrint.isChecked());
+                    permissionInfo.setAllowsCopying(!cbRestrictCopy.isChecked());
                     document.setPermissionsInfo(permissionInfo);
                     document.setOwnerPassword(ownerPassword);
                 } else {
-                    if ( permissions == CPDFDocument.PDFDocumentPermissions.PDFDocumentPermissionsOwner) {
+                    if (permissions == CPDFDocument.PDFDocumentPermissions.PDFDocumentPermissionsOwner) {
                         removeOwnerPassword = true;
                         document.setOwnerPassword("");
                     }
                 }
-                document.setEncryptAlgorithm(CPDFDocument.PDFDocumentEncryptAlgo.PDFDocumentRC4);
+                document.setEncryptAlgorithm(algorithmSpinnerAdapter.getSelectEncryptAlgo());
                 boolean result;
                 boolean isRemoveSecurity = removeUserPassword && removeOwnerPassword;
                 if (isRemoveSecurity) {
                     // remove security
-                    result = document.save(CPDFDocument.PDFDocumentSaveType.PDFDocumentSaveRemoveSecurity);
+                    result = document.saveAs(filePath, true);
                 } else {
                     // Save to specified directory
                     result = document.saveAs(filePath, false);
                 }
                 document.close();
                 if (getActivity() != null) {
-                    getActivity().runOnUiThread(()->{
+                    getActivity().runOnUiThread(() -> {
                         if (encryptionResultListener != null) {
                             encryptionResultListener.result(isRemoveSecurity,
                                     result,
@@ -288,14 +334,14 @@ public class CDocumentEncryptionDialog extends CBasicBottomSheetDialogFragment i
                 exception.printStackTrace();
             }
         });
-
     }
 
+
     public void setEncryptionResultListener(CEncryptionResultListener encryptionResultListener) {
         this.encryptionResultListener = encryptionResultListener;
     }
 
-    public interface CEncryptionResultListener{
+    public interface CEncryptionResultListener {
         void result(boolean isRemoveSecurity, boolean result, String filePath, String password);
     }
 }

+ 112 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/encryption/CEncryptAlgorithmSpinnerAdapter.java

@@ -0,0 +1,112 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.tools.security.encryption;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.AppCompatTextView;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.tools.R;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+
+public class CEncryptAlgorithmSpinnerAdapter extends BaseAdapter {
+
+    public List<CPDFDocument.PDFDocumentEncryptAlgo> list;
+
+    private Context mContext;
+
+    private CPDFDocument.PDFDocumentEncryptAlgo encryptAlgo;
+
+    public CEncryptAlgorithmSpinnerAdapter(@NonNull Context context) {
+        encryptAlgo = CPDFDocument.PDFDocumentEncryptAlgo.PDFDocumentRC4;
+        this.list = Arrays.asList(CPDFDocument.PDFDocumentEncryptAlgo.PDFDocumentRC4,
+                CPDFDocument.PDFDocumentEncryptAlgo.PDFDocumentAES128,
+                CPDFDocument.PDFDocumentEncryptAlgo.PDFDocumentAES256);
+        mContext = context;
+    }
+
+    public void setSelectEncrypt(CPDFDocument.PDFDocumentEncryptAlgo encryptAlgo) {
+        this.encryptAlgo = encryptAlgo;
+    }
+
+    public int getSelectEncryptAlgoIndex(){
+        if (encryptAlgo != null){
+            for (int i = 0; i < list.size(); i++) {
+                CPDFDocument.PDFDocumentEncryptAlgo item = list.get(i);
+                if (encryptAlgo.equals(item)) {
+                    return i;
+                }
+            }
+        }
+        return 0;
+    }
+
+    public CPDFDocument.PDFDocumentEncryptAlgo getSelectEncryptAlgo(){
+        if (encryptAlgo != null){
+            return encryptAlgo;
+        }
+        return CPDFDocument.PDFDocumentEncryptAlgo.PDFDocumentRC4;
+    }
+
+    @Override
+    public int getCount() {
+        return list.size();
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return list.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        convertView = inflater.inflate(R.layout.tools_spinner_list_item, null);
+        if (convertView != null){
+            AppCompatTextView textView = convertView.findViewById(R.id.tv_menu_title);
+            CPDFDocument.PDFDocumentEncryptAlgo item = list.get(position);
+            textView.setText(getEncryptAlgorithmStr(textView.getContext(), item));
+            textView.setTypeface(encryptAlgo != null && encryptAlgo == item ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
+        }
+        return convertView;
+    }
+
+
+    private String getEncryptAlgorithmStr(Context context, CPDFDocument.PDFDocumentEncryptAlgo encryptAlgo){
+        switch (encryptAlgo){
+            case PDFDocumentRC4:
+                return context.getString(R.string.tools_encryption_rc4);
+            case PDFDocumentAES128:
+                return context.getString(R.string.tools_encryption_128_aes);
+            case PDFDocumentAES256:
+                return context.getString(R.string.tools_encryption_256_aes);
+            case PDFDocumentNoEncryptAlgo:
+                return context.getString(R.string.tools_encryption_128_aes);
+            default:
+                return context.getString(R.string.tools_encryption_128_aes);
+        }
+    }
+}

+ 15 - 2
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/encryption/CInputOwnerPwdDialog.java

@@ -3,6 +3,7 @@ package com.compdfkit.tools.security.encryption;
 import android.os.Bundle;
 import android.os.Environment;
 import android.text.Editable;
+import android.text.InputType;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.view.LayoutInflater;
@@ -13,6 +14,7 @@ import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.appcompat.widget.AppCompatButton;
 import androidx.appcompat.widget.AppCompatEditText;
+import androidx.appcompat.widget.AppCompatImageView;
 import androidx.appcompat.widget.AppCompatTextView;
 import androidx.fragment.app.DialogFragment;
 
@@ -39,6 +41,10 @@ public class CInputOwnerPwdDialog extends DialogFragment {
 
     private CPDFDocument document;
 
+    private AppCompatImageView ivPasswordVisible;
+
+    private AppCompatTextView tvPasswordError;
+
     public void setDocument(CPDFDocument document) {
         this.document = document;
     }
@@ -63,10 +69,11 @@ public class CInputOwnerPwdDialog extends DialogFragment {
             getDialog().getWindow().setBackgroundDrawableResource(R.drawable.tools_dialog_background);
         }
         View rootView = inflater.inflate(R.layout.tools_cpdf_security_input_owner_pwd_dialog, container, false);
-        AppCompatTextView tvTitle = rootView.findViewById(R.id.tv_title);
         etPassword = rootView.findViewById(R.id.et_password);
         btnCancel = rootView.findViewById(R.id.btn_cancel);
         btnConfirm = rootView.findViewById(R.id.btn_confirm);
+        ivPasswordVisible = rootView.findViewById(R.id.iv_input_visible);
+        tvPasswordError = rootView.findViewById(R.id.tv_pwd_error);
         return rootView;
     }
 
@@ -81,7 +88,7 @@ public class CInputOwnerPwdDialog extends DialogFragment {
                 if (document.checkOwnerPassword(password)) {
                     ownerPasswordListener.result(password);
                 }else {
-                    CToastUtil.showLongToast(getContext(), R.string.tools_invalid_password);
+                    tvPasswordError.setVisibility(View.VISIBLE);
                 }
             }
         });
@@ -93,6 +100,7 @@ public class CInputOwnerPwdDialog extends DialogFragment {
 
             @Override
             public void onTextChanged(CharSequence s, int start, int before, int count) {
+                tvPasswordError.setVisibility(View.INVISIBLE);
                 btnConfirm.setEnabled(!TextUtils.isEmpty(s));
             }
 
@@ -101,6 +109,11 @@ public class CInputOwnerPwdDialog extends DialogFragment {
 
             }
         });
+        ivPasswordVisible.setOnClickListener(v -> {
+            ivPasswordVisible.setSelected(!ivPasswordVisible.isSelected());
+            etPassword.setInputType(ivPasswordVisible.isSelected() ? InputType.TYPE_CLASS_TEXT : InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+            etPassword.setSelection(etPassword.getText().length());
+        });
     }
 
     public void setCancelClickListener(View.OnClickListener cancelListener) {

+ 0 - 128
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/encryption/CInputSaveNameDialog.java

@@ -1,128 +0,0 @@
-package com.compdfkit.tools.security.encryption;
-
-import android.os.Bundle;
-import android.os.Environment;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appcompat.widget.AppCompatButton;
-import androidx.appcompat.widget.AppCompatEditText;
-import androidx.appcompat.widget.AppCompatTextView;
-import androidx.fragment.app.DialogFragment;
-
-import com.compdfkit.tools.R;
-import com.compdfkit.tools.common.utils.CFileUtils;
-import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
-
-import java.io.File;
-
-
-class CInputSaveNameDialog extends DialogFragment {
-
-    private AppCompatTextView tvTitle;
-
-    private AppCompatButton btnCancel;
-
-    private AppCompatButton btnConfirm;
-
-    private AppCompatEditText etFileName;
-
-    private AppCompatTextView tvSaveLocation;
-
-    private View.OnClickListener cancelListener;
-
-    private CSecuritySavePathListener securitySaveInfoListener;
-
-    public static CInputSaveNameDialog newInstance(String fileName) {
-        Bundle args = new Bundle();
-        args.putString("file_name", fileName);
-        CInputSaveNameDialog fragment = new CInputSaveNameDialog();
-        fragment.setArguments(args);
-        return fragment;
-    }
-
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setStyle(STYLE_NO_TITLE, R.style.tools_dialog_theme);
-    }
-
-    @Nullable
-    @Override
-    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
-        if (getDialog() != null && getDialog().getWindow() != null) {
-            getDialog().getWindow().setBackgroundDrawableResource(R.drawable.tools_dialog_background);
-        }
-        View rootView = inflater.inflate(R.layout.tools_cpdf_security_save_dialog, container, false);
-        tvTitle = rootView.findViewById(R.id.tv_title);
-        etFileName = rootView.findViewById(R.id.et_file_name);
-        tvSaveLocation = rootView.findViewById(R.id.tv_save_location);
-        btnCancel = rootView.findViewById(R.id.btn_cancel);
-        btnConfirm = rootView.findViewById(R.id.btn_confirm);
-        return rootView;
-    }
-
-    @Override
-    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        if (getArguments() != null && !TextUtils.isEmpty(getArguments().getString("file_name"))) {
-            String hint = getArguments().getString("file_name");
-            etFileName.setText(hint);
-            CViewUtils.showKeyboard(etFileName);
-            if (hint.endsWith(".pdf") || hint.endsWith(".PDF")) {
-                etFileName.setSelection(0, hint.length() - 4);
-            } else {
-                etFileName.setSelection(0, hint.length());
-            }
-        }
-        tvSaveLocation.setText(getText(R.string.tools_save_location) + "\n" + "Downloads/compdfkit");
-        btnConfirm.setEnabled(!TextUtils.isEmpty(etFileName.getText()));
-        btnCancel.setOnClickListener(cancelListener);
-        btnConfirm.setOnClickListener(v -> {
-            if (securitySaveInfoListener != null && !TextUtils.isEmpty(etFileName.getText())) {
-                File dir = new File(saveDir());
-                dir.mkdirs();
-                securitySaveInfoListener.result(saveDir() + File.separator + etFileName.getText().toString());
-            }
-        });
-        etFileName.addTextChangedListener(new TextWatcher() {
-            @Override
-            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-
-            }
-
-            @Override
-            public void onTextChanged(CharSequence s, int start, int before, int count) {
-                btnConfirm.setEnabled(!TextUtils.isEmpty(s));
-            }
-
-            @Override
-            public void afterTextChanged(Editable s) {
-
-            }
-        });
-    }
-
-    private String saveDir() {
-        //sdcard/Downloads/compdfkit/
-        return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator + CFileUtils.ROOT_FOLDER;
-    }
-
-    public void setCancelClickListener(View.OnClickListener cancelListener) {
-        this.cancelListener = cancelListener;
-    }
-
-    public void setConfirmClickListener(CSecuritySavePathListener securitySaveInfoListener) {
-        this.securitySaveInfoListener = securitySaveInfoListener;
-    }
-
-    public interface CSecuritySavePathListener {
-        void result(String savePath);
-    }
-}

+ 166 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/CWatermarkEditDialog.java

@@ -0,0 +1,166 @@
+package com.compdfkit.tools.security.watermark;
+
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.appcompat.widget.AppCompatButton;
+
+import com.compdfkit.core.annotation.CPDFTextAttribute;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.dialog.CEditDialog;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.common.views.CToolBar;
+import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CAnnotStyle;
+import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CBasicOnStyleChangeListener;
+import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleDialogFragment;
+import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleType;
+import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
+import com.compdfkit.tools.security.watermark.view.CWatermarkPageView;
+
+
+public class CWatermarkEditDialog extends CBasicBottomSheetDialogFragment implements View.OnClickListener {
+
+    private CToolBar toolBar;
+
+    private AppCompatButton btnDone;
+
+    private CWatermarkToolBar watermarkToolBar;
+
+    private CWatermarkPageView watermarkView;
+
+    private CPDFViewCtrl pdfView;
+
+
+    public static CWatermarkEditDialog newInstance() {
+
+        Bundle args = new Bundle();
+
+        CWatermarkEditDialog fragment = new CWatermarkEditDialog();
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public void initWithPDFView(CPDFViewCtrl pdfView) {
+        this.pdfView = pdfView;
+    }
+
+
+    @Override
+    protected boolean draggable() {
+        return false;
+    }
+
+    @Override
+    protected boolean fullScreen() {
+        return true;
+    }
+
+    @Override
+    protected float dimAmount() {
+        return CViewUtils.isLandScape(getContext()) ? 0.2F : 0F;
+    }
+
+    @Override
+    protected int layoutId() {
+        return R.layout.tools_cpdf_security_watermark_edit_dialog;
+    }
+
+    @Override
+    protected void onCreateView(View rootView) {
+        toolBar = rootView.findViewById(R.id.tool_bar);
+        btnDone = rootView.findViewById(R.id.btn_done);
+        watermarkToolBar = rootView.findViewById(R.id.watermark_toolbar);
+        watermarkView = rootView.findViewById(R.id.watermark_view);
+    }
+
+    @Override
+    protected void onViewCreate() {
+        toolBar.setBackBtnClickListener(this::onClick);
+        btnDone.setOnClickListener(this::onClick);
+        watermarkView.setDocument(pdfView.getCPdfReaderView().getPDFDocument(), 0);
+        initWatermarkToolbar();
+    }
+
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == toolBar.getIvToolBarBackBtn().getId()){
+            dismiss();
+        } else if (v.getId() == R.id.btn_done){
+            showWatermarkStyleDialog(CStyleType.WATERMARK_TEXT);
+        }
+    }
+
+    private void initWatermarkToolbar(){
+        watermarkToolBar.setClickAddTextWatermarkListener(v -> {
+            CEditDialog editDialog = CEditDialog.newInstance(getString(R.string.tools_text_watermark), "");
+            editDialog.setEditListener(title -> {
+                editDialog.dismiss();
+            });
+            editDialog.show(getChildFragmentManager(), "inputWatermarkContentDialog");
+        });
+        watermarkToolBar.setClickAddImageWatermarkListener(v -> {
+            watermarkView.createTextWatermark("ComPDFKit");
+        });
+        watermarkToolBar.setClickDeleteWatermarkListener(v -> {
+            watermarkView.applyWatermark(pdfView.getCPdfReaderView().getPDFDocument());
+            pdfView.getCPdfReaderView().reloadPages();
+            dismiss();
+
+        });
+    }
+
+    private void showWatermarkStyleDialog(CStyleType styleType){
+
+        CAnnotStyle annotStyle = new CAnnotStyle(styleType);
+        annotStyle.setFontColor(watermarkView.getTextColor());
+        annotStyle.setFontSize(watermarkView.getTextSize());
+        annotStyle.setTextColorOpacity(watermarkView.getWatermarkOpacity());
+        annotStyle.setFontType(watermarkView.getFontType());
+        annotStyle.setFontBold(watermarkView.isBold());
+        annotStyle.setFontItalic(watermarkView.isItalic());
+
+        CStyleDialogFragment styleDialogFragment = CStyleDialogFragment.newInstance(annotStyle);
+        styleDialogFragment.addAnnotStyleChangeListener(new CBasicOnStyleChangeListener(){
+            @Override
+            public void onChangeTextColor(int textColor) {
+                super.onChangeTextColor(textColor);
+                watermarkView.setTextColor(textColor);
+            }
+
+            @Override
+            public void onChangeTextColorOpacity(int textColorOpacity) {
+                super.onChangeTextColorOpacity(textColorOpacity);
+                watermarkView.setTextColorOpacity(textColorOpacity);
+            }
+
+            @Override
+            public void onChangeFontType(CPDFTextAttribute.FontNameHelper.FontType fontType) {
+                super.onChangeFontType(fontType);
+                watermarkView.setTypeface(fontType, watermarkView.isBold(), watermarkView.isItalic());
+            }
+
+            @Override
+            public void onChangeFontBold(boolean bold) {
+                super.onChangeFontBold(bold);
+                watermarkView.setBold(bold);
+            }
+
+            @Override
+            public void onChangeFontItalic(boolean italic) {
+                super.onChangeFontItalic(italic);
+                watermarkView.setItalic(italic);
+            }
+
+            @Override
+            public void onChangeFontSize(int fontSize) {
+                super.onChangeFontSize(fontSize);
+                watermarkView.setTextSize(fontSize);
+            }
+        });
+        styleDialogFragment.show(getChildFragmentManager(), "styleFragment");
+    }
+
+}

+ 66 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/CWatermarkToolBar.java

@@ -0,0 +1,66 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.tools.security.watermark;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.fragment.app.FragmentActivity;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.tools.R;
+
+public class CWatermarkToolBar extends FrameLayout {
+
+    private ConstraintLayout clAddTextWatermark;
+
+    private ConstraintLayout clAddImageWatermark;
+
+    private ConstraintLayout clDeleteWatermark;
+
+    public CWatermarkToolBar(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CWatermarkToolBar(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CWatermarkToolBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+    }
+
+    private void initView(Context context) {
+        inflate(context, R.layout.tools_cpdf_security_watermark_tool_bar, this);
+        clAddTextWatermark = findViewById(R.id.cl_add_text_watermark);
+        clAddImageWatermark = findViewById(R.id.cl_add_image_watermark);
+        clDeleteWatermark = findViewById(R.id.cl_delete_watermark);
+    }
+
+    public void setClickAddTextWatermarkListener(View.OnClickListener clickListener){
+        clAddTextWatermark.setOnClickListener(clickListener);
+    }
+
+    public void setClickAddImageWatermarkListener(View.OnClickListener clickListener){
+        clAddImageWatermark.setOnClickListener(clickListener);
+    }
+
+    public void setClickDeleteWatermarkListener(View.OnClickListener clickListener){
+        clDeleteWatermark.setOnClickListener(clickListener);
+    }
+}

+ 200 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/bean/WatermarkInfo.java

@@ -0,0 +1,200 @@
+package com.compdfkit.tools.security.watermark.bean;
+
+
+import static com.compdfkit.tools.security.watermark.view.WatermarkView.DEFAULT_STR;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.text.TextUtils;
+
+import com.compdfkit.core.watermark.CPDFWatermark;
+import com.compdfkit.tools.security.watermark.view.WatermarkView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class WatermarkInfo {
+
+    /**
+     * The page number to which the watermark belongs
+     */
+    private int index = 0;
+
+    /**
+     * watermark type
+     * txt or image
+     */
+    private CPDFWatermark.Type editType;
+
+    private CPDFWatermark watermark;
+
+    private PointF centerPoint = new PointF(0F, 0F);
+
+    /**
+     * image watermark bitmap
+     */
+    private Bitmap bitmap;
+
+    /**
+     * text watermark content
+     */
+    private String textContent = DEFAULT_STR;
+
+    private int textColor = Color.BLACK;
+
+    private float textSize = 0;
+
+    private float scale = 1F;
+
+    private float degree = 0F;
+
+    private float alpha = 1F;
+
+    private String pages = "";
+
+    private float hScale = 1F;
+
+    private boolean isDeleted = false;
+
+    private ArrayList<Integer> pageList = new ArrayList<>();
+
+    public WatermarkInfo(int index, CPDFWatermark watermark){
+        this.index = index;
+        this.watermark = watermark;
+    }
+
+    public void init(float scale, float pageWidth, float pageHeight, CPDFWatermark watermark, int pageCount){
+        this.hScale = scale;
+        editType = watermark.getType();
+        bitmap = watermark.getImage();
+        textContent = TextUtils.isEmpty(watermark.getText()) ? DEFAULT_STR : watermark.getText();
+        textColor = watermark.getTextRGBColor();
+        textSize = watermark.getFontSize();
+        scale = watermark.getScale() * hScale;
+        degree = (float) -(watermark.getRotation() * 180 / Math.PI);
+        alpha = watermark.getOpacity();
+        centerPoint.set((watermark.getHorizOffset() + pageWidth / 2) * hScale, (pageHeight / 2 - watermark.getVertOffset()) * hScale);
+    }
+
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public CPDFWatermark.Type getEditType() {
+        return editType;
+    }
+
+    public void setEditType(CPDFWatermark.Type editType) {
+        this.editType = editType;
+    }
+
+    public CPDFWatermark getWatermark() {
+        return watermark;
+    }
+
+    public void setWatermark(CPDFWatermark watermark) {
+        this.watermark = watermark;
+    }
+
+    public PointF getCenterPoint() {
+        return centerPoint;
+    }
+
+    public void setCenterPoint(PointF centerPoint) {
+        this.centerPoint = centerPoint;
+    }
+
+    public Bitmap getBitmap() {
+        return bitmap;
+    }
+
+    public void setBitmap(Bitmap bitmap) {
+        this.bitmap = bitmap;
+    }
+
+    public String getTextContent() {
+        return textContent;
+    }
+
+    public void setTextContent(String textContent) {
+        this.textContent = textContent;
+    }
+
+    public int getTextColor() {
+        return textColor;
+    }
+
+    public void setTextColor(int textColor) {
+        this.textColor = textColor;
+    }
+
+    public float getTextSize() {
+        return textSize;
+    }
+
+    public void setTextSize(float textSize) {
+        this.textSize = textSize;
+    }
+
+    public float getScale() {
+        return scale;
+    }
+
+    public void setScale(float scale) {
+        this.scale = scale;
+    }
+
+    public float getDegree() {
+        return degree;
+    }
+
+    public void setDegree(float degree) {
+        this.degree = degree;
+    }
+
+    public float getAlpha() {
+        return alpha;
+    }
+
+    public void setAlpha(float alpha) {
+        this.alpha = alpha;
+    }
+
+    public String getPages() {
+        return pages;
+    }
+
+    public void setPages(String pages) {
+        this.pages = pages;
+    }
+
+    public float gethScale() {
+        return hScale;
+    }
+
+    public void sethScale(float hScale) {
+        this.hScale = hScale;
+    }
+
+    public boolean isDeleted() {
+        return isDeleted;
+    }
+
+    public void setDeleted(boolean deleted) {
+        isDeleted = deleted;
+    }
+
+    public ArrayList<Integer> getPageList() {
+        return pageList;
+    }
+
+    public void setPageList(ArrayList<Integer> pageList) {
+        this.pageList = pageList;
+    }
+}

+ 177 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/pdfproperties/CWatermarkTextStyleFragment.java

@@ -0,0 +1,177 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.tools.security.watermark.pdfproperties;
+
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatImageView;
+
+import com.compdfkit.core.annotation.CPDFTextAttribute;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.view.colorpicker.CColorPickerFragment;
+import com.compdfkit.tools.common.utils.view.colorpicker.widget.ColorPickerView;
+import com.compdfkit.tools.common.utils.view.sliderbar.CSliderBar;
+import com.compdfkit.tools.common.views.pdfproperties.basic.CBasicPropertiesFragment;
+import com.compdfkit.tools.common.views.pdfproperties.colorlist.ColorListView;
+import com.compdfkit.tools.common.views.pdfproperties.font.CFontSpinnerAdapter;
+import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CAnnotStyle;
+import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleFragmentDatas;
+import com.compdfkit.tools.common.views.pdfproperties.preview.CStylePreviewView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CWatermarkTextStyleFragment extends CBasicPropertiesFragment implements View.OnClickListener,
+        ColorPickerView.COnColorChangeListener,ColorPickerView.COnColorAlphaChangeListener {
+
+    private ColorListView colorListView;
+
+    private CSliderBar opacitySliderBar;
+
+    private AppCompatImageView ivFontItalic;
+
+    private AppCompatImageView ivFontBold;
+
+    private CSliderBar fontSizeSliderBar;
+
+    private Spinner fontSpinner;
+
+    @Nullable
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View rootView = inflater.inflate(R.layout.tools_cpdf_security_watermark_text_style_fragment, container, false);
+        colorListView = rootView.findViewById(R.id.border_color_list_view);
+        opacitySliderBar = rootView.findViewById(R.id.slider_bar);
+        ivFontItalic = rootView.findViewById(R.id.iv_font_italic);
+        ivFontBold = rootView.findViewById(R.id.iv_font_bold);
+        fontSizeSliderBar = rootView.findViewById(R.id.font_size_slider_bar);
+        fontSpinner = rootView.findViewById(R.id.spinner_font);
+        ivFontItalic.setOnClickListener(this);
+        ivFontBold.setOnClickListener(this);
+        return rootView;
+    }
+
+    @Override
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        CAnnotStyle annotStyle = viewModel.getStyle();
+        if (annotStyle != null) {
+            List<CPDFTextAttribute.FontNameHelper.FontType> fontTypes = new ArrayList<>();
+            fontTypes.add(CPDFTextAttribute.FontNameHelper.FontType.Helvetica);
+            fontTypes.add(CPDFTextAttribute.FontNameHelper.FontType.Courier);
+            fontTypes.add(CPDFTextAttribute.FontNameHelper.FontType.Times_Roman);
+            CFontSpinnerAdapter fontSpinnerAdapter = new CFontSpinnerAdapter(getContext(), fontTypes);
+            fontSpinner.setAdapter(fontSpinnerAdapter);
+            switch (annotStyle.getFontType()) {
+                case Courier:
+                    fontSpinner.setSelection(1);
+                    break;
+                case Times_Roman:
+                    fontSpinner.setSelection(2);
+                    break;
+                default:
+                    fontSpinner.setSelection(0);
+                    break;
+            }
+            colorListView.setSelectColor(annotStyle.getTextColor());
+            opacitySliderBar.setProgress(annotStyle.getTextColorOpacity());
+            ivFontBold.setSelected(annotStyle.isFontBold());
+            ivFontItalic.setSelected(annotStyle.isFontItalic());
+            fontSizeSliderBar.setProgress(annotStyle.getFontSize());
+        }
+        colorListView.setOnColorSelectListener(this::color);
+        colorListView.setColorPickerClickListener(() -> {
+            CAnnotStyle cAnnotStyle = viewModel.getStyle();
+            showFragment(CStyleFragmentDatas.colorPicker(), (CColorPickerFragment colorPickerFragment)->{
+                colorPickerFragment.initColor(cAnnotStyle.getTextColor(), cAnnotStyle.getTextColorOpacity());
+                colorPickerFragment.setColorPickerListener(this);
+                colorPickerFragment.setColorAlphaChangeListener(this);
+            });
+        });
+        opacitySliderBar.setChangeListener((progress, percentageValue, isStop) -> opacity(progress));
+        fontSizeSliderBar.setChangeListener((progress, percentageValue, isStop) -> {
+            if (viewModel != null) {
+                viewModel.getStyle().setFontSize(progress);
+            }
+        });
+        viewModel.addStyleChangeListener(this);
+        fontSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                if (viewModel != null) {
+                    CPDFTextAttribute.FontNameHelper.FontType fontType = (CPDFTextAttribute.FontNameHelper.FontType) fontSpinner.getItemAtPosition(position);
+                    viewModel.getStyle().setFontType(fontType);
+                }
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+
+            }
+        });
+    }
+
+    @Override
+    public void color(int color) {
+        if (viewModel != null && viewModel.getStyle() != null) {
+            viewModel.getStyle().setFontColor(color);
+        }
+    }
+
+    @Override
+    public void opacity(int opacity) {
+        if (viewModel.getStyle() != null) {
+            viewModel.getStyle().setTextColorOpacity(opacity);
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.iv_font_bold) {
+            ivFontBold.setSelected(!ivFontBold.isSelected());
+            if (viewModel != null) {
+                viewModel.getStyle().setFontBold(ivFontBold.isSelected());
+            }
+        } else if (v.getId() == R.id.iv_font_italic) {
+            ivFontItalic.setSelected(!ivFontItalic.isSelected());
+            if (viewModel != null) {
+                viewModel.getStyle().setFontItalic(ivFontItalic.isSelected());
+            }
+        }
+    }
+
+    @Override
+    public void onChangeTextColor(int textColor) {
+        if (!isOnResume) {
+            if (colorListView != null) {
+                colorListView.setSelectColor(textColor);
+            }
+        }
+    }
+
+    @Override
+    public void onChangeTextColorOpacity(int textColorOpacity) {
+        if (!isOnResume) {
+            if (colorListView != null) {
+                opacitySliderBar.setProgress(textColorOpacity);
+            }
+        }
+    }
+
+}

+ 335 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/view/CWatermarkPageView.java

@@ -0,0 +1,335 @@
+package com.compdfkit.tools.security.watermark.view;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.graphics.Typeface;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.core.content.ContextCompat;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.compdfkit.core.annotation.CPDFTextAttribute;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.watermark.CPDFWatermark;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.CLog;
+import com.compdfkit.tools.common.utils.glide.CPDFWrapper;
+import com.compdfkit.tools.common.utils.viewutils.CDimensUtils;
+
+
+public class CWatermarkPageView extends FrameLayout {
+
+    public static final String TAG = "CWatermarkPageView";
+
+    private AppCompatImageView ivPageView;
+
+    private WatermarkView watermarkView;
+
+    private FrameLayout watermarkViewContent;
+
+    private CPDFDocument document;
+
+    private int pageIndex = 0;
+
+    private float currentPageWidth = 0;
+
+    private float currentPageHeight = 0;
+
+    private float whScale = 1F;
+
+    private PointF centerPoint = new PointF();
+
+    public CWatermarkPageView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CWatermarkPageView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CWatermarkPageView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(attrs);
+    }
+
+    private void initView(AttributeSet attributeSet) {
+
+        ivPageView = new AppCompatImageView(getContext());
+        ivPageView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.tools_color_accent_50));
+        LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        layoutParams.gravity = Gravity.CENTER;
+
+        watermarkViewContent = new FrameLayout(getContext());
+        LayoutParams layoutParams1 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        layoutParams1.gravity = Gravity.CENTER;
+        watermarkViewContent.setLayoutParams(layoutParams1);
+        addView(watermarkViewContent);
+
+        watermarkView = new WatermarkView(getContext());
+        LayoutParams watermarkLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        watermarkLayoutParams.gravity = Gravity.CENTER;
+        watermarkViewContent.addView(ivPageView, watermarkLayoutParams);
+        watermarkViewContent.addView(watermarkView, watermarkLayoutParams);
+
+
+        watermarkView.setEditable(true);
+        watermarkView.setFrameColor(ContextCompat.getColor(getContext(), R.color.tools_color_accent));
+        watermarkView.setFramePadding(10);
+        watermarkView.setFrameWidth(CDimensUtils.dp2px(getContext(), 2));
+        watermarkView.setControlLocation(WatermarkView.LEFT_BOTTOM);
+        watermarkView.setUpActionListener((scale, pointF) -> {
+//            this.scale = scale;
+
+        });
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        CLog.e(TAG, "onSizeChanged-viewWidth:" + w + ", viewHeight:" + h);
+        if (document != null) {
+            initPageSize(w, h);
+        }
+
+    }
+
+    public void setDocument(CPDFDocument document, int pageIndex) {
+        this.document = document;
+        this.pageIndex = pageIndex;
+    }
+
+    private void initDocumentThumbnail() {
+        if (document != null && currentPageWidth != 0 && currentPageHeight != 0) {
+            CLog.e(TAG, "initDocumentThumbnail-加载PDF缩略图");
+            Glide.with(getContext())
+                    .load(CPDFWrapper.fromDocument(document, pageIndex))
+                    .diskCacheStrategy(DiskCacheStrategy.NONE)
+                    .override((int) currentPageWidth, (int) currentPageHeight)
+                    .into(ivPageView);
+        }
+    }
+
+    private void initPageSize(int itemWidth, int itemHeight) {
+
+        RectF rectF = document.pageAtIndex(pageIndex).getSize();
+
+        float imageWidth = itemWidth;
+        float imageHeight = ((float) imageWidth / (float) rectF.width()) * rectF.height();
+        if (imageHeight > itemHeight) {
+            imageHeight = itemHeight;
+            imageWidth = (imageHeight / rectF.height()) * rectF.width();
+        }
+        currentPageWidth = imageWidth;
+        currentPageHeight = imageHeight;
+        whScale = rectF.width() / currentPageWidth ;
+
+        CLog.e(TAG, "initPage()-currentPageWidth:" + currentPageWidth + ", currentPageHeight:" + currentPageHeight);
+
+        ViewGroup.LayoutParams layoutParams = watermarkViewContent.getLayoutParams();
+        layoutParams.width = (int) currentPageWidth;
+        layoutParams.height = (int) currentPageHeight;
+        watermarkViewContent.setLayoutParams(layoutParams);
+
+        watermarkView.setImageScale(whScale);
+        initDocumentThumbnail();
+
+
+        float currentPageHeight1;
+        float currentPageWidth1;
+        RectF pageSize = document.pageAtIndex(0).getSize();
+        float pw = pageSize.width();
+        float ph = pageSize.height();
+        float wScale = pw / ph;
+        float hScale = ph / pw;
+        float deno = 4;
+        float mScale = 1F;
+        float maxHeight = itemHeight;
+        float maxWidth = itemWidth;
+        if (pw <= itemWidth && ph >= itemHeight) {
+            currentPageHeight1 = itemHeight;
+            currentPageWidth1 = (wScale * maxHeight);
+            mScale = currentPageHeight1 / ph;
+        } else {
+            currentPageWidth1 = maxWidth;
+            currentPageHeight1 = (hScale * maxWidth);
+            mScale = currentPageWidth1 / pw;
+            while (currentPageHeight1 > maxHeight) {
+                currentPageWidth1 = maxWidth * 3 / (deno++);
+                currentPageHeight1 = (hScale * currentPageWidth1);
+                mScale = currentPageWidth1 / pw;
+            }
+        }
+
+        CLog.e(TAG, "mScale:"+mScale +" pageWidth1:" + currentPageWidth1 +"pageHeight1:" + currentPageHeight1);
+
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        int viewWidth = getSize(widthMeasureSpec);
+        int viewHeight = getSize(heightMeasureSpec);
+        if (document != null) {
+            RectF rectF = document.pageAtIndex(pageIndex).getSize();
+
+            float imageWidth = viewWidth;
+            float imageHeight = ((float) imageWidth / (float) rectF.width()) * rectF.height();
+            if (imageHeight > viewHeight) {
+                imageHeight = viewHeight;
+                imageWidth = (imageHeight / rectF.height()) * rectF.width();
+            }
+            setMeasuredDimension((int) imageWidth, (int) imageHeight);
+        } else {
+            setMeasuredDimension(viewWidth, viewHeight);
+        }
+    }
+
+    private int getSize(int measureSpec) {
+        int customSize = CDimensUtils.getScreenWidth(getContext());
+
+        int size = MeasureSpec.getSize(measureSpec);
+        int mode = MeasureSpec.getMode(measureSpec);
+
+        switch (mode) {
+            case MeasureSpec.AT_MOST:
+                customSize = size;
+                break;
+            case MeasureSpec.UNSPECIFIED:
+                customSize = CDimensUtils.getScreenWidth(getContext());
+                break;
+            case MeasureSpec.EXACTLY:
+                customSize = size;
+                break;
+            default:
+                break;
+        }
+        return customSize;
+    }
+
+    public void setFrameColor(@ColorInt int color) {
+        watermarkView.setFrameColor(color);
+    }
+
+    public void setFramePadding(int padding) {
+        watermarkView.setFramePadding(padding);
+    }
+
+    public void setFrameWidth(int width) {
+        watermarkView.setFrameWidth(width);
+    }
+
+    public void setText(String watermarkText) {
+        watermarkView.setText(watermarkText);
+    }
+
+    public void setTextColor(@ColorInt int color) {
+        watermarkView.setTextColor(color);
+    }
+
+    public int getTextColor() {
+        return watermarkView.getTextColor();
+    }
+
+    public void setTextColorOpacity(int alpha) {
+        watermarkView.setWatermarkAlpha(alpha);
+    }
+
+    public int getWatermarkOpacity() {
+        return watermarkView.getWatermarkAlpha();
+    }
+
+    public void setTextSize(int textSize) {
+        watermarkView.setTextSize(textSize);
+    }
+
+    public int getTextSize() {
+        return watermarkView.getTextSize();
+    }
+
+    public boolean isBold() {
+        return watermarkView.isBold();
+    }
+
+    public boolean isItalic() {
+        return watermarkView.isItalic();
+    }
+
+    public CPDFTextAttribute.FontNameHelper.FontType getFontType() {
+        return watermarkView.getFontType();
+    }
+
+    public void setBold(boolean bold) {
+        setTypeface(watermarkView.getFontType(), bold, isItalic());
+    }
+
+    public void setItalic(boolean italic) {
+        setTypeface(watermarkView.getFontType(), isBold(), italic);
+    }
+
+    public void setTypeface(CPDFTextAttribute.FontNameHelper.FontType fontType, boolean isBold, boolean isItalic) {
+        String fontName = CPDFTextAttribute.FontNameHelper.obtainFontName(fontType, isBold, isItalic);
+        Typeface typeface = CPDFTextAttribute.FontNameHelper.getInnerTypeface(getContext(), fontName);
+        watermarkView.setTypeface(fontType, typeface, isBold, isItalic);
+    }
+
+
+    public void setEditable(boolean editable) {
+        watermarkView.setEditable(editable);
+    }
+
+    public void createTextWatermark(String watermarkText) {
+        PointF centerPointF = new PointF(currentPageWidth / 2, currentPageHeight / 2);
+        int fontSize = CDimensUtils.spToPx(14, getContext());
+        watermarkView.setCenter(centerPointF);
+        watermarkView.initTextWaterMark(watermarkText, Color.BLACK, fontSize, 255);
+        watermarkView.setDegree(-45F);
+    }
+
+    public void createImageWatermark(Bitmap bitmap) {
+        PointF centerPointF = new PointF(currentPageWidth / 2, currentPageHeight / 2);
+        watermarkView.setCenter(centerPointF);
+        watermarkView.setImageBitmap(bitmap);
+    }
+
+    public void applyWatermark(CPDFDocument document) {
+        RectF pageSize = document.getPageSize(0);
+        CPDFWatermark watermark = document.createWatermark(watermarkView.getWatermarkType() == WatermarkView.EditType.TXT ? CPDFWatermark.Type.WATERMARK_TYPE_TEXT : CPDFWatermark.Type.WATERMARK_TYPE_IMG);
+        watermark.setFontName(CPDFTextAttribute.FontNameHelper.obtainFontName(
+                watermarkView.getFontType(), watermarkView.isBold(), watermarkView.isItalic()
+        ));
+        watermark.setText(watermarkView.getText());
+        watermark.setTextRGBColor(getTextColor());
+        watermark.setFontSize(watermarkView.getTextSize() * whScale);
+        watermark.setOpacity(getWatermarkOpacity() / 255F);
+        watermark.setPages("0");
+        watermark.setFront(true);
+
+        watermark.setScale(watermarkView.getScale());
+        watermark.setRotation(-watermarkView.getRadian());
+        watermark.setHorizalign(CPDFWatermark.Horizalign.WATERMARK_HORIZALIGN_CENTER);
+        watermark.setVertalign(CPDFWatermark.Vertalign.WATERMARK_VERTALIGN_CENTER);
+        float offsetX = watermarkView.getScale() * watermarkView.centerPoint().x - pageSize.width() /2;
+        float offsetY = pageSize.height() / 2 - watermarkView.getScale() * watermarkView.centerPoint().y;
+
+//        watermark.setHorizOffset(offsetX);
+//        watermark.setVertOffset(offsetY);
+
+
+        watermark.update();
+        watermark.release();
+    }
+
+
+}

File diff suppressed because it is too large
+ 1126 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/security/watermark/view/WatermarkView.java


+ 32 - 0
ComPDFKit_Tools/src/main/res/drawable/ic_watermark_zoom.xml

@@ -0,0 +1,32 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportWidth="16"
+    android:viewportHeight="16">
+    <path
+        android:fillType="evenOdd"
+        android:pathData="M-248,-29h381v287h-381z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
+    <path
+        android:fillColor="#FF4F4F"
+        android:fillType="evenOdd"
+        android:pathData="M8,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
+    <path
+        android:fillColor="#00000000"
+        android:fillType="evenOdd"
+        android:pathData="M11.74,8.12C11.74,5.5684 9.6716,3.5 7.12,3.5C4.5684,3.5 2.5,5.5684 2.5,8.12C2.5,10.6716 4.5684,12.74 7.12,12.74C8.0516,12.74 8.9188,12.4643 9.6444,11.99"
+        android:strokeWidth="1"
+        android:strokeColor="#FFFFFF"
+        android:strokeLineCap="round" />
+    <path
+        android:fillColor="#00000000"
+        android:fillType="evenOdd"
+        android:pathData="M9.166,6.7859l2.52,2.52l2.52,-2.52"
+        android:strokeWidth="1"
+        android:strokeColor="#FFFFFF"
+        android:strokeLineCap="round"
+        android:strokeLineJoin="round" />
+</vector>

+ 7 - 0
ComPDFKit_Tools/src/main/res/drawable/selector_radiobutton.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+<!--    <item android:drawable="@drawable/ic_radio_btn_seleted" android:state_checked="true" android:state_enabled="true" />-->
+<!--    <item android:drawable="@drawable/ic_base_radio_unselected" />-->
+
+</selector>

+ 5 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_btn_eyes_visible_selector.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:drawable="@drawable/tools_ic_btn_eyes_visible"/>
+    <item android:drawable="@drawable/tools_ic_btn_eyes_invisible"/>
+</selector>

+ 17 - 4
ComPDFKit_Tools/src/main/res/drawable/tools_ic_baseline_folder.xml

@@ -1,5 +1,18 @@
-<vector android:height="24dp" android:tint="#000000"
-    android:viewportHeight="24" android:viewportWidth="24"
-    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="@android:color/white" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="40dp"
+    android:height="41dp"
+    android:viewportWidth="40"
+    android:viewportHeight="41">
+  <path
+      android:pathData="M17.191,7.922C16.813,7.528 16.292,7.306 15.746,7.306H5.017C3.912,7.306 3.017,8.201 3.017,9.305C3.017,9.78 3.017,10.308 3.017,10.854L3.001,32.679C3.001,33.784 3.896,34.681 5.001,34.681H35C36.105,34.681 37,33.785 37,32.681V12.854C37,11.75 36.105,10.854 35,10.854H20L17.191,7.922Z"
+      android:fillColor="#273C62"
+      android:fillAlpha="0.3"/>
+  <group>
+    <clip-path
+        android:pathData="M17.191,7.922C16.813,7.528 16.292,7.306 15.746,7.306H5.017C3.912,7.306 3.017,8.201 3.017,9.305C3.017,9.78 3.017,10.308 3.017,10.854L3.001,32.679C3.001,33.784 3.896,34.681 5.001,34.681H35C36.105,34.681 37,33.785 37,32.681V12.854C37,11.75 36.105,10.854 35,10.854H20L17.191,7.922Z"/>
+    <path
+        android:pathData="M1,1.223h25v9.632h-25z"
+        android:fillColor="#273C62"
+        android:fillAlpha="0.8"/>
+  </group>
 </vector>

+ 10 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_btn_eyes_invisible.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M19.955,18.894L5.106,4.045L4.045,5.106L18.894,19.955L19.955,18.894ZM3,12C3,12 4.047,10.442 5.731,8.913L14.379,17.561C13.621,17.836 12.823,18 12,18C7.029,18 3,12 3,12ZM21,12C21,12 19.953,13.559 18.269,15.087L9.621,6.439C10.379,6.165 11.177,6 12,6C16.971,6 21,12 21,12Z"
+      android:fillColor="#666666"
+      android:fillType="evenOdd"/>
+</vector>

+ 10 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_btn_eyes_visible.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M12,18C16.971,18 21,12 21,12C21,12 16.971,6 12,6C7.029,6 3,12 3,12C3,12 7.029,18 12,18ZM12,15C13.657,15 15,13.657 15,12C15,10.343 13.657,9 12,9C10.343,9 9,10.343 9,12C9,13.657 10.343,15 12,15Z"
+      android:fillColor="#666666"
+      android:fillType="evenOdd"/>
+</vector>

+ 13 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_watermark_control.xml

@@ -0,0 +1,13 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportWidth="16"
+    android:viewportHeight="16">
+  <path
+      android:pathData="M8,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+      android:fillColor="#1460F3"/>
+  <path
+      android:pathData="M7.414,3.458L6.996,3.732L7.27,4.15L8.398,5.868L9.234,5.319L8.757,4.593C10.539,4.944 11.884,6.517 11.884,8.402C11.884,10.547 10.145,12.285 8,12.285C5.856,12.285 4.117,10.547 4.117,8.402C4.117,7.118 4.74,5.979 5.703,5.271L5.111,4.465C3.903,5.353 3.117,6.786 3.117,8.402C3.117,11.099 5.303,13.285 8,13.285C10.697,13.285 12.884,11.099 12.884,8.402C12.884,6.044 11.212,4.077 8.99,3.619L9.68,3.166L9.131,2.33L7.414,3.458Z"
+      android:fillColor="#ffffff"
+      android:fillType="evenOdd"/>
+</vector>

+ 10 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_watermark_location_bottom.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="20dp"
+    android:height="20dp"
+    android:viewportWidth="20"
+    android:viewportHeight="20">
+  <path
+      android:pathData="M10,15.487L10.54,14.966L14.137,11.493L14.677,10.972L13.597,9.931L13.058,10.452L10.75,12.679V2.75V2H9.25V2.75L9.25,12.679L6.942,10.452L6.402,9.931L5.323,10.972L5.863,11.493L9.46,14.966L10,15.487ZM2.75,17.48H2V18.98H2.75H16.75H17.5V17.48H16.75H2.75Z"
+      android:fillColor="#43474D"
+      android:fillType="evenOdd"/>
+</vector>

+ 10 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_watermark_location_top.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="20dp"
+    android:height="20dp"
+    android:viewportWidth="20"
+    android:viewportHeight="20">
+  <path
+      android:pathData="M10,5.494L10.54,6.015L14.137,9.487L14.677,10.008L13.597,11.05L13.058,10.529L10.75,8.301V18.23V18.98H9.25V18.23L9.25,8.301L6.942,10.529L6.402,11.05L5.323,10.008L5.863,9.487L9.46,6.015L10,5.494ZM2.75,3.5H2V2H2.75H16.75H17.5V3.5H16.75H2.75Z"
+      android:fillColor="#43474D"
+      android:fillType="evenOdd"/>
+</vector>

File diff suppressed because it is too large
+ 10 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_mode_switch_digital_signature.xml


+ 5 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_selector_radiobutton_color.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/tools_text_color_primary" android:state_checked="true" />
+    <item android:color="@color/tools_text_color_disable" android:state_checked="false" />
+</selector>

+ 18 - 5
ComPDFKit_Tools/src/main/res/layout/tools_bota_bookmark_input_dialog.xml

@@ -21,9 +21,9 @@
             android:id="@+id/tv_title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginHorizontal="24dp"
             android:gravity="center_vertical|start"
             android:text="@string/tools_add_bookmarks"
-            android:layout_marginHorizontal="24dp"
             android:textColor="@color/tools_text_color_primary"
             android:textSize="16sp"
             app:layout_constraintStart_toStartOf="parent"
@@ -31,20 +31,33 @@
 
         <androidx.appcompat.widget.AppCompatEditText
             android:id="@+id/tv_message"
-            android:layout_width="match_parent"
+            android:layout_width="0dp"
             android:layout_height="wrap_content"
+            android:layout_marginStart="24dp"
             android:layout_marginTop="12dp"
             android:backgroundTint="@color/tools_color_accent"
             android:gravity="center_vertical"
-            android:layout_marginHorizontal="24dp"
+            android:layout_marginEnd="24dp"
             android:maxLines="1"
             android:minHeight="45dp"
             android:textColor="@color/tools_text_color_primary"
             android:textColorHint="@color/tools_text_color_hint"
             android:textCursorDrawable="@drawable/tools_normal_et_cursor"
-            app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/tv_title" />
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/tv_title"
+            android:paddingEnd="28dp"
+            />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_input_visible"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:layout_marginEnd="8dp"
+            android:src="@drawable/tools_btn_eyes_visible_selector"
+            app:layout_constraintBottom_toBottomOf="@id/tv_message"
+            app:layout_constraintEnd_toEndOf="@id/tv_message"
+            app:layout_constraintTop_toTopOf="@id/tv_message" />
 
         <LinearLayout
             android:layout_width="wrap_content"

+ 248 - 198
ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_document_encryption_dialog.xml

@@ -29,211 +29,261 @@
 
     </com.compdfkit.tools.common.views.CToolBar>
 
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/tv_setting_password_title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="16dp"
-        android:text="@string/tools_setting_password"
-        android:textColor="@color/tools_text_color_primary"
-        android:textStyle="bold"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/tool_bar" />
-
-    <Switch
-        android:id="@+id/sw_setting_password"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="16dp"
-        android:checked="false"
-        app:layout_constraintBottom_toBottomOf="@id/tv_setting_password_title"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="@id/tv_setting_password_title" />
-
-    <View
-        android:id="@+id/line1"
+    <ScrollView
         android:layout_width="match_parent"
-        android:layout_height="0.5dp"
-        android:layout_marginHorizontal="8dp"
-        android:layout_marginTop="16dp"
-        android:background="@color/tools_item_dividing_line_color"
+        android:layout_height="0dp"
+        android:fillViewport="true"
+        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/tv_setting_password_title" />
-
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/tv_enter_password"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="16dp"
-        android:text="@string/tools_enter_password"
-        android:textColor="@color/tools_text_color_primary"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/line1" />
-
-    <androidx.appcompat.widget.AppCompatEditText
-        android:id="@+id/et_user_password"
-        android:layout_width="0dp"
-        android:layout_height="35dp"
-        android:layout_marginStart="8dp"
-        android:layout_marginEnd="16dp"
-        android:gravity="end|center_vertical"
-        android:enabled="false"
-        android:inputType="textPassword"
-        android:maxLines="1"
-        android:background="@null"
-        app:layout_constrainedWidth="true"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintHorizontal_bias="1"
-        app:layout_constraintTop_toTopOf="@id/tv_enter_password"
-        app:layout_constraintBottom_toBottomOf="@id/tv_enter_password"
-        app:layout_constraintStart_toEndOf="@id/tv_enter_password" />
+        app:layout_constraintTop_toBottomOf="@id/tool_bar">
 
-    <View
-        android:id="@+id/line2"
-        android:layout_width="match_parent"
-        android:layout_height="28dp"
-        android:layout_marginTop="16dp"
-        android:background="@color/tools_reader_setting_head_bg_color"
-        app:layout_constraintTop_toBottomOf="@id/tv_enter_password" />
-
-
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/tv_permission_password_title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="16dp"
-        android:text="@string/tools_setting_permission_password"
-        android:textColor="@color/tools_text_color_primary"
-        android:textStyle="bold"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/line2" />
-
-    <Switch
-        android:id="@+id/sw_setting_permission_password"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="16dp"
-        android:checked="false"
-        app:layout_constraintBottom_toBottomOf="@id/tv_permission_password_title"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="@id/tv_permission_password_title" />
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
 
-    <View
-        android:id="@+id/line3"
-        android:layout_width="match_parent"
-        android:layout_height="0.5dp"
-        android:layout_marginHorizontal="8dp"
-        android:layout_marginTop="16dp"
-        android:background="@color/tools_item_dividing_line_color"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/sw_setting_permission_password" />
-
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/tv_enter_permission_password"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="16dp"
-        android:text="@string/tools_enter_password"
-        android:textColor="@color/tools_text_color_primary"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/line3" />
-
-    <androidx.appcompat.widget.AppCompatEditText
-        android:id="@+id/et_owner_password"
-        android:layout_width="0dp"
-        android:layout_height="35dp"
-        android:layout_marginStart="8dp"
-        android:enabled="false"
-        android:layout_marginEnd="16dp"
-        android:gravity="end|center_vertical"
-        android:inputType="textPassword"
-        android:background="@null"
-        android:maxLines="1"
-        app:layout_constrainedWidth="true"
-        app:layout_constraintTop_toTopOf="@id/tv_enter_permission_password"
-        app:layout_constraintBottom_toBottomOf="@id/tv_enter_permission_password"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintHorizontal_bias="1"
-        app:layout_constraintStart_toEndOf="@id/tv_enter_permission_password" />
 
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_setting_password_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="16dp"
+                android:layout_marginTop="16dp"
+                android:text="@string/tools_setting_password"
+                android:textColor="@color/tools_text_color_primary"
+                android:textStyle="bold"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent" />
+
+            <Switch
+                android:id="@+id/sw_setting_password"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="16dp"
+                android:checked="false"
+                app:layout_constraintBottom_toBottomOf="@id/tv_setting_password_title"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="@id/tv_setting_password_title" />
+
+            <View
+                android:id="@+id/line1"
+                android:layout_width="match_parent"
+                android:layout_height="0.5dp"
+                android:layout_marginHorizontal="8dp"
+                android:layout_marginTop="16dp"
+                android:background="@color/tools_item_dividing_line_color"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/tv_setting_password_title" />
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_enter_password"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="16dp"
+                android:layout_marginTop="16dp"
+                android:text="@string/tools_enter_password"
+                android:textColor="@color/tools_text_color_hint"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/line1" />
+
+            <androidx.appcompat.widget.AppCompatEditText
+                android:id="@+id/et_user_password"
+                android:layout_width="0dp"
+                android:layout_height="35dp"
+                android:layout_marginStart="8dp"
+                android:background="@null"
+                android:enabled="false"
+                android:gravity="end|center_vertical"
+                android:hint="@string/tools_please_enter_the_password"
+                android:inputType="textPassword"
+                android:maxLines="1"
+                android:textSize="13sp"
+                android:textColorHint="@color/tools_text_color_hint"
+                app:layout_constrainedWidth="true"
+                app:layout_constraintBottom_toBottomOf="@id/tv_enter_password"
+                app:layout_constraintEnd_toStartOf="@id/iv_user_pwd_show"
+                app:layout_constraintHorizontal_bias="1"
+                app:layout_constraintStart_toEndOf="@id/tv_enter_password"
+                app:layout_constraintTop_toTopOf="@id/tv_enter_password" />
+
+            <androidx.appcompat.widget.AppCompatImageView
+                android:id="@+id/iv_user_pwd_show"
+                android:layout_width="35dp"
+                android:layout_height="35dp"
+                android:layout_marginEnd="24dp"
+                android:padding="2dp"
+                app:layout_constraintBottom_toBottomOf="@id/et_user_password"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="@id/et_user_password"
+                app:srcCompat="@drawable/tools_btn_eyes_visible_selector" />
+
+            <View
+                android:id="@+id/line2"
+                android:layout_width="match_parent"
+                android:layout_height="28dp"
+                android:layout_marginTop="16dp"
+                android:background="@color/tools_reader_setting_head_bg_color"
+                app:layout_constraintTop_toBottomOf="@id/tv_enter_password" />
+
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_permission_password_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="16dp"
+                android:layout_marginTop="16dp"
+                android:text="@string/tools_setting_permission_password"
+                android:textColor="@color/tools_text_color_primary"
+                android:textStyle="bold"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/line2" />
+
+            <Switch
+                android:id="@+id/sw_setting_permission_password"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="16dp"
+                android:checked="false"
+                app:layout_constraintBottom_toBottomOf="@id/tv_permission_password_title"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="@id/tv_permission_password_title" />
+
+            <View
+                android:id="@+id/line3"
+                android:layout_width="match_parent"
+                android:layout_height="0.5dp"
+                android:layout_marginHorizontal="8dp"
+                android:layout_marginTop="16dp"
+                android:background="@color/tools_item_dividing_line_color"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/sw_setting_permission_password" />
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_enter_permission_password"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="16dp"
+                android:layout_marginTop="16dp"
+                android:text="@string/tools_enter_password"
+                android:textColor="@color/tools_text_color_hint"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/line3" />
+
+            <androidx.appcompat.widget.AppCompatEditText
+                android:id="@+id/et_owner_password"
+                android:layout_width="0dp"
+                android:layout_height="35dp"
+                android:layout_marginStart="8dp"
+                android:background="@null"
+                android:enabled="false"
+                android:gravity="end|center_vertical"
+                android:hint="@string/tools_please_enter_owner_password"
+                android:inputType="textPassword"
+                android:maxLines="1"
+                android:textSize="13sp"
+                android:textColorHint="@color/tools_text_color_hint"
+                app:layout_constrainedWidth="true"
+                app:layout_constraintBottom_toBottomOf="@id/tv_enter_permission_password"
+                app:layout_constraintEnd_toStartOf="@id/iv_owner_pwd_show"
+                app:layout_constraintHorizontal_bias="1"
+                app:layout_constraintStart_toEndOf="@id/tv_enter_permission_password"
+                app:layout_constraintTop_toTopOf="@id/tv_enter_permission_password" />
+
+            <androidx.appcompat.widget.AppCompatImageView
+                android:id="@+id/iv_owner_pwd_show"
+                android:layout_width="35dp"
+                android:layout_height="35dp"
+                android:layout_marginEnd="24dp"
+                android:padding="2dp"
+                app:layout_constraintBottom_toBottomOf="@id/et_owner_password"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="@id/et_owner_password"
+                app:srcCompat="@drawable/tools_btn_eyes_visible_selector" />
+
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_owner_functions"
+                android:layout_width="match_parent"
+                android:layout_height="28dp"
+                android:layout_marginTop="8dp"
+                android:background="@color/tools_reader_setting_head_bg_color"
+                android:gravity="center_vertical"
+                android:paddingStart="16dp"
+                android:paddingEnd="16dp"
+                android:text="@string/tools_also_entrypts_the_followint_fuctions"
+                android:textColor="@color/tools_text_color_disable"
+                android:textSize="11sp"
+                app:layout_constraintTop_toBottomOf="@id/et_owner_password" />
+
+            <androidx.appcompat.widget.AppCompatCheckBox
+                android:id="@+id/cb_print"
+                android:layout_width="0dp"
+                android:layout_height="45dp"
+                android:layout_marginStart="16dp"
+                android:layout_marginEnd="16dp"
+                android:button="@drawable/tools_ic_digital_sign_checkbox"
+                android:enabled="false"
+                android:gravity="center_vertical"
+                android:paddingStart="8dp"
+                android:text="@string/tools_restrict_document_printing"
+                android:textColor="@color/tools_text_color_disable"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/tv_owner_functions" />
+
+            <androidx.appcompat.widget.AppCompatCheckBox
+                android:id="@+id/cb_copy"
+                android:layout_width="0dp"
+                android:layout_height="45dp"
+                android:layout_marginStart="16dp"
+                android:layout_marginEnd="16dp"
+                android:button="@drawable/tools_ic_digital_sign_checkbox"
+                android:enabled="false"
+                android:gravity="center_vertical"
+                android:paddingStart="8dp"
+                android:text="@string/tools_restrict_content_copying"
+                android:textColor="@color/tools_text_color_disable"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/cb_print" />
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_encryption_level"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="16dp"
+                android:layout_marginTop="16dp"
+                android:text="@string/tools_encryption_level"
+                android:textColor="@color/tools_text_color_primary"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/cb_copy" />
+
+            <LinearLayout
+                android:layout_width="wrap_content"
+                android:layout_height="35dp"
+                android:layout_marginStart="20dp"
+                android:layout_marginEnd="16dp"
+                android:background="@drawable/tools_bg_import_certificate_digital_id_item"
+                android:gravity="center_vertical"
+                app:layout_constraintBottom_toBottomOf="@id/tv_encryption_level"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintHorizontal_bias="1"
+                app:layout_constraintStart_toEndOf="@id/tv_encryption_level"
+                app:layout_constraintTop_toTopOf="@id/tv_encryption_level">
+
+                <androidx.appcompat.widget.AppCompatSpinner
+                    android:id="@+id/spinner_cryptographic_level"
+                    android:layout_width="170dp"
+                    android:layout_height="match_parent"
+                    android:dropDownSelector="@color/tools_color_primary"
+                    android:popupBackground="@drawable/tools_common_window_bg" />
+
+            </LinearLayout>
 
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/tv_owner_functions"
-        android:layout_width="match_parent"
-        android:layout_height="28dp"
-        android:layout_marginTop="8dp"
-        android:background="@color/tools_reader_setting_head_bg_color"
-        android:gravity="center_vertical"
-        android:paddingStart="16dp"
-        android:paddingEnd="16dp"
-        android:text="@string/tools_also_entrypts_the_followint_fuctions"
-        android:textColor="@color/tools_text_color_disable"
-        android:textSize="11sp"
-        app:layout_constraintTop_toBottomOf="@id/et_owner_password" />
-
-    <androidx.appcompat.widget.AppCompatCheckBox
-        android:id="@+id/cb_print"
-        android:layout_width="0dp"
-        android:layout_height="45dp"
-        android:layout_marginStart="16dp"
-        app:layout_constraintEnd_toEndOf="parent"
-        android:layout_marginEnd="16dp"
-        android:button="@drawable/tools_ic_digital_sign_checkbox"
-        android:gravity="center_vertical"
-        android:paddingStart="8dp"
-        android:text="@string/tools_print"
-        android:enabled="false"
-        android:textColor="@color/tools_text_color_disable"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/tv_owner_functions" />
-
-    <androidx.appcompat.widget.AppCompatCheckBox
-        android:id="@+id/cb_copy"
-        android:layout_width="0dp"
-        android:layout_height="45dp"
-        android:layout_marginStart="16dp"
-        android:button="@drawable/tools_ic_digital_sign_checkbox"
-        android:gravity="center_vertical"
-        app:layout_constraintEnd_toEndOf="parent"
-        android:layout_marginEnd="16dp"
-        android:paddingStart="8dp"
-        android:enabled="false"
-        android:text="@string/tools_copy"
-        android:textColor="@color/tools_text_color_disable"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/cb_print" />
-
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/tv_cryptographic_level"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="16dp"
-        android:text="@string/tools_cryptographic_level"
-        android:textColor="@color/tools_text_color_primary"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/cb_copy" />
-
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/tv_cryptographic_level_value"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginEnd="16dp"
-        android:drawableEnd="@drawable/tools_ic_right_arrow"
-        android:gravity="center_vertical"
-        android:textColor="@color/tools_text_color_primary"
-        app:layout_constraintBaseline_toBaselineOf="@id/tv_cryptographic_level"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintHorizontal_bias="1"
-        app:layout_constraintStart_toEndOf="@id/tv_cryptographic_level"
-        tools:text="128 - bit RC4" />
 
+        </androidx.constraintlayout.widget.ConstraintLayout>
+    </ScrollView>
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 33 - 4
ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_input_owner_pwd_dialog.xml

@@ -22,7 +22,7 @@
             android:layout_height="wrap_content"
             android:layout_marginHorizontal="24dp"
             android:gravity="center_vertical"
-            android:text="@string/tools_input_owner_permission"
+            android:text="@string/tools_enter_password"
             android:textColor="@color/tools_text_color_primary"
             android:textSize="16sp"
             app:layout_constraintEnd_toEndOf="parent"
@@ -37,12 +37,41 @@
             android:layout_marginHorizontal="20dp"
             android:layout_marginTop="8dp"
             android:gravity="center_vertical"
-            android:hint="@string/tools_enter_password_here"
             android:singleLine="true"
             android:textSize="13sp"
             android:inputType="textPassword"
             app:layout_constraintTop_toBottomOf="@id/tv_title" />
 
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_input_visible"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:layout_marginEnd="8dp"
+            android:src="@drawable/tools_btn_eyes_visible_selector"
+            app:layout_constraintBottom_toBottomOf="@id/et_password"
+            app:layout_constraintEnd_toEndOf="@id/et_password"
+            app:layout_constraintTop_toTopOf="@id/et_password" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/tools_password_error"
+            app:layout_constraintTop_toBottomOf="@id/et_password"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0"
+            android:layout_marginHorizontal="24dp"
+            app:layout_constrainedWidth="true"
+            android:layout_marginTop="4dp"
+            android:id="@+id/tv_pwd_error"
+            android:textSize="12sp"
+            android:visibility="invisible"
+            android:textColor="@color/tools_error"
+            />
+
+
+
         <LinearLayout
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -50,7 +79,7 @@
             android:layout_marginTop="12dp"
             android:orientation="horizontal"
             app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/et_password">
+            app:layout_constraintTop_toBottomOf="@id/tv_pwd_error">
 
             <Button
                 android:id="@+id/btn_cancel"
@@ -63,7 +92,7 @@
                 android:id="@+id/btn_confirm"
                 style="@style/tools_dialog_button_style"
                 android:background="@drawable/tools_common_btn_corner_ripple"
-                android:text="@string/tools_okay"
+                android:text="@string/contextmenu_done"
                 tools:textColor="@color/tools_normal_btn_text_color" />
 
         </LinearLayout>

+ 0 - 87
ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_save_dialog.xml

@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center">
-
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:layout_width="@dimen/tools_dialog_layout_width"
-        android:layout_height="wrap_content"
-        android:paddingTop="24dp"
-        android:paddingBottom="8dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <androidx.appcompat.widget.AppCompatTextView
-            android:id="@+id/tv_title"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:gravity="center_vertical"
-            android:layout_marginHorizontal="24dp"
-            android:textColor="@color/tools_text_color_primary"
-            app:layout_constraintEnd_toEndOf="parent"
-            android:textSize="16sp"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent"
-            android:text="@string/tools_save_document_as" />
-
-
-        <androidx.appcompat.widget.AppCompatEditText
-            android:layout_width="match_parent"
-            android:layout_height="40dp"
-            app:layout_constraintTop_toBottomOf="@id/tv_title"
-            android:layout_marginHorizontal="20dp"
-            android:layout_marginTop="8dp"
-            android:id="@+id/et_file_name"
-            android:textSize="13sp"
-            android:singleLine="true"
-            tools:hint="ComPDFKit.pdf"
-            android:gravity="center_vertical"
-            />
-
-        <androidx.appcompat.widget.AppCompatTextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginHorizontal="24dp"
-            app:layout_constraintTop_toBottomOf="@id/et_file_name"
-            android:id="@+id/tv_save_location"
-            android:textColor="@color/tools_text_color_secondary"
-            android:text="@string/tools_file_location"
-            android:textSize="13sp"
-            android:layout_marginTop="4dp"
-            tools:text="file location\nsdcard/Downloads/compdfkit"
-            />
-
-        <LinearLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="end"
-            android:layout_marginTop="12dp"
-            android:orientation="horizontal"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/tv_save_location">
-
-            <Button
-                android:id="@+id/btn_cancel"
-                style="@style/tools_dialog_button_style"
-                android:background="@drawable/tools_common_btn_corner_ripple"
-                android:text="@string/tools_cancel"
-                tools:textColor="@color/tools_normal_btn_text_color" />
-
-            <Button
-                android:id="@+id/btn_confirm"
-                style="@style/tools_dialog_button_style"
-                android:background="@drawable/tools_common_btn_corner_ripple"
-                android:text="@string/tools_okay"
-                tools:textColor="@color/tools_normal_btn_text_color" />
-
-        </LinearLayout>
-
-
-    </androidx.constraintlayout.widget.ConstraintLayout>
-
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 49 - 0
ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_watermark_edit_dialog.xml

@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.compdfkit.tools.common.views.CToolBar
+        android:id="@+id/tool_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+        android:elevation="4dp"
+        android:title="@string/tools_document_watermark"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <androidx.appcompat.widget.AppCompatButton
+            android:id="@+id/btn_done"
+            android:layout_width="wrap_content"
+            android:layout_height="32dp"
+            android:layout_gravity="end|center_vertical"
+            android:layout_marginEnd="16dp"
+            android:background="@drawable/tools_properties_signature_add_sign"
+            android:minWidth="70dp"
+            android:text="@string/tools_page_edit_toolbar_done"
+            android:textColor="@color/tools_color_accent"
+            android:textSize="16sp" />
+
+    </com.compdfkit.tools.common.views.CToolBar>
+
+    <com.compdfkit.tools.security.watermark.view.CWatermarkPageView
+        android:id="@+id/watermark_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_margin="4dp"
+        app:layout_constraintBottom_toTopOf="@id/watermark_toolbar"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar" />
+
+    <com.compdfkit.tools.security.watermark.CWatermarkToolBar
+        android:id="@+id/watermark_toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/watermark_view" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 35 - 0
ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_watermark_page_fragment.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:background="@color/tools_style_content_bg"
+    android:paddingHorizontal="8dp"
+    android:paddingTop="8dp"
+    android:layout_height="wrap_content">
+
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_page_image"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        android:background="@android:color/holo_red_dark"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"/>
+
+
+    <com.compdfkit.tools.security.watermark.view.WaterMarkTestView
+        android:id="@+id/watermark_view"
+        android:layout_width="match_parent"
+        android:layout_height="300dp"
+        app:frameColor="@color/tools_color_accent"
+        app:frameWidth="5dp"
+        android:layout_gravity="center"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 152 - 0
ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_watermark_text_style_fragment.xml

@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_rootView"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:animateLayoutChanges="true">
+
+
+        <com.compdfkit.tools.common.views.pdfproperties.colorlist.ColorListView
+            android:id="@+id/border_color_list_view"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            android:title="@string/tools_text_color" />
+
+        <com.compdfkit.tools.common.utils.view.sliderbar.CSliderBar
+            android:id="@+id/slider_bar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:max="255"
+            android:progress="255"
+            app:layout_constraintTop_toBottomOf="@id/border_color_list_view"
+            app:tools_slider_bar_value_show_type="percentage" />
+
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_font_type"
+            style="@style/tools_style_fragment_sub_title_style"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/tools_annot_font"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/slider_bar" />
+
+        <androidx.appcompat.widget.AppCompatSpinner
+            android:id="@+id/spinner_font"
+            android:layout_width="0dp"
+            android:layout_height="35dp"
+            android:layout_marginStart="20dp"
+            android:layout_marginEnd="16dp"
+            android:dropDownSelector="@color/tools_color_primary"
+            android:popupBackground="@drawable/tools_common_window_bg"
+            app:layout_constraintBottom_toBottomOf="@id/tv_font_type"
+            app:layout_constraintEnd_toStartOf="@id/iv_font_bold"
+            app:layout_constraintStart_toEndOf="@id/tv_font_type"
+            app:layout_constraintTop_toTopOf="@id/tv_font_type" />
+
+        <View
+            android:id="@+id/font_line"
+            style="@style/tools_style_fragment_line"
+            android:layout_width="0dp"
+            android:layout_marginHorizontal="12dp"
+            app:layout_constraintStart_toStartOf="@id/spinner_font"
+            app:layout_constraintEnd_toEndOf="@id/spinner_font"
+            app:layout_constraintTop_toBottomOf="@id/spinner_font"
+            />
+
+
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_font_italic"
+            android:layout_width="40dp"
+            android:layout_height="32dp"
+            android:layout_marginEnd="16dp"
+            android:background="@drawable/tools_annotation_font_italic_bg"
+            android:gravity="center"
+            android:padding="5dp"
+            app:layout_constraintBottom_toBottomOf="@id/tv_font_type"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="@id/tv_font_type"
+            app:srcCompat="@drawable/tools_ic_font_italic"
+            app:tint="@color/tools_font_style_iv_color" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_font_bold"
+            android:layout_width="40dp"
+            android:layout_height="32dp"
+            android:background="@drawable/tools_annotation_font_bold_bg"
+            android:gravity="center"
+            android:padding="5dp"
+            app:layout_constraintBottom_toBottomOf="@id/tv_font_type"
+            app:layout_constraintEnd_toStartOf="@id/iv_font_italic"
+            app:layout_constraintTop_toTopOf="@id/tv_font_type"
+            app:srcCompat="@drawable/tools_ic_font_bold"
+            app:tint="@color/tools_font_style_iv_color" />
+
+
+        <com.compdfkit.tools.common.utils.view.sliderbar.CSliderBar
+            android:id="@+id/font_size_slider_bar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:max="100"
+            app:tools_value_unit="pt"
+            android:progress="1"
+            app:layout_constraintTop_toBottomOf="@id/iv_font_bold"
+            app:tools_slider_bar_value_show_type="source"
+            android:title="@string/tools_annot_font_size" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_location"
+            style="@style/tools_style_fragment_sub_title_style"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:text="@string/tools_location"
+            android:layout_marginBottom="24dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@id/font_size_slider_bar" />
+
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_location_bottom"
+            android:layout_width="40dp"
+            android:layout_height="32dp"
+            android:layout_marginEnd="16dp"
+            android:background="@drawable/tools_annotation_font_italic_bg"
+            android:gravity="center"
+            android:padding="5dp"
+            app:layout_constraintBottom_toBottomOf="@id/tv_location"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="@id/tv_location"
+            app:srcCompat="@drawable/tools_ic_watermark_location_top"
+            app:tint="@color/tools_font_style_iv_color" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_location_top"
+            android:layout_width="40dp"
+            android:layout_height="32dp"
+            android:background="@drawable/tools_annotation_font_bold_bg"
+            android:gravity="center"
+            android:padding="5dp"
+            app:layout_constraintBottom_toBottomOf="@id/tv_location"
+            app:layout_constraintEnd_toStartOf="@id/iv_location_bottom"
+            app:layout_constraintTop_toTopOf="@id/tv_location"
+            app:srcCompat="@drawable/tools_ic_watermark_location_bottom"
+            app:tint="@color/tools_font_style_iv_color" />
+
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</androidx.core.widget.NestedScrollView>
+

+ 129 - 0
ComPDFKit_Tools/src/main/res/layout/tools_cpdf_security_watermark_tool_bar.xml

@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="?android:attr/actionBarSize"
+    android:background="@color/tools_color_primary">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_add_text_watermark"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="80dp"
+        android:layout_marginVertical="4dp"
+        android:background="@drawable/tools_signature_toolbar_btn_corner_status_bg"
+        android:foreground="@drawable/tools_common_btn_corner_ripple"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/cl_add_image_watermark"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_add_text_watermark"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            app:layout_constraintVertical_chainStyle="packed"
+            app:layout_constraintVertical_bias="0.65"
+            android:src="@drawable/tools_ic_annotation_freetext"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintBottom_toTopOf="@id/tv_add_text_watermark"
+            app:tint="@color/tools_text_color_primary" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_add_text_watermark"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/tools_custom_stamp_text"
+            app:layout_constraintBottom_toBottomOf="parent"
+            android:textColor="@color/tools_text_color_primary"
+            app:layout_constraintTop_toBottomOf="@id/iv_add_text_watermark"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_add_image_watermark"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="80dp"
+        android:layout_marginVertical="4dp"
+        android:background="@drawable/tools_signature_toolbar_btn_corner_status_bg"
+        android:foreground="@drawable/tools_common_btn_corner_ripple"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/cl_delete_watermark"
+        app:layout_constraintStart_toEndOf="@id/cl_add_text_watermark"
+        app:layout_constraintTop_toTopOf="parent">
+
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_add_image_watermark"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            app:layout_constraintVertical_bias="0.65"
+            android:src="@drawable/tools_ic_annotation_pic"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toTopOf="@id/tv_add_image_watermark"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:tint="@color/tools_text_color_primary" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_add_image_watermark"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            app:layout_constraintBottom_toBottomOf="parent"
+            android:text="@string/tools_image"
+            android:textColor="@color/tools_text_color_primary"
+            app:layout_constraintTop_toBottomOf="@id/iv_add_image_watermark"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+           />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_delete_watermark"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="80dp"
+        android:layout_marginVertical="4dp"
+        android:background="@drawable/tools_signature_toolbar_btn_corner_status_bg"
+        android:foreground="@drawable/tools_common_btn_corner_ripple"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@id/cl_add_image_watermark"
+        app:layout_constraintTop_toTopOf="parent">
+
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_delete_watermark"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            app:layout_constraintVertical_bias="0.65"
+            app:layout_constraintBottom_toTopOf="@id/tv_delete_watermark"
+            android:src="@drawable/tools_ic_pageedit_delete"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:tint="@color/tools_text_color_primary" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_delete_watermark"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/tools_delete"
+            app:layout_constraintBottom_toBottomOf="parent"
+            android:textColor="@color/tools_text_color_primary"
+            app:layout_constraintTop_toBottomOf="@id/iv_delete_watermark"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 11 - 7
ComPDFKit_Tools/src/main/res/layout/tools_file_directory_dialog.xml

@@ -22,7 +22,6 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
-        android:background="@color/tools_reader_setting_head_bg_color"
         app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
         app:layout_constraintEnd_toEndOf="parent"
         android:paddingHorizontal="8dp"
@@ -30,6 +29,13 @@
         app:layout_constraintTop_toBottomOf="@id/tool_bar"
         tools:listitem="@layout/tools_file_directory_list_title_item" />
 
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0.5dp"
+        android:background="@color/tools_item_dividing_line_color"
+        app:layout_constraintTop_toBottomOf="@id/rv_folder_title"
+        android:id="@+id/line"
+        />
     <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/recycler_view"
         android:layout_width="match_parent"
@@ -39,22 +45,20 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintVertical_bias="0"
         app:layout_constrainedHeight="true"
-        app:layout_constraintTop_toBottomOf="@id/rv_folder_title"
+        app:layout_constraintTop_toBottomOf="@id/line"
         tools:listitem="@layout/tools_file_directory_list_item" />
 
 
     <androidx.appcompat.widget.AppCompatButton
         android:id="@+id/btn_ok"
         android:layout_width="match_parent"
-        android:layout_height="40dp"
-        android:layout_marginHorizontal="16dp"
-        android:layout_marginBottom="16dp"
-        android:background="@drawable/tools_sign_cert_info_btn_bg"
+        android:layout_height="56dp"
+        android:background="@color/tools_directory_item_title_color"
         android:foreground="@drawable/tools_common_btn_corner_ripple"
         android:gravity="center"
         android:text="@string/tools_page_edit_toolbar_done"
         android:textAllCaps="false"
-        android:textColor="@color/tools_color_accent"
+        android:textColor="@android:color/white"
         android:textSize="16sp"
         android:textStyle="bold"
         app:layout_constraintBottom_toBottomOf="parent"

+ 4 - 12
ComPDFKit_Tools/src/main/res/layout/tools_file_directory_list_item.xml

@@ -3,14 +3,14 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
-    android:layout_height="60dp"
+    android:layout_height="65dp"
     android:background="@drawable/tools_common_btn_rectangle_ripple">
 
     <androidx.appcompat.widget.AppCompatImageView
         android:id="@+id/iv_image"
-        android:layout_width="24dp"
-        android:layout_height="24dp"
-        android:layout_marginStart="24dp"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_marginStart="16dp"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
@@ -35,13 +35,5 @@
         app:layout_constraintTop_toTopOf="parent"
         tools:text="Folder" />
 
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="1px"
-        android:background="@color/tools_item_dividing_line_color"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        />
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 2 - 2
ComPDFKit_Tools/src/main/res/layout/tools_file_directory_list_title_item.xml

@@ -3,7 +3,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="wrap_content"
-    android:layout_height="30dp"
+    android:layout_height="40dp"
     android:background="@drawable/tools_common_btn_rectangle_ripple">
 
     <androidx.appcompat.widget.AppCompatTextView
@@ -14,7 +14,7 @@
         android:layout_marginEnd="8dp"
         android:ellipsize="start"
         android:singleLine="true"
-        android:textColor="@color/tools_text_color_primary"
+        android:textColor="@color/tools_directory_item_title_color"
         app:layout_constrainedWidth="true"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"

+ 1 - 1
ComPDFKit_Tools/src/main/res/layout/tools_file_directory_list_title_separator_item.xml

@@ -3,7 +3,7 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="wrap_content"
-    android:layout_height="30dp"
+    android:layout_height="40dp"
     >
 
     <androidx.appcompat.widget.AppCompatImageView

+ 1 - 9
ComPDFKit_Tools/src/main/res/layout/tools_pdf_mode_switch_dialog_fragment.xml

@@ -69,17 +69,9 @@
             android:layout_height="60dp"
             android:visibility="gone"
             tools:visibility="visible"
-            android:drawableStart="@drawable/tools_ic_digital_signature"
+            android:drawableStart="@drawable/tools_mode_switch_digital_signature"
             android:text="@string/tools_digital_signature" />
 
-        <androidx.appcompat.widget.AppCompatRadioButton
-            android:id="@+id/r_btn_security_mode"
-            style="@style/tools_pdf_reader_mode_radio_button_style"
-            android:layout_height="60dp"
-            android:visibility="gone"
-            tools:visibility="visible"
-            android:drawableStart="@drawable/tools_ic_digital_signature"
-            android:text="@string/tools_security" />
 
     </RadioGroup>
 

+ 23 - 1
ComPDFKit_Tools/src/main/res/values/tools_attrs.xml

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:tools="http://schemas.android.com/tools">
+<resources xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android">
 
     <attr name="tools_show_title" format="boolean"/>
 
@@ -104,4 +104,26 @@
         </attr>
     </declare-styleable>
 
+
+    <!--水印-->
+    <declare-styleable name="WatermarkView" tools:ignore="ResourceName">
+        <attr name="src" format="reference" tools:ignore="ResourceName" />            <!-- 用于缩放旋转的图标 -->
+        <attr name="editable" format="boolean" tools:ignore="ResourceName"/>          <!-- 是否SingleTouchView处于可编辑状态 -->
+        <attr name="frameColor" format="color" tools:ignore="ResourceName"/>         <!-- 边框颜色 -->
+        <attr name="frameWidth" format="dimension" tools:ignore="ResourceName"/>     <!-- 边框线宽度 -->
+        <attr name="framePadding" format="dimension" tools:ignore="ResourceName"/>   <!-- 边框与图片的间距 -->
+        <attr name="controlDrawableWidth" format="dimension" tools:ignore="ResourceName"/> <!-- 控制图标宽-->
+        <attr name="controlDrawableHeight" format="dimension" tools:ignore="ResourceName"/> <!-- 控制图标高-->
+        <attr name="degree" format="float" tools:ignore="ResourceName"/>             <!-- 旋转角度 -->
+        <attr name="scale" format="float" tools:ignore="ResourceName"/>              <!-- 缩放比例 -->
+        <attr name="controlDrawable" format="reference" tools:ignore="ResourceName"/> <!-- 控制图标 -->
+        <attr name="controlLocation" >                     <!-- 控制图标的位置 -->
+            <enum name="left_top" value="0" />
+            <enum name="right_top" value="1" />
+            <enum name="right_bottom" value="2" />
+            <enum name="left_bottom" value="3" />
+        </attr>
+    </declare-styleable>
+
+
 </resources>

+ 1 - 1
ComPDFKit_Tools/src/main/res/values/tools_colors.xml

@@ -60,5 +60,5 @@
     <color name="tools_form_default_bg_color">#CCE5E5FF</color>
     <color name="tools_sign_preview_text_color">#232531</color>
     <color name="tools_sign_preview_bg_color">#F4F7FF</color>
-
+    <color name="tools_directory_item_title_color">#4982E6</color>
 </resources>

+ 16 - 2
ComPDFKit_Tools/src/main/res/values/tools_strings.xml

@@ -418,12 +418,24 @@
 
 
     <!--    Security Mode Start! -->
+    <string name="tools_files_security">Files Security</string>
+    <string name="tools_files_watermark">Files Watermark</string>
+    <string name="tools_security_settings">Security Settings</string>
+    <string name="tools_set_password">Set Password</string>
+    <string name="tools_enter_password">Enter the Password</string>
+    <string name="tools_enter_password_can_not_be_empty">The password can\'t be empty.</string>
+    <string name="tools_please_enter_owner_password">Please enter the owner\'s password</string>
+    <string name="tools_restrict_document_printing">Restrict document printing</string>
+    <string name="tools_restrict_content_copying">Restrict content copying</string>
+    <string name="tools_encryption_level">Encryption Level</string>
+    <string name="tools_password_error">Password Error</string>
+
+
     <string name="tools_security">Security</string>
     <string name="tools_add_security">Add Security</string>
     <string name="tools_add_watermark">Add Watermark</string>
     <string name="tools_document_encryption">Document encryption</string>
     <string name="tools_setting_password">Setting Password</string>
-    <string name="tools_enter_password">Enter Password</string>
     <string name="tools_setting_permission_password">Setting Permission Password</string>
     <string name="tools_also_entrypts_the_followint_fuctions">Also Encrypts the following functions</string>
     <string name="tools_print">Print</string>
@@ -439,6 +451,8 @@
     <string name="tools_encryption_256_aes">256-bit AES</string>
     <string name="tools_input_owner_permission">请输入权限密码后下一步</string>
     <string name="tools_enter_password_here">Enter password here</string>
-
+    <string name="tools_document_watermark">Document Watermark</string>
+    <string name="tools_text_watermark">Text Watermark</string>
+    <string name="tools_watermark">Watermark</string>
     <!--    Security Mode End-->
 </resources>

+ 0 - 13
PDFViewer/src/main/java/com/compdfkit/pdfviewer/CSampleScreenManager.java

@@ -42,7 +42,6 @@ public class CSampleScreenManager {
             binding.editToolBar.setVisibility(View.GONE);
             binding.formToolBar.setVisibility(View.GONE);
             binding.signatureToolBar.setVisibility(View.GONE);
-            binding.securityToolBar.setVisibility(View.GONE);
             constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
         } else if (mode == CPreviewMode.Edit) {
             fillScreenManager.bindBottomToolViewList(binding.flBottomToolBar);
@@ -50,7 +49,6 @@ public class CSampleScreenManager {
             binding.editToolBar.setVisibility(View.VISIBLE);
             binding.formToolBar.setVisibility(View.GONE);
             binding.signatureToolBar.setVisibility(View.GONE);
-            binding.securityToolBar.setVisibility(View.GONE);
             constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
         } else if (mode == CPreviewMode.Form){
             fillScreenManager.bindBottomToolViewList(binding.flBottomToolBar);
@@ -58,8 +56,6 @@ public class CSampleScreenManager {
             binding.editToolBar.setVisibility(View.GONE);
             binding.formToolBar.setVisibility(View.VISIBLE);
             binding.signatureToolBar.setVisibility(View.GONE);
-            binding.securityToolBar.setVisibility(View.GONE);
-
             constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
         } else if (mode == CPreviewMode.Signature){
             fillScreenManager.bindBottomToolViewList(binding.flBottomToolBar);
@@ -67,15 +63,6 @@ public class CSampleScreenManager {
             binding.editToolBar.setVisibility(View.GONE);
             binding.formToolBar.setVisibility(View.GONE);
             binding.signatureToolBar.setVisibility(View.VISIBLE);
-            binding.securityToolBar.setVisibility(View.GONE);
-            constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
-        } else if (mode == CPreviewMode.Security){
-            fillScreenManager.bindBottomToolViewList(binding.flBottomToolBar);
-            binding.annotationToolBar.setVisibility(View.GONE);
-            binding.editToolBar.setVisibility(View.GONE);
-            binding.formToolBar.setVisibility(View.GONE);
-            binding.signatureToolBar.setVisibility(View.GONE);
-            binding.securityToolBar.setVisibility(View.VISIBLE);
             constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
         }
         constraintSetUtils.apply(constraintSet, binding.getRoot());

+ 49 - 10
PDFViewer/src/main/java/com/compdfkit/pdfviewer/MainActivity.java

@@ -14,14 +14,17 @@ import static com.compdfkit.ui.contextmenu.CPDFContextMenuShowHelper.AddEditImag
 import static com.compdfkit.ui.contextmenu.CPDFContextMenuShowHelper.ReplaceEditImageArea;
 
 import android.Manifest;
+import android.app.AlertDialog;
 import android.content.Intent;
 import android.os.Build;
 import android.os.Bundle;
+import android.text.InputType;
 import android.view.View;
 import android.widget.Toast;
 
 import androidx.activity.result.ActivityResultLauncher;
 import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
 
 import com.compdfkit.core.annotation.CPDFAnnotation;
 import com.compdfkit.core.annotation.form.CPDFComboboxWidget;
@@ -34,9 +37,11 @@ import com.compdfkit.tools.common.basic.activity.CBasicPDFActivity;
 import com.compdfkit.tools.common.contextmenu.CPDFContextMenuHelper;
 import com.compdfkit.tools.common.utils.CFileUtils;
 import com.compdfkit.tools.common.utils.CPermissionUtil;
+import com.compdfkit.tools.common.utils.CToastUtil;
 import com.compdfkit.tools.common.utils.activitycontracts.CSelectPDFDocumentResultContract;
 import com.compdfkit.tools.common.utils.annotation.CPDFAnnotationManager;
 import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
+import com.compdfkit.tools.common.utils.dialog.CEditDialog;
 import com.compdfkit.tools.common.utils.task.CExtractAssetFileTask;
 import com.compdfkit.tools.common.utils.threadpools.CThreadPoolUtils;
 import com.compdfkit.tools.common.utils.window.CPopupMenuWindow;
@@ -51,10 +56,10 @@ import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.manager.CStyleMan
 import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
 import com.compdfkit.tools.common.views.pdfview.CPreviewMode;
 import com.compdfkit.tools.contenteditor.CPDFEditPage;
-import com.compdfkit.tools.forms.pdfproperties.pdfcombobox.CustomComboBoxWidgetImpl;
-import com.compdfkit.tools.forms.pdfproperties.pdflistbox.CustomListBoxWidgetImpl;
-import com.compdfkit.tools.forms.pdfproperties.pdfsign.CustomSignatureWidgetImpl;
 import com.compdfkit.tools.forms.pdfproperties.pdfsign.SignatureWidgetImpl;
+import com.compdfkit.tools.security.encryption.CDocumentEncryptionDialog;
+import com.compdfkit.tools.security.encryption.CInputOwnerPwdDialog;
+import com.compdfkit.tools.security.watermark.CWatermarkEditDialog;
 import com.compdfkit.tools.signature.CertificateDigitalDatas;
 import com.compdfkit.tools.signature.bean.CPDFDocumentSignInfo;
 import com.compdfkit.tools.signature.info.signlist.CPDFCertDigitalSignListDialog;
@@ -117,7 +122,6 @@ public class MainActivity extends CBasicPDFActivity {
         initFormToolbar();
         initEditBar();
         initSignatureToolbar();
-        initSecurityToolbar();
         setPreviewMode(CPreviewMode.Viewer);
         onDoNext();
     }
@@ -127,7 +131,7 @@ public class MainActivity extends CBasicPDFActivity {
             CFileUtils.takeUriPermission(this, getIntent().getData());
             binding.pdfView.openPDF(getIntent().getData());
             binding.editToolBar.setEditMode(false);
-        }else {
+        } else {
             CExtractAssetFileTask.extract(this, QUICK_START_GUIDE, QUICK_START_GUIDE, (filePath) -> {
                         binding.pdfView.openPDF(filePath);
                         binding.editToolBar.setEditMode(false);
@@ -223,7 +227,6 @@ public class MainActivity extends CBasicPDFActivity {
         binding.pdfToolBar.addMode(CPreviewMode.Edit);
         binding.pdfToolBar.addMode(CPreviewMode.Form);
         binding.pdfToolBar.addMode(CPreviewMode.Signature);
-        binding.pdfToolBar.addMode(CPreviewMode.Security);
         binding.pdfToolBar.setPreviewModeChangeListener(this::setPreviewMode);
         binding.pdfToolBar.setSearchBtnClickListener(v -> {
             if (binding.pdfView.getCPdfReaderView().getEditManager().isEditMode()) {
@@ -283,6 +286,29 @@ public class MainActivity extends CBasicPDFActivity {
                     }
                 });
             });
+            menuWindow.addItem(R.drawable.tools_ic_add_security, R.string.tools_files_security, v1 -> {
+                CPDFDocument document = binding.pdfView.getCPdfReaderView().getPDFDocument();
+                if (document.getPermissions() == CPDFDocument.PDFDocumentPermissions.PDFDocumentPermissionsUser) {
+                    CInputOwnerPwdDialog inputOwnerPwdDialog = CInputOwnerPwdDialog.newInstance();
+                    inputOwnerPwdDialog.setDocument(document);
+                    inputOwnerPwdDialog.setCancelClickListener(v2->{
+                        inputOwnerPwdDialog.dismiss();
+                    });
+                    inputOwnerPwdDialog.setConfirmClickListener(ownerPassword -> {
+                        document.reload(ownerPassword);
+                        showSettingEncryptionDialog();
+                        inputOwnerPwdDialog.dismiss();
+                    });
+                    inputOwnerPwdDialog.show(getSupportFragmentManager(), "inputPasswordDialog");
+                    return;
+                }
+                showSettingEncryptionDialog();
+            });
+            menuWindow.addItem(R.drawable.tools_ic_add_watermark, R.string.tools_files_watermark, v1 -> {
+                CWatermarkEditDialog watermarkEditDialog = CWatermarkEditDialog.newInstance();
+                watermarkEditDialog.initWithPDFView(binding.pdfView);
+                watermarkEditDialog.show(getSupportFragmentManager(), "watermarkEditDialog");
+            });
             menuWindow.addItem(R.drawable.tools_ic_document_info, R.string.tools_document_info, v1 -> {
                 showDocumentInfo(binding.pdfView);
             });
@@ -441,10 +467,6 @@ public class MainActivity extends CBasicPDFActivity {
         }
     }
 
-    private void initSecurityToolbar(){
-        binding.securityToolBar.initWithPDFView(binding.pdfView);
-    }
-
     private void selectDocument() {
         if (binding.pdfToolBar.getMode() == CPreviewMode.Edit) {
             binding.pdfView.exitEditMode();
@@ -526,6 +548,23 @@ public class MainActivity extends CBasicPDFActivity {
         }
     }
 
+    private void showSettingEncryptionDialog() {
+        CDocumentEncryptionDialog documentEncryptionDialog = CDocumentEncryptionDialog.newInstance();
+        documentEncryptionDialog.setDocument(binding.pdfView.getCPdfReaderView().getPDFDocument());
+        documentEncryptionDialog.setEncryptionResultListener((isRemoveSecurity, result, filePath, passowrd) -> {
+            binding.pdfView.openPDF(filePath, passowrd);
+            documentEncryptionDialog.dismiss();
+            int msgResId;
+            if (isRemoveSecurity) {
+                msgResId = result ? R.string.tools_password_remove_success : R.string.tools_password_remove_fail;
+            } else {
+                msgResId = result ? R.string.tools_set_password_successfully : R.string.tools_set_password_failures;
+            }
+            CToastUtil.showLongToast(this, msgResId);
+        });
+        documentEncryptionDialog.show(getSupportFragmentManager(), "documentEncryption");
+    }
+
     @Override
     protected void registerFormHelper(CPDFViewCtrl pdfView) {
         super.registerFormHelper(pdfView);

+ 0 - 6
PDFViewer/src/main/res/layout/pdf_sample_activity.xml

@@ -103,12 +103,6 @@
             android:layout_height="?android:attr/actionBarSize"
             app:layout_constraintBottom_toBottomOf="parent" />
 
-        <com.compdfkit.tools.security.CSecurityToolBar
-            android:id="@+id/security_tool_bar"
-            android:layout_width="match_parent"
-            android:visibility="gone"
-            android:layout_height="?android:attr/actionBarSize"
-            app:layout_constraintBottom_toBottomOf="parent"/>
     </FrameLayout>