Browse Source

PDFTools(Android) - 1.新增Ink注释控制板 2.Ink注释交互

liuxiaolong 1 year ago
parent
commit
3c909aff0a
37 changed files with 1153 additions and 54 deletions
  1. 1 0
      .gitignore
  2. 18 2
      annotation-ctrl-demo/src/main/java/com/compdfkit/demo/annotation/MainActivity.java
  3. 24 13
      annotation-ctrl-demo/src/main/res/layout/activity_main.xml
  4. 2 0
      compdfkit-repo/compdfkit-kmhandwriting/build.gradle
  5. BIN
      compdfkit-repo/compdfkit-kmhandwriting/kmhandwriting-v1.0.0.0(202112211011)_release.aar
  6. 2 0
      compdfkit-tools/build.gradle
  7. 3 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/CAnnotStyleDialogFragment.java
  8. 27 1
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfannotstyle/CAnnotStyle.java
  9. 5 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfannotstyle/CBasicOnStyleChangeListener.java
  10. 11 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfannotstyle/data/CPropertiesFragmentDatas.java
  11. 39 11
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfannotstyle/manager/CAnnotStyleManager.java
  12. 1 1
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfmarkup/CLinkStyleFragment.java
  13. 111 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdflnk/CInkCtrlView.java
  14. 69 2
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdflnk/CInkStyleFragment.java
  15. 160 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdflnk/CPDFFakeInkAnnotAttachHelper.java
  16. 2 3
      compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfmarkup/CMarkupStyleFragment.java
  17. 144 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/utils/view/CSineCurveView.java
  18. 44 10
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfannotationbar/CAnnotationToolbar.java
  19. 5 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/basic/CBasicPropertiesFragment.java
  20. 68 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CAnnotInkPreviewView.java
  21. 2 2
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CAnnotMarkupPreviewView.java
  22. 1 1
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CAnnotNotePreviewView.java
  23. 9 4
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CBasicAnnotPreviewView.java
  24. 11 2
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CStylePreviewView.java
  25. 138 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/sliderbar/CBorderWidthSliderBar.java
  26. 3 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/sliderbar/CSliderBar.java
  27. 6 0
      compdfkit-tools/src/main/res/drawable/tools_annot_border_slider_bar_size_bg.xml
  28. 30 0
      compdfkit-tools/src/main/res/drawable/tools_annot_properties_ink_btn_bg.xml
  29. 6 0
      compdfkit-tools/src/main/res/drawable/tools_annot_properties_ink_ctrl_bg.xml
  30. 9 0
      compdfkit-tools/src/main/res/drawable/tools_ic_eraser.xml
  31. 89 0
      compdfkit-tools/src/main/res/layout/tools_annot_properties_ink_ctrl_layout.xml
  32. 56 0
      compdfkit-tools/src/main/res/layout/tools_common_border_width_slider_bar.xml
  33. 0 2
      compdfkit-tools/src/main/res/layout/tools_common_slider_bar.xml
  34. 46 0
      compdfkit-tools/src/main/res/layout/tools_properties_ink_style_fragment.xml
  35. 8 0
      compdfkit-tools/src/main/res/values/tools_attrs.xml
  36. 2 0
      compdfkit-tools/src/main/res/values/tools_strings.xml
  37. 1 0
      settings.gradle

+ 1 - 0
.gitignore

@@ -17,3 +17,4 @@ local.properties
 /compdfkit-repo/build/
 /compdfkit-repo/compdfkit/build/
 /compdfkit-repo/compdfkit-ui/build/
+/compdfkit-repo/compdfkit-kmhandwriting/build/

+ 18 - 2
annotation-ctrl-demo/src/main/java/com/compdfkit/demo/annotation/MainActivity.java

@@ -6,8 +6,11 @@ import android.view.View;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.core.content.ContextCompat;
 
+import com.compdfkit.core.annotation.CPDFAnnotation;
+import com.compdfkit.core.annotation.CPDFInkAnnotation;
 import com.compdfkit.core.annotation.CPDFTextAnnotation;
 import com.compdfkit.demo.annotation.databinding.ActivityMainBinding;
+import com.compdfkit.tools.annotation.pdfproperties.pdflnk.CPDFFakeInkAnnotAttachHelper;
 import com.compdfkit.tools.annotation.pdfproperties.pdfnote.CPDFtextAnnotAttachHelper;
 import com.compdfkit.tools.annotation.pdfproperties.pdfnote.CPDFtextAnnotImpl;
 import com.compdfkit.tools.common.utils.animation.CFillScreenManager;
@@ -51,21 +54,31 @@ public class MainActivity extends AppCompatActivity {
     }
 
     private void initListener() {
-        screenManager.bindTopToolView(binding.flTool);
+        screenManager.bindTopToolView(binding.flTool, binding.inkCtrlView);
         screenManager.bindBottomToolViewList(binding.annotationToolBar);
         screenManager.bindLeftToolViewList(binding.pdfView.indicatorView);
         screenManager.bindRightToolViewList(binding.pdfView.slideBar);
+
         binding.pdfView.setOnTapMainDocAreaCallback(() -> {
             screenManager.fillScreenChange(binding.flTool.getVisibility() == View.VISIBLE);
         });
+        binding.pdfView.addOnPDFFocusedTypeChangeListener(type -> {
+            if (type == CPDFAnnotation.Type.INK){
+                screenManager.showFromTop(binding.inkCtrlView, 200);
+            }else {
+                screenManager.hideFromTop(binding.inkCtrlView, 200);
+            }
+        });
 
         binding.pdfToolBar.addMode(CPDFToolbarPopupMenu.PreviewMode.Annotation);
         binding.pdfToolBar.setPreviewModeChangeListener((mode, title) -> {
             if (mode == CPDFToolbarPopupMenu.PreviewMode.PDFView) {
                 screenManager.hideFromBottom(binding.annotationToolBar, 200);
                 screenManager.removeToolView(binding.annotationToolBar);
+                screenManager.removeToolView(binding.inkCtrlView);
             } else {
                 screenManager.bindBottomToolViewList(binding.annotationToolBar);
+                screenManager.bindTopToolView(binding.inkCtrlView);
                 screenManager.showFromBottom(binding.annotationToolBar, 200);
             }
             binding.pdfView.setAllowAddAndEditAnnot(mode != CPDFToolbarPopupMenu.PreviewMode.PDFView);
@@ -118,6 +131,8 @@ public class MainActivity extends AppCompatActivity {
 
         binding.annotationToolBar.initWithPDFView(binding.pdfView);
         binding.annotationToolBar.setFragmentManager(getSupportFragmentManager());
+
+        binding.inkCtrlView.initWithPDFView(binding.pdfView);
     }
 
     private void initSearchBar() {
@@ -155,9 +170,10 @@ public class MainActivity extends AppCompatActivity {
                 .setShape(CAnnotationType.SQUARE, defaultColor, 255, defaultColor, 255, 5)
                 .setShape(CAnnotationType.CIRCLE, defaultColor, 255, defaultColor, 255, 5)
                 .setShape(CAnnotationType.LINE, defaultColor, 255, defaultColor, 255, 5)
-                .setInkAttribute(defaultColor, 255)
+                .setInkAttribute(defaultColor, 255, 10)
                 .init();
         binding.pdfView.getCPdfReaderView().getAnnotImplRegistry().registAttachHelper(CPDFTextAnnotation.class, CPDFtextAnnotAttachHelper.class);
         binding.pdfView.getCPdfReaderView().getAnnotImplRegistry().registImpl(CPDFTextAnnotation.class, CPDFtextAnnotImpl.class);
+//        binding.pdfView.getCPdfReaderView().getAnnotImplRegistry().registAttachHelper(CPDFInkAnnotation.class, CPDFFakeInkAnnotAttachHelper.class);
     }
 }

+ 24 - 13
annotation-ctrl-demo/src/main/res/layout/activity_main.xml

@@ -6,6 +6,22 @@
     android:layout_height="match_parent"
     tools:context=".MainActivity">
 
+
+
+
+    <com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl
+        android:id="@+id/pdf_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        app:tools_enable_page_indicator="true"
+        app:tools_enable_slider_bar="true"
+        app:tools_slider_bar_position="right"
+        app:layout_constrainedHeight="true"
+        app:layout_constraintTop_toTopOf="parent"
+        app:tools_page_indicator_margin_bottom="?android:attr/actionBarSize"
+        app:tools_slider_bar_icon="@drawable/tools_ic_pdf_slider_bar"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
     <FrameLayout
         android:id="@+id/fl_tool"
         android:layout_width="match_parent"
@@ -33,23 +49,18 @@
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent"
-             />
+            />
 
     </FrameLayout>
 
-    <com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl
-        android:id="@+id/pdf_view"
+    <com.compdfkit.tools.annotation.pdfproperties.pdflnk.CInkCtrlView
+        android:id="@+id/ink_ctrl_view"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:tools_enable_page_indicator="true"
-        app:tools_enable_slider_bar="true"
-        app:tools_slider_bar_position="right"
-        app:layout_constrainedHeight="true"
-        app:layout_constraintTop_toTopOf="parent"
-        app:tools_page_indicator_margin_bottom="?android:attr/actionBarSize"
-        app:tools_slider_bar_icon="@drawable/tools_ic_pdf_slider_bar"
-        app:layout_constraintBottom_toBottomOf="parent"/>
-
+        android:layout_height="wrap_content"
+        app:layout_constraintTop_toBottomOf="@id/fl_tool"
+        android:layout_marginHorizontal="16dp"
+        android:visibility="gone"
+        />
 
     <com.compdfkit.tools.common.views.pdfannotationbar.CAnnotationToolbar
         android:id="@+id/annotation_tool_bar"

+ 2 - 0
compdfkit-repo/compdfkit-kmhandwriting/build.gradle

@@ -0,0 +1,2 @@
+configurations.maybeCreate("default")
+artifacts.add("default", file('kmhandwriting-v1.0.0.0(202112211011)_release.aar'))

BIN
compdfkit-repo/compdfkit-kmhandwriting/kmhandwriting-v1.0.0.0(202112211011)_release.aar


+ 2 - 0
compdfkit-tools/build.gradle

@@ -40,9 +40,11 @@ android {
 }
 
 dependencies {
+
     api fileTree(include: ['*.jar'], dir: 'libs')
     api project(path:':compdfkit-repo:compdfkit')
     api project(path:':compdfkit-repo:compdfkit-ui')
+    api project(path:':compdfkit-repo:compdfkit-kmhandwriting')
 
     api 'com.github.bumptech.glide:glide:4.15.1'
     annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'

+ 3 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/CAnnotStyleDialogFragment.java

@@ -9,6 +9,7 @@
 
 package com.compdfkit.tools.annotation.pdfproperties;
 
+import android.content.DialogInterface;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -134,4 +135,6 @@ public class CAnnotStyleDialogFragment extends BottomSheetDialogFragment impleme
     public void addAnnotStyleChangeListener(CAnnotStyle.OnAnnotStyleChangeListener annotStyleChangeListener) {
         this.annotStyleChangeListenerList.add(annotStyleChangeListener);
     }
+
+
 }

+ 27 - 1
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfannotstyle/CAnnotStyle.java

@@ -41,7 +41,9 @@ public class CAnnotStyle implements Parcelable, Cloneable {
 
     private int colorOpacity = 255;
 
-    private float borderWidth;
+    private float borderWidth = 10;
+
+    private float eraserWidth = 10;
 
     private int lineColor = Color.BLACK;
 
@@ -168,7 +170,18 @@ public class CAnnotStyle implements Parcelable, Cloneable {
     }
 
     public void setBorderWidth(@FloatRange(from = 0.0) float borderWidth) {
+        boolean update = borderWidth != this.borderWidth;
         this.borderWidth = borderWidth;
+        Log.e("CAnnotStyle", "setBorderWidth(" + borderWidth + ", update:" + update + ")");
+        updateBorderWidth(this.borderWidth, update);
+    }
+
+    public void setEraserWidth(float eraserWidth) {
+        this.eraserWidth = eraserWidth;
+    }
+
+    public float getEraserWidth() {
+        return eraserWidth;
     }
 
     public int getLineColor() {
@@ -398,6 +411,9 @@ public class CAnnotStyle implements Parcelable, Cloneable {
             case SQUIGGLY:
                 titleResId = R.string.tools_annot_squiggly;
                 break;
+            case INK:
+                titleResId = R.string.tools_annot_ink;
+                break;
             default:
                 titleResId = R.string.tools_menu_pdfview;
                 break;
@@ -422,6 +438,14 @@ public class CAnnotStyle implements Parcelable, Cloneable {
         }
     }
 
+    private void updateBorderWidth(float borderWidth, boolean update) {
+        if (styleChangeListenerList != null && update) {
+            for (OnAnnotStyleChangeListener onAnnotStyleChangeListener : styleChangeListenerList) {
+                onAnnotStyleChangeListener.onChangeAnnotBorderWidth(borderWidth);
+            }
+        }
+    }
+
     public void addStyleChangeListener(OnAnnotStyleChangeListener styleChangeListener) {
         this.styleChangeListenerList.add(styleChangeListener);
     }
@@ -439,6 +463,8 @@ public class CAnnotStyle implements Parcelable, Cloneable {
         void onChangeAnnotColor(@ColorInt int color);
 
         void onChangeAnnotColorOpacity(@ColorInt int opacity);
+
+        void onChangeAnnotBorderWidth(float borderWidth);
     }
 
 }

+ 5 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfannotstyle/CBasicOnStyleChangeListener.java

@@ -20,4 +20,9 @@ public class CBasicOnStyleChangeListener  implements CAnnotStyle.OnAnnotStyleCha
     public void onChangeAnnotColorOpacity(int opacity) {
 
     }
+
+    @Override
+    public void onChangeAnnotBorderWidth(float borderWidth) {
+
+    }
 }

+ 11 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfannotstyle/data/CPropertiesFragmentDatas.java

@@ -13,6 +13,7 @@ import androidx.annotation.StringRes;
 
 import com.compdfkit.tools.R;
 import com.compdfkit.tools.annotation.pdfproperties.pdfannotstyle.CAnnotStyle;
+import com.compdfkit.tools.annotation.pdfproperties.pdflnk.CInkStyleFragment;
 import com.compdfkit.tools.annotation.pdfproperties.pdfmarkup.CMarkupStyleFragment;
 import com.compdfkit.tools.annotation.pdfproperties.pdfnote.CNoteStyleFragment;
 import com.compdfkit.tools.common.views.pdfproperties.basic.CBasicPropertiesFragment;
@@ -36,6 +37,9 @@ public class CPropertiesFragmentDatas {
             case TEXT:
                 list.addAll(noteFragments(style));
                 break;
+            case INK:
+                list.addAll(inkFragments(style));
+                break;
             default:
                break;
         }
@@ -64,6 +68,13 @@ public class CPropertiesFragmentDatas {
         return list;
     }
 
+    private static List<CPropertiesFragmentBean> inkFragments(CAnnotStyle style){
+        List<CPropertiesFragmentBean> list = new ArrayList<>();
+        list.add(new CPropertiesFragmentBean(style.getAnnotTypeTitleResId(), CInkStyleFragment.class));
+        list.add(new CPropertiesFragmentBean(R.string.tools_custom_color, CColorPickerFragment.class));
+        return list;
+    }
+
     public static class CPropertiesFragmentBean{
 
         private Class<? extends CBasicPropertiesFragment> fragmentClass;

+ 39 - 11
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfannotstyle/manager/CAnnotStyleManager.java

@@ -12,12 +12,14 @@ package com.compdfkit.tools.annotation.pdfproperties.pdfannotstyle.manager;
 import androidx.annotation.ColorInt;
 import androidx.annotation.IntRange;
 
+import com.compdfkit.core.annotation.CPDFInkAnnotation;
 import com.compdfkit.tools.annotation.pdfproperties.CAnnotStyleDialogFragment;
 import com.compdfkit.tools.annotation.pdfproperties.pdfannotstyle.CAnnotStyle;
 import com.compdfkit.tools.common.views.pdfannotationbar.bean.CAnnotationType;
 import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
 import com.compdfkit.ui.attribute.CPDFAnnotAttribute;
 import com.compdfkit.ui.attribute.CPDFHighlightAttr;
+import com.compdfkit.ui.attribute.CPDFInkAttr;
 import com.compdfkit.ui.attribute.CPDFSquigglyAttr;
 import com.compdfkit.ui.attribute.CPDFStrikeoutAttr;
 import com.compdfkit.ui.attribute.CPDFUnderlineAttr;
@@ -30,7 +32,7 @@ import java.util.LinkedHashSet;
 
 public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListener {
 
-    public void apply(CPDFViewCtrl pdfView, CAnnotStyle style, boolean onStore){
+    public void apply(CPDFViewCtrl pdfView, CAnnotStyle style, boolean onStore) {
         LinkedHashSet<CAnnotStyle> linkedHashSet = new LinkedHashSet<>();
         linkedHashSet.add(style);
         apply(pdfView, linkedHashSet, onStore);
@@ -76,6 +78,13 @@ public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListene
                     strikeoutAttr.setAlpha(params.getColorOpacity());
                     callback = strikeoutAttr;
                     break;
+                case INK:
+                    CPDFInkAttr inkAttr = attribute.getInkAttr();
+                    inkAttr.setColor(params.getColor());
+                    inkAttr.setAlpha(params.getColorOpacity());
+                    inkAttr.setBorderWidth(params.getBorderWidth());
+                    inkAttr.setEraseWidth(params.getEraserWidth());
+                    break;
                 default:
                     break;
             }
@@ -87,7 +96,7 @@ public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListene
         }
     }
 
-    public void changeAnnotStyle(){
+    public void changeAnnotStyle() {
 
 
     }
@@ -96,7 +105,7 @@ public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListene
 
     private CPDFViewCtrl pdfView;
 
-    public void bindAnnotStyleFragment(CPDFViewCtrl pdfView, CAnnotStyleDialogFragment styleDialogFragment){
+    public void bindAnnotStyleFragment(CPDFViewCtrl pdfView, CAnnotStyleDialogFragment styleDialogFragment) {
         this.pdfView = pdfView;
         annotStyleDialogFragment = styleDialogFragment;
         annotStyleDialogFragment.addAnnotStyleChangeListener(this);
@@ -104,21 +113,27 @@ public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListene
 
     @Override
     public void onChangeAnnotColor(int color) {
-        if (pdfView != null && annotStyleDialogFragment != null) {
-            CAnnotStyle style = annotStyleDialogFragment.getStyle();
-            apply(pdfView, style, false);
-        }
+        updateAnnot();
     }
 
     @Override
     public void onChangeAnnotColorOpacity(int opacity) {
+        updateAnnot();
+    }
+
+    @Override
+    public void onChangeAnnotBorderWidth(float borderWidth) {
+        updateAnnot();
+    }
+
+    private void updateAnnot() {
         if (pdfView != null && annotStyleDialogFragment != null) {
             CAnnotStyle style = annotStyleDialogFragment.getStyle();
             apply(pdfView, style, false);
         }
     }
 
-    public CAnnotStyle getAnnotStyle(CPDFViewCtrl pdfView, CAnnotationType type){
+    public CAnnotStyle getAnnotStyle(CPDFViewCtrl pdfView, CAnnotationType type) {
         CAnnotStyle style = new CAnnotStyle(type);
         CPDFAnnotAttribute attribute = pdfView.getCPdfReaderView().getReaderAttribute().getAnnotAttribute();
         switch (type) {
@@ -149,6 +164,11 @@ public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListene
                 style.setColor(strikeoutAttr.getColor());
                 style.setColorOpacity(strikeoutAttr.getAlpha());
                 break;
+            case INK:
+                CPDFInkAttr inkAttr = attribute.getInkAttr();
+                style.setColor(inkAttr.getColor());
+                style.setColorOpacity(inkAttr.getAlpha());
+                style.setBorderWidth(inkAttr.getBorderWidth());
             default:
                 break;
         }
@@ -165,7 +185,7 @@ public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListene
             this.pdfView = pdfView;
         }
 
-        public Builder setColor(CAnnotationType type, @ColorInt int color){
+        public Builder setColor(CAnnotationType type, @ColorInt int color) {
             CAnnotStyle style = new CAnnotStyle(type);
             style.setColor(color);
             attrSet.add(style);
@@ -181,10 +201,18 @@ public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListene
         }
 
 
-        public Builder setInkAttribute(@ColorInt int color, @IntRange(from = 0, to = 255) int colorAlpha) {
+        public Builder setInkAttribute(@ColorInt int color, @IntRange(from = 0, to = 255) int colorAlpha, int borderWidth) {
             CAnnotStyle style = new CAnnotStyle(CAnnotationType.INK);
             style.setColor(color);
             style.setColorOpacity(colorAlpha);
+            style.setBorderWidth(borderWidth);
+            attrSet.add(style);
+            return this;
+        }
+
+        public Builder setEraserWidth(int borderWidth){
+            CAnnotStyle style = new CAnnotStyle(CAnnotationType.INK);
+            style.setEraserWidth(borderWidth);
             attrSet.add(style);
             return this;
         }
@@ -209,7 +237,7 @@ public class CAnnotStyleManager implements CAnnotStyle.OnAnnotStyleChangeListene
             return new CAnnotStyleManager();
         }
 
-        public void clear(){
+        public void clear() {
             attrSet.clear();
         }
 

+ 1 - 1
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfmarkup/CLinkStyleFragment.java

@@ -7,7 +7,7 @@
  * This notice may not be removed from this file.
  */
 
-package com.compdfkit.tools.annotation.pdfproperties.pdfmarkup;
+package com.compdfkit.tools.annotation.pdfproperties.pdflink;
 
 
 import android.os.Bundle;

+ 111 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdflnk/CInkCtrlView.java

@@ -0,0 +1,111 @@
+/**
+ * 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.annotation.pdfproperties.pdflnk;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatImageView;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
+import com.compdfkit.ui.proxy.attach.IInkDrawCallback;
+
+
+public class CInkCtrlView extends FrameLayout implements View.OnClickListener {
+
+    private AppCompatImageView ivEraser;
+
+    private AppCompatImageView ivUndo;
+
+    private AppCompatImageView ivRedo;
+
+    private AppCompatImageView ivDelete;
+
+    private AppCompatImageView ivConfirm;
+
+    private CPDFViewCtrl pdfView;
+
+    public CInkCtrlView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CInkCtrlView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CInkCtrlView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+    }
+
+    private void initView(Context context) {
+        inflate(context, R.layout.tools_annot_properties_ink_ctrl_layout, this);
+        ivEraser = findViewById(R.id.iv_ink_eraser);
+        ivUndo = findViewById(R.id.iv_ink_undo);
+        ivRedo = findViewById(R.id.iv_ink_redo);
+        ivDelete = findViewById(R.id.iv_ink_clean);
+        ivConfirm = findViewById(R.id.iv_ink_done);
+        ivEraser.setOnClickListener(this);
+        ivUndo.setOnClickListener(this);
+        ivRedo.setOnClickListener(this);
+        ivDelete.setOnClickListener(this);
+        ivConfirm.setOnClickListener(this);
+    }
+
+    public void initWithPDFView(CPDFViewCtrl pdfView) {
+        this.pdfView = pdfView;
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.iv_ink_eraser) {
+            if (pdfView != null) {
+                if (ivEraser.isSelected()){
+                    ivEraser.setSelected(false);
+                    pdfView.getCPdfReaderView().getInkDrawHelper().setMode(IInkDrawCallback.Mode.DRAW);
+                }else {
+                    ivEraser.setSelected(true);
+                    pdfView.getCPdfReaderView().getInkDrawHelper().setMode(IInkDrawCallback.Mode.ERASE);
+                }
+            }
+        } else if (v.getId() == R.id.iv_ink_undo) {
+            if (pdfView != null) {
+                pdfView.getCPdfReaderView().getInkDrawHelper().onUndo();
+            }
+        } else if (v.getId() == R.id.iv_ink_redo) {
+            if (pdfView != null) {
+                pdfView.getCPdfReaderView().getInkDrawHelper().onRedo();
+            }
+        } else if (v.getId() == R.id.iv_ink_clean) {
+            if (pdfView != null) {
+                pdfView.getCPdfReaderView().getInkDrawHelper().onClean();
+                pdfView.getCPdfReaderView().getInkDrawHelper().setMode(IInkDrawCallback.Mode.DRAW);
+            }
+        } else if (v.getId() == R.id.iv_ink_done) {
+            if (pdfView != null) {
+                pdfView.getCPdfReaderView().getInkDrawHelper().setMode(IInkDrawCallback.Mode.DRAW);
+                pdfView.getCPdfReaderView().getInkDrawHelper().onSave();
+                pdfView.resetAnnotationType();
+            }
+        } else {
+
+        }
+
+    }
+
+
+}

+ 69 - 2
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdflnk/CInkStyleFragment.java

@@ -1,6 +1,6 @@
 /**
  * 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.
@@ -11,6 +11,7 @@ package com.compdfkit.tools.annotation.pdfproperties.pdflnk;
 
 
 import android.os.Bundle;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -18,11 +19,23 @@ import android.view.ViewGroup;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.compdfkit.tools.R;
 import com.compdfkit.tools.annotation.pdfproperties.pdfannotstyle.CAnnotStyle;
 import com.compdfkit.tools.common.views.pdfproperties.basic.CBasicPropertiesFragment;
+import com.compdfkit.tools.common.views.pdfproperties.colorlist.CColorListView;
+import com.compdfkit.tools.common.views.pdfproperties.preview.CStylePreviewView;
+import com.compdfkit.tools.common.views.pdfproperties.sliderbar.CBorderWidthSliderBar;
+import com.compdfkit.tools.common.views.pdfproperties.sliderbar.CSliderBar;
 
 public class CInkStyleFragment extends CBasicPropertiesFragment {
 
+    private CColorListView colorListView;
+
+    private CSliderBar opacitySliderBar;
+
+    private CStylePreviewView stylePreviewView;
+
+    private CBorderWidthSliderBar borderWidthSliderBar;
 
     public static CInkStyleFragment newInstance() {
         return new CInkStyleFragment();
@@ -31,11 +44,65 @@ public class CInkStyleFragment extends CBasicPropertiesFragment {
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
-        return super.onCreateView(inflater, container, savedInstanceState);
+        View rootView = inflater.inflate(R.layout.tools_properties_ink_style_fragment, container, false);
+        colorListView = rootView.findViewById(R.id.color_list_view);
+        stylePreviewView = rootView.findViewById(R.id.style_preview);
+        opacitySliderBar = rootView.findViewById(R.id.slider_bar);
+        borderWidthSliderBar = rootView.findViewById(R.id.slider_bar_border_width);
+        return rootView;
     }
 
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
+        colorListView.setColorPickerClickListener(this::nextFragment);
+        CAnnotStyle cAnnotStyle = viewModel.getStyle();
+        if (cAnnotStyle != null) {
+            stylePreviewView.setColor(cAnnotStyle.getColor());
+            stylePreviewView.setColorOpacity(cAnnotStyle.getColorOpacity());
+            stylePreviewView.setBorderWidth((int) cAnnotStyle.getBorderWidth());
+            borderWidthSliderBar.setProgress((int) cAnnotStyle.getBorderWidth());
+            colorListView.setSelectColor(cAnnotStyle.getColor());
+            opacitySliderBar.setProgress(cAnnotStyle.getColorOpacity());
+        }
+        opacitySliderBar.setChangeListener((progress, percentageValue) -> {
+            if (viewModel != null) {
+                viewModel.getStyle().setColorOpacity(progress);
+            }
+        });
+        colorListView.setColorChangeListener(color -> {
+            if (viewModel != null) {
+                viewModel.getStyle().setColor(color);
+            }
+        });
+        borderWidthSliderBar.setChangeListener((progress, percentageValue) -> {
+            if (viewModel != null) {
+                viewModel.getStyle().setBorderWidth(progress);
+            }
+        });
+        viewModel.addStyleChangeListener(this);
+    }
+
+    @Override
+    public void onChangeAnnotColor(int color) {
+        super.onChangeAnnotColor(color);
+        if (stylePreviewView != null) {
+            stylePreviewView.setColor(color);
+        }
+    }
+
+    @Override
+    public void onChangeAnnotColorOpacity(int opacity) {
+        super.onChangeAnnotColorOpacity(opacity);
+        if (stylePreviewView != null) {
+            stylePreviewView.setColorOpacity(opacity);
+        }
+    }
+
+    @Override
+    public void onChangeAnnotBorderWidth(float borderWidth) {
+        if (stylePreviewView != null) {
+            stylePreviewView.setBorderWidth((int) borderWidth);
+        }
     }
 }

+ 160 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdflnk/CPDFFakeInkAnnotAttachHelper.java

@@ -0,0 +1,160 @@
+package com.compdfkit.tools.annotation.pdfproperties.pdflnk;
+
+
+import android.graphics.Bitmap;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+import com.compdfkit.ui.proxy.attach.IInkDrawCallback;
+import com.kdanmobile.handwriting.KMHandwritingHelper;
+
+public class CPDFFakeInkAnnotAttachHelper extends com.compdfkit.ui.proxy.attach.CPDFFakeInkAnnotAttachHelper {
+
+
+    public CPDFFakeInkAnnotAttachHelper(){
+        setHandwritingHelper(new CPDFHandwritingHelper(new KMHandwritingHelper()));
+    }
+
+
+    static class CPDFHandwritingHelper implements HandwritingHelper {
+
+        private KMHandwritingHelper kmHandwritingHelper;
+
+        public CPDFHandwritingHelper(KMHandwritingHelper handwritingHelper){
+            this.kmHandwritingHelper = handwritingHelper;
+        }
+
+        @Override
+        public boolean isInited() {
+            return kmHandwritingHelper != null && kmHandwritingHelper.isInited();
+        }
+
+        @Override
+        public void initCanvas(int i, int i1) {
+            if (kmHandwritingHelper != null) {
+                kmHandwritingHelper.initCanvas(i, i1);
+            }
+        }
+
+        @Override
+        public void setPenWidth(float v) {
+            if (kmHandwritingHelper != null) {
+                kmHandwritingHelper.setPenWidth(v);
+            }
+        }
+
+        @Override
+        public void setEraseWidth(float v) {
+            if (kmHandwritingHelper != null) {
+                kmHandwritingHelper.setEraseWidth(v);
+            }
+        }
+
+        @Override
+        public void setMode(Mode mode) {
+            if (kmHandwritingHelper != null) {
+                if (mode == Mode.DRAW){
+                    kmHandwritingHelper.setDrawMode(KMHandwritingHelper.DrawMode.DRAW);
+                }else {
+                    kmHandwritingHelper.setDrawMode(KMHandwritingHelper.DrawMode.ERASE);
+                }
+            }
+        }
+
+        @Override
+        public void setEffect(Effect effect) {
+            if (kmHandwritingHelper != null) {
+                if (effect == IInkDrawCallback.Effect.NORMAL) {
+                    kmHandwritingHelper.setDrawEffect(KMHandwritingHelper.DrawEffect.NORMAL);
+                } else {
+                    kmHandwritingHelper.setDrawEffect(KMHandwritingHelper.DrawEffect.PENSTROKE);
+                }
+            }
+        }
+
+        @Override
+        public void setColor(int i) {
+            if (kmHandwritingHelper != null) {
+                kmHandwritingHelper.setColor(i);
+            }
+        }
+
+        @Override
+        public void setAlpha(int i) {
+            if (kmHandwritingHelper != null) {
+                kmHandwritingHelper.setAlpha(i);
+            }
+        }
+
+        @Override
+        public void clean() {
+            if (kmHandwritingHelper != null) {
+                kmHandwritingHelper.clean();
+            }
+        }
+
+        @Override
+        public boolean onDown(float v, float v1, float v2, float v3) {
+            if (kmHandwritingHelper != null){
+                return kmHandwritingHelper.onDown(v, v1, v2, v3);
+            }
+            return false;
+        }
+
+        @Override
+        public boolean onMove(float v, float v1, float v2, float v3) {
+            if (kmHandwritingHelper != null){
+                return kmHandwritingHelper.onMove(v, v1, v2, v3);
+            }
+            return true;
+        }
+
+        @Override
+        public boolean onUp(float v, float v1, float v2, float v3) {
+            if (kmHandwritingHelper != null){
+                return kmHandwritingHelper.onUp(v, v1, v2, v3);
+            }
+            return true;
+        }
+
+        @Override
+        public void onMisTouch() {
+            if (kmHandwritingHelper != null){
+                 kmHandwritingHelper.onMisTouch();
+            }
+        }
+
+        @Override
+        public void onUndo() {
+            if (kmHandwritingHelper != null) {
+                kmHandwritingHelper.onUndo();
+            }
+        }
+
+        @Override
+        public void onRedo() {
+            if (kmHandwritingHelper != null) {
+                kmHandwritingHelper.onRedo();
+            }
+        }
+
+        @Override
+        public Path getErasePath() {
+            return kmHandwritingHelper != null ? kmHandwritingHelper.getErasePath() : null;
+        }
+
+        @Override
+        public RectF getArea() {
+            return kmHandwritingHelper != null ? kmHandwritingHelper.getArea() : null;
+
+        }
+
+        @Override
+        public Bitmap getBitmap() {
+            return kmHandwritingHelper != null ? kmHandwritingHelper.getBitmap() : null;
+
+        }
+    }
+
+
+}

+ 2 - 3
compdfkit-tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfmarkup/CMarkupStyleFragment.java

@@ -19,7 +19,6 @@ import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.compdfkit.tools.R;
-import com.compdfkit.tools.annotation.pdfproperties.pdfannotstyle.CBasicOnStyleChangeListener;
 import com.compdfkit.tools.common.views.pdfproperties.basic.CBasicPropertiesFragment;
 import com.compdfkit.tools.common.views.pdfproperties.colorlist.CColorListView;
 import com.compdfkit.tools.common.views.pdfproperties.preview.CStylePreviewView;
@@ -52,7 +51,7 @@ public class CMarkupStyleFragment extends CBasicPropertiesFragment {
         super.onViewCreated(view, savedInstanceState);
         previewView.setAnnotType(viewModel.getStyle().getType());
         previewView.setColor(viewModel.getStyle().getColor());
-        previewView.setColorAlpha(viewModel.getStyle().getColorOpacity());
+        previewView.setColorOpacity(viewModel.getStyle().getColorOpacity());
         colorListView.setColorChangeListener(color -> {
             if (viewModel != null) {
                 viewModel.getStyle().setColor(color);
@@ -90,7 +89,7 @@ public class CMarkupStyleFragment extends CBasicPropertiesFragment {
             }
         }
         if (previewView != null) {
-            previewView.setColorAlpha(opacity);
+            previewView.setColorOpacity(opacity);
         }
     }
 }

+ 144 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/common/utils/view/CSineCurveView.java

@@ -0,0 +1,144 @@
+package com.compdfkit.tools.common.utils.view;
+
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PointF;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CSineCurveView extends View {
+
+    enum DrawType {Normal, PenStroke}
+
+    private int MAX_POINT_NUMBER = 100;
+
+    private int HALF = 50;
+
+    private float HALFF = 50f;
+
+    private int lineColor = Color.RED;
+
+    private int lineAlpha = 255;
+
+    private float borderWidth = 20f;
+
+    private DrawType drawType = DrawType.Normal;
+
+    private Paint paint = new Paint();
+
+    private float sineCurveHeight = 70F;
+
+    private List<PointF> points = new ArrayList<>();
+
+    public CSineCurveView(Context context) {
+        this(context, null);
+    }
+
+    public CSineCurveView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CSineCurveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        paint.setColor(lineColor);
+        paint.setAlpha(lineAlpha);
+        paint.setStrokeWidth(borderWidth);
+        paint.setStyle(Paint.Style.STROKE);
+        paint.setStrokeCap(Paint.Cap.ROUND);
+        paint.setStrokeJoin(Paint.Join.ROUND);
+        paint.setAntiAlias(true);
+    }
+
+    public void setLineColor(int lineColor) {
+        this.lineColor = lineColor;
+        paint.setColor(lineColor);
+        paint.setAlpha(lineAlpha);
+        invalidate();
+    }
+
+    public void setBorderWidth(float lineWidth) {
+        this.borderWidth = lineWidth;
+        paint.setStrokeWidth(lineWidth);
+        invalidate();
+
+    }
+
+    public void setLineAlpha(int lineAlpha) {
+        this.lineAlpha = lineAlpha;
+        paint.setAlpha(lineAlpha);
+        invalidate();
+    }
+
+    public void setDrawType(DrawType type) {
+        this.drawType = type;
+        invalidate();
+    }
+
+    public int getLineColor() {
+        return lineColor;
+    }
+
+    public int getLineAlpha() {
+        return lineAlpha;
+    }
+
+    public float getBorderWidth() {
+        return borderWidth;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+        Path path = new Path();
+        int viewWidth = getWidth();
+        float startX = 0F;
+        if (drawType == DrawType.PenStroke) {
+            startX = borderWidth;
+            viewWidth = (int) (getWidth() - 2 * borderWidth);
+        }
+        /****** 起始位置  */
+        path.moveTo(startX, ((float) getHeight() / 2));
+        /****** rQuardto的位置是相对的  */
+        path.rQuadTo(((float) viewWidth / 4), -sineCurveHeight, ((float) viewWidth / 2), 0F);
+        path.rQuadTo(((float) viewWidth / 4), sineCurveHeight, ((float) viewWidth / 2), 0F);
+
+        if (drawType == DrawType.Normal) {
+            paint.setStrokeWidth(borderWidth);
+            canvas.drawPath(path, paint);
+        } else {
+            PathMeasure measure = new PathMeasure(path, false);
+            float distance = measure.getLength() / MAX_POINT_NUMBER;
+
+            points.clear();
+            for (int i = 0; i < MAX_POINT_NUMBER; i++) {
+                float[] point = new float[2];
+                measure.getPosTan(i * distance, point, null);
+                points.add(new PointF(point[0], point[1]));
+            }
+
+            PointF lastPoint = points.get(0);
+            for (int i = 0; i < points.size(); i++) {
+                PointF currentPoint = points.get(i);
+                float lWidth = 0f;
+                if (i < HALF) {
+                    lWidth = borderWidth;
+                } else {
+                    lWidth = borderWidth - (i - HALFF) / HALFF * borderWidth * 0.8F;
+                }
+                paint.setStrokeWidth(lWidth);
+                canvas.drawLine(lastPoint.x, lastPoint.y, currentPoint.x, currentPoint.y, paint);
+                lastPoint = currentPoint;
+            }
+        }
+    }
+}

+ 44 - 10
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfannotationbar/CAnnotationToolbar.java

@@ -1,6 +1,6 @@
 /**
  * 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.
@@ -32,6 +32,7 @@ import com.compdfkit.tools.common.views.pdfannotationbar.data.CAnnotationToolDat
 import com.compdfkit.tools.annotation.pdfproperties.CAnnotStyleDialogFragment;
 import com.compdfkit.tools.annotation.pdfproperties.pdfannotstyle.CAnnotStyle;
 import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
+import com.compdfkit.ui.proxy.attach.IInkDrawCallback;
 
 public class CAnnotationToolbar extends FrameLayout {
 
@@ -62,7 +63,7 @@ public class CAnnotationToolbar extends FrameLayout {
         initView(context);
     }
 
-    private void initView(Context context){
+    private void initView(Context context) {
         inflate(context, R.layout.tools_annot_tool_bar, this);
         rvAnnotationList = findViewById(R.id.rv_annotation);
         ivSetting = findViewById(R.id.iv_annotation_attr_settings);
@@ -74,7 +75,7 @@ public class CAnnotationToolbar extends FrameLayout {
         initListener();
     }
 
-    private void initListener(){
+    private void initListener() {
         ivSetting.setEnabled(false);
         ivSetting.setOnClickListener(v -> {
             CAnnotStyleManager manager = new CAnnotStyleManager();
@@ -82,7 +83,7 @@ public class CAnnotationToolbar extends FrameLayout {
 
             CAnnotStyleDialogFragment dialogFragment = CAnnotStyleDialogFragment.newInstance(style);
             manager.bindAnnotStyleFragment(pdfView, dialogFragment);
-            dialogFragment.addAnnotStyleChangeListener(new CBasicOnStyleChangeListener(){
+            dialogFragment.addAnnotStyleChangeListener(new CBasicOnStyleChangeListener() {
                 @Override
                 public void onChangeAnnotColor(int color) {
                     super.onChangeAnnotColor(color);
@@ -93,10 +94,10 @@ public class CAnnotationToolbar extends FrameLayout {
         });
 
         ivUndo.setOnClickListener(v -> {
-
+            undo();
         });
         ivRedo.setOnClickListener(v -> {
-
+            redo();
         });
         toolListAdapter.setOnItemClickListener((adapter, view, position) -> {
             CAnnotToolBean bean = adapter.list.get(position);
@@ -105,7 +106,7 @@ public class CAnnotationToolbar extends FrameLayout {
         });
     }
 
-    public void initWithPDFView(CPDFViewCtrl pdfView){
+    public void initWithPDFView(CPDFViewCtrl pdfView) {
         this.pdfView = pdfView;
         toolListAdapter.setList(CAnnotationToolDatas.getAnnotationList(pdfView));
         this.pdfView.addOnPDFFocusedTypeChangeListener(type -> {
@@ -118,15 +119,24 @@ public class CAnnotationToolbar extends FrameLayout {
         this.fragmentManager = fragmentManager;
     }
 
-    private void switchAnnotationType(CAnnotToolBean bean){
-        if (!bean.isSelect()){
+    private void switchAnnotationType(CAnnotToolBean bean) {
+        if (!bean.isSelect()) {
             pdfView.resetAnnotationType();
+            pdfView.getCPdfReaderView().getInkDrawHelper().onClean();
             return;
         }
-        switch (bean.getType()){
+        if (bean.getType() != CAnnotationType.INK) {
+            pdfView.getCPdfReaderView().getInkDrawHelper().onClean();
+            pdfView.getCPdfReaderView().getInkDrawHelper().setMode(IInkDrawCallback.Mode.DRAW);
+        }
+        switch (bean.getType()) {
             case TEXT:
                 pdfView.changeAnnotationType(CPDFAnnotation.Type.TEXT);
                 break;
+            case INK:
+                pdfView.changeAnnotationType(CPDFAnnotation.Type.INK);
+                pdfView.getCPdfReaderView().getInkDrawHelper().setEffect(IInkDrawCallback.Effect.NORMAL);
+                break;
             case ARROW:
                 pdfView.changeAnnotationType(CPDFAnnotation.Type.LINE);
                 break;
@@ -140,4 +150,28 @@ public class CAnnotationToolbar extends FrameLayout {
                 break;
         }
     }
+
+    private void undo() {
+        switch (toolListAdapter.getCurrentAnnotType()) {
+            case INK:
+                if (pdfView != null) {
+                    pdfView.getCPdfReaderView().getInkDrawHelper().onUndo();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    private void redo() {
+        switch (toolListAdapter.getCurrentAnnotType()) {
+            case INK:
+                if (pdfView != null) {
+                    pdfView.getCPdfReaderView().getInkDrawHelper().onRedo();
+                }
+                break;
+            default:
+                break;
+        }
+    }
 }

+ 5 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/basic/CBasicPropertiesFragment.java

@@ -71,6 +71,11 @@ public abstract class CBasicPropertiesFragment extends Fragment implements CAnno
 
     }
 
+    @Override
+    public void onChangeAnnotBorderWidth(float borderWidth) {
+
+    }
+
     public interface OnSwitchFragmentListener {
 
         void nextFragment();

+ 68 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CAnnotInkPreviewView.java

@@ -0,0 +1,68 @@
+/**
+ * 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.common.views.pdfproperties.preview;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.compdfkit.tools.common.utils.view.CSineCurveView;
+
+public class CAnnotInkPreviewView extends CBasicAnnotPreviewView{
+
+    private CSineCurveView sineCurveView;
+
+    public CAnnotInkPreviewView(@NonNull Context context) {
+        super(context);
+    }
+
+    public CAnnotInkPreviewView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public CAnnotInkPreviewView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    protected int layoutResId() {
+        return 0;
+    }
+
+    @Override
+    protected void initView() {
+        sineCurveView = new CSineCurveView(getContext());
+        addView(sineCurveView);
+    }
+
+    @Override
+    public void setColor(int color) {
+        if (sineCurveView != null) {
+            sineCurveView.setLineColor(color);
+        }
+    }
+
+    @Override
+    public void setColorOpacity(int colorOpacity) {
+        if (sineCurveView != null) {
+            sineCurveView.setLineAlpha(colorOpacity);
+        }
+    }
+
+    @Override
+    public void setBorderWidth(int borderWidth) {
+        if (sineCurveView != null){
+            sineCurveView.setBorderWidth(borderWidth);
+        }
+    }
+}

+ 2 - 2
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CAnnotMarkupPreviewView.java

@@ -52,8 +52,8 @@ class CAnnotMarkupPreviewView extends CBasicAnnotPreviewView {
     }
 
     @Override
-    public void setColorAlpha(int alpha) {
-        float percent = (float) alpha / 255F;
+    public void setColorOpacity(int colorOpacity) {
+        float percent = (float) colorOpacity / 255F;
         viewMarkupBg.setAlpha(percent);
     }
 

+ 1 - 1
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CAnnotNotePreviewView.java

@@ -44,7 +44,7 @@ import com.compdfkit.tools.R;
     }
 
     @Override
-    public void setColorAlpha(int alpha) {
+    public void setColorOpacity(int colorOpacity) {
 
     }
 

+ 9 - 4
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CBasicAnnotPreviewView.java

@@ -3,7 +3,6 @@ package com.compdfkit.tools.common.views.pdfproperties.preview;
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.view.View;
 import android.widget.FrameLayout;
 
 import androidx.annotation.ColorInt;
@@ -23,7 +22,9 @@ import androidx.annotation.Nullable;
 
     public CBasicAnnotPreviewView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        inflate(context, layoutResId(), this);
+        if (layoutResId() != 0) {
+            inflate(context, layoutResId(), this);
+        }
         initView();
     }
 
@@ -31,8 +32,12 @@ import androidx.annotation.Nullable;
 
     protected abstract void initView();
 
-    public abstract void setColor(@ColorInt int color);
+    public void setColor(@ColorInt int color){}
 
-    public abstract void setColorAlpha(@IntRange(from = 0, to = 255) int alpha);
+    public void setColorOpacity(@IntRange(from = 0, to = 255) int colorOpacity){}
+
+    public void setBorderWidth(int borderWidth){
+
+    }
 
 }

+ 11 - 2
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/preview/CStylePreviewView.java

@@ -62,9 +62,15 @@ public class CStylePreviewView extends FrameLayout {
         }
     }
 
-    public void setColorAlpha(int colorAlpha){
+    public void setColorOpacity(int colorOpacity){
         if (previewView != null){
-            previewView.setColorAlpha(colorAlpha);
+            previewView.setColorOpacity(colorOpacity);
+        }
+    }
+
+    public void setBorderWidth(int width){
+        if (previewView != null){
+            previewView.setBorderWidth(width);
         }
     }
 
@@ -83,6 +89,9 @@ public class CStylePreviewView extends FrameLayout {
                 view.setMarkupType(annotationType);
                 previewView = view;
                 break;
+            case INK:
+                previewView = new CAnnotInkPreviewView(getContext());
+                break;
             default:
                 break;
         }

+ 138 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/sliderbar/CBorderWidthSliderBar.java

@@ -0,0 +1,138 @@
+/**
+ * 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.common.views.pdfproperties.sliderbar;
+
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.FrameLayout;
+import android.widget.SeekBar;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.appcompat.widget.AppCompatSeekBar;
+import androidx.appcompat.widget.AppCompatTextView;
+
+import com.compdfkit.tools.R;
+
+public class CBorderWidthSliderBar extends FrameLayout implements SeekBar.OnSeekBarChangeListener {
+
+    private AppCompatTextView tvTitle;
+
+    private AppCompatSeekBar seekBar;
+
+    private boolean showTitle;
+
+    private String title;
+
+    private int sliderBarMaxValue;
+    private int sliderBarMinValue;
+
+    private boolean showValueTips = true;
+
+    private OnProgressChangeListener changeListener;
+
+    public CBorderWidthSliderBar(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CBorderWidthSliderBar(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CBorderWidthSliderBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView();
+        initAttr(context, attrs);
+
+    }
+
+    private void initAttr(Context context, AttributeSet attrs) {
+        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CBorderWidthSliderBar);
+        if (typedArray != null) {
+            showTitle = typedArray.getBoolean(R.styleable.CBorderWidthSliderBar_tools_show_title, true);
+            title = typedArray.getString(R.styleable.CBorderWidthSliderBar_tools_title);
+            sliderBarMaxValue = typedArray.getInt(R.styleable.CBorderWidthSliderBar_android_max, 100);
+            sliderBarMinValue = typedArray.getInt(R.styleable.CBorderWidthSliderBar_slider_bar_min, 0);
+            int progress = typedArray.getInt(R.styleable.CBorderWidthSliderBar_android_progress, 0);
+            tvTitle.setVisibility(showTitle ? VISIBLE : GONE);
+            if (!TextUtils.isEmpty(title)) {
+                tvTitle.setText(title);
+            }
+            seekBar.setMax(sliderBarMaxValue);
+            seekBar.setProgress(Math.max(0, progress));
+            typedArray.recycle();
+        }
+    }
+
+    private void initView() {
+        inflate(getContext(), R.layout.tools_common_border_width_slider_bar, this);
+        tvTitle = findViewById(R.id.tv_title);
+        seekBar = findViewById(R.id.seek_bar);
+        seekBar.setOnSeekBarChangeListener(this);
+    }
+
+    public void setProgress(int progress) {
+        if (progress >sliderBarMaxValue){
+            progress = sliderBarMaxValue;
+        }
+        this.seekBar.setProgress(progress);
+    }
+
+    public void setShowTitle(boolean show){
+        this.showTitle = show;
+        tvTitle.setVisibility(showTitle ? VISIBLE : GONE);
+    }
+
+    public void setTitle(String title){
+        this.title = title;
+        tvTitle.setText(title);
+    }
+
+    public void setTitle(@StringRes int stringResId){
+        this.title = getContext().getString(stringResId);
+        tvTitle.setText(title);
+    }
+
+    private void updateSeekBarValue(int value) {
+        int v = Math.max(sliderBarMinValue, value);
+        int currentPercentage = Math.round((float) v / (float) sliderBarMaxValue * 100F);
+        if (changeListener != null) {
+            changeListener.changed(v, currentPercentage);
+        }
+    }
+
+    public void setChangeListener(OnProgressChangeListener changeListener) {
+        this.changeListener = changeListener;
+    }
+
+    @Override
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        updateSeekBarValue(progress);
+    }
+
+    @Override
+    public void onStartTrackingTouch(SeekBar seekBar) {
+
+    }
+
+    @Override
+    public void onStopTrackingTouch(SeekBar seekBar) {
+
+    }
+
+    public interface OnProgressChangeListener {
+        void changed(int progress, int percentageValue);
+    }
+}

+ 3 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/sliderbar/CSliderBar.java

@@ -100,6 +100,9 @@ public class CSliderBar extends FrameLayout implements SeekBar.OnSeekBarChangeLi
     }
 
     public void setProgress(int progress) {
+        if (progress > sliderBarMaxValue){
+            progress = sliderBarMaxValue;
+        }
         this.seekBar.setProgress(progress);
     }
 

+ 6 - 0
compdfkit-tools/src/main/res/drawable/tools_annot_border_slider_bar_size_bg.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
+
+    <solid android:color="?android:attr/colorAccent"/>
+
+</shape>

+ 30 - 0
compdfkit-tools/src/main/res/drawable/tools_annot_properties_ink_btn_bg.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_selected="true">
+        <ripple android:color="?android:attr/colorControlHighlight">
+            <item android:id="@android:id/mask">
+                <shape android:shape="oval">
+                    <solid android:color="?android:attr/colorControlHighlight" />
+                </shape>
+            </item>
+            <item >
+                <shape android:shape="oval">
+                    <solid android:color="?android:attr/colorControlHighlight" />
+                </shape>
+            </item>
+        </ripple>
+    </item>
+
+    <item>
+        <ripple android:color="?android:attr/colorControlHighlight">
+            <item android:id="@android:id/mask">
+                <shape android:shape="oval">
+                    <solid android:color="?android:attr/colorBackground" />
+                </shape>
+            </item>
+        </ripple>
+    </item>
+
+
+</selector>

+ 6 - 0
compdfkit-tools/src/main/res/drawable/tools_annot_properties_ink_ctrl_bg.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="?android:attr/colorBackground"/>
+    <corners android:bottomLeftRadius="16dp" android:bottomRightRadius="16dp"/>
+
+</shape>

File diff suppressed because it is too large
+ 9 - 0
compdfkit-tools/src/main/res/drawable/tools_ic_eraser.xml


+ 89 - 0
compdfkit-tools/src/main/res/layout/tools_annot_properties_ink_ctrl_layout.xml

@@ -0,0 +1,89 @@
+<?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:layoutDirection="ltr"
+    android:layout_height="wrap_content">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="16dp"
+        android:layout_marginBottom="8dp"
+        android:background="@drawable/tools_annot_properties_ink_ctrl_bg"
+        android:elevation="4dp"
+        android:paddingVertical="4dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_ink_eraser"
+            android:layout_width="45dp"
+            android:layout_height="45dp"
+            android:background="@drawable/tools_annot_properties_ink_btn_bg"
+            android:padding="8dp"
+            app:layout_constraintEnd_toStartOf="@id/iv_ink_undo"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:srcCompat="@drawable/tools_ic_eraser"
+            app:tint="?android:attr/colorAccent" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_ink_undo"
+            android:layout_width="45dp"
+            android:layout_height="45dp"
+            android:background="@drawable/tools_common_oval_ripple"
+            android:padding="8dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/iv_ink_redo"
+            app:layout_constraintStart_toEndOf="@id/iv_ink_eraser"
+            app:layout_constraintTop_toTopOf="parent"
+            app:srcCompat="@drawable/tools_ic_annotation_undo"
+            app:tint="?android:attr/colorAccent" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_ink_redo"
+            android:layout_width="45dp"
+            android:layout_height="45dp"
+            android:background="@drawable/tools_common_oval_ripple"
+            android:padding="8dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/iv_ink_clean"
+            app:layout_constraintStart_toEndOf="@id/iv_ink_undo"
+            app:layout_constraintTop_toTopOf="parent"
+            app:srcCompat="@drawable/tools_ic_annotation_redo"
+            app:tint="?android:attr/colorAccent" />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_ink_clean"
+            android:layout_width="45dp"
+            android:layout_height="45dp"
+            android:background="@drawable/tools_common_oval_ripple"
+            android:padding="8dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/iv_ink_done"
+            app:layout_constraintStart_toEndOf="@id/iv_ink_redo"
+            app:layout_constraintTop_toTopOf="parent"
+            app:srcCompat="@drawable/tools_ic_close"
+            app:tint="?android:attr/colorAccent"
+            />
+
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_ink_done"
+            android:layout_width="45dp"
+            android:layout_height="45dp"
+            android:background="@drawable/tools_common_oval_ripple"
+            android:padding="8dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@id/iv_ink_clean"
+            app:layout_constraintTop_toTopOf="parent"
+            app:srcCompat="@drawable/tools_ic_check_select"
+            app:tint="?android:attr/colorAccent" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 56 - 0
compdfkit-tools/src/main/res/layout/tools_common_border_width_slider_bar.xml

@@ -0,0 +1,56 @@
+<?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="wrap_content"
+    android:orientation="vertical">
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:text="@string/tools_size"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textSize="18sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatSeekBar
+        android:id="@+id/seek_bar"
+        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="30dp"
+        android:layout_marginHorizontal="8dp"
+        android:max="100"
+        android:progress="50"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_title" />
+
+    <View
+        android:id="@+id/view_min"
+        android:layout_width="5dp"
+        android:layout_height="5dp"
+        android:layout_marginStart="24dp"
+        android:background="@drawable/tools_annot_border_slider_bar_size_bg"
+        app:layout_constraintBottom_toBottomOf="@id/view_max"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="@id/view_max" />
+
+
+    <View
+        android:id="@+id/view_max"
+        android:layout_width="20dp"
+        android:layout_height="20dp"
+        android:layout_marginEnd="24dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        android:background="@drawable/tools_annot_border_slider_bar_size_bg"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/seek_bar" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 0 - 2
compdfkit-tools/src/main/res/layout/tools_common_slider_bar.xml

@@ -10,7 +10,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginStart="16dp"
-        android:layout_marginTop="16dp"
         android:text="@string/tools_opacity"
         android:textColor="?android:attr/textColorPrimary"
         android:textSize="18sp" />
@@ -31,7 +30,6 @@
         android:layout_height="wrap_content"
         android:layout_gravity="end"
         android:layout_marginEnd="24dp"
-        android:layout_marginBottom="16dp"
         tools:text="50%"/>
 
 </LinearLayout>

+ 46 - 0
compdfkit-tools/src/main/res/layout/tools_properties_ink_style_fragment.xml

@@ -0,0 +1,46 @@
+<?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.pdfproperties.preview.CStylePreviewView
+        android:id="@+id/style_preview"
+        android:layout_width="match_parent"
+        android:layout_height="80dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:tools_annot_type="ink" />
+
+
+    <com.compdfkit.tools.common.views.pdfproperties.colorlist.CColorListView
+        android:id="@+id/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_toBottomOf="@id/style_preview" />
+
+
+    <com.compdfkit.tools.common.views.pdfproperties.sliderbar.CSliderBar
+        android:id="@+id/slider_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:max="255"
+        app:layout_constraintTop_toBottomOf="@id/color_list_view"
+        app:tools_slider_bar_value_show_type="percentage" />
+
+    <com.compdfkit.tools.common.views.pdfproperties.sliderbar.CBorderWidthSliderBar
+        android:id="@+id/slider_bar_border_width"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:max="20"
+        android:paddingBottom="16dp"
+        app:layout_constraintTop_toBottomOf="@id/slider_bar"
+        app:slider_bar_min="1"
+        app:tools_title="@string/tools_size" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 8 - 0
compdfkit-tools/src/main/res/values/tools_attrs.xml

@@ -49,6 +49,14 @@
         <attr name="tools_slider_bar_show_value" format="boolean"/>
     </declare-styleable>
 
+    <declare-styleable name="CBorderWidthSliderBar"  tools:ignore="ResourceName">
+        <attr name="tools_title"/>
+        <attr name="tools_show_title"/>
+        <attr name="android:max"/>
+        <attr name="slider_bar_min" format="integer"/>
+        <attr name="android:progress"/>
+    </declare-styleable>
+
     <declare-styleable name="CStylePreviewView" tools:ignore="ResourceName">
         <attr name="tools_annot_type" format="enum">
             <enum name="text" value="0"/>

+ 2 - 0
compdfkit-tools/src/main/res/values/tools_strings.xml

@@ -66,11 +66,13 @@
 
     <string name="tools_color">Color:</string>
     <string name="tools_opacity">Opacity:</string>
+    <string name="tools_size">Size:</string>
     <string name="tools_annot_highlight">Highlight</string>
     <string name="tools_annot_underline">Underline</string>
     <string name="tools_annot_strikeout">StrikeOut</string>
     <string name="tools_annot_squiggly">Squiggly</string>
     <string name="tools_annot_note">Note</string>
+    <string name="tools_annot_ink">Ink</string>
 
     <string name="tools_menu_pdfview">PDFView</string>
     <string name="tools_menu_annotation">Annotation</string>

+ 1 - 0
settings.gradle

@@ -22,3 +22,4 @@ include ':pageedit-ctrl-demo'
 include ':compdfkit-tools'
 include ':compdfkit-repo:compdfkit'
 include ':compdfkit-repo:compdfkit-ui'
+include ':compdfkit-repo:compdfkit-kmhandwriting'