Browse Source

PDFView Flutter - 签名注释

liuxiaolong 2 years ago
parent
commit
ee816ed085
34 changed files with 1032 additions and 196 deletions
  1. 49 0
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/AnnotAttributeUtil.kt
  2. 3 0
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/AnnotType.kt
  3. 9 1
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/PluginUtils.kt
  4. 44 34
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/SampleContextMenuHelper.kt
  5. 14 6
      android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/view/PDFReaderView.kt
  6. 4 0
      assets/images/ic_reader_freetext.svg
  7. 4 0
      assets/images/ic_reader_freetext_select.svg
  8. 6 0
      assets/images/ic_reader_signature.svg
  9. 6 0
      assets/images/ic_reader_signature_select.svg
  10. 6 0
      assets/images/ic_reader_stamp.svg
  11. 6 0
      assets/images/ic_reader_stamp_select.svg
  12. 8 0
      lib/widgets/config.dart
  13. 22 3
      lib/widgets/constains.dart
  14. 13 78
      lib/widgets/events.dart
  15. 43 22
      lib/widgets/function/annot_attribute_options_widget.dart
  16. 2 2
      lib/widgets/function/attrwidget/color_list_widget.dart
  17. 165 0
      lib/widgets/function/attrwidget/attr_free_text_widget.dart
  18. 1 1
      lib/widgets/function/attrwidget/ink_pen_line_width_widget.dart
  19. 1 1
      lib/widgets/function/attrwidget/ink_pen_wave_widget.dart
  20. 2 3
      lib/widgets/function/attrwidget/shape_attr_widget.dart
  21. 86 0
      lib/widgets/function/attrwidget/attr_signature_edit_widget.dart
  22. 142 0
      lib/widgets/function/attrwidget/attr_signature_list_widget.dart
  23. 0 19
      lib/widgets/function/attrwidget/attr_slider_widgets.dart
  24. 6 1
      lib/widgets/function/attrwidget/base_slider_widget.dart
  25. 66 0
      lib/widgets/function/attrwidget/signature_draw_board_widget.dart
  26. 56 17
      lib/widgets/function/pdf_bottom_annot_fun_widget.dart
  27. 1 2
      lib/widgets/function/pdf_page_turning_widget.dart
  28. 1 1
      lib/widgets/function/pdf_themes_widget.dart
  29. 107 3
      lib/widgets/models/annot_attribute_bean.dart
  30. 2 2
      lib/widgets/page/setting_page_widget.dart
  31. 57 0
      lib/widgets/util/signature_image_util.dart
  32. 2 0
      macos/Flutter/GeneratedPluginRegistrant.swift
  33. 96 0
      pubspec.lock
  34. 2 0
      pubspec.yaml

+ 49 - 0
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/AnnotAttributeUtil.kt

@@ -3,6 +3,9 @@ package com.compdfkit.pdfviewer.flutter.helpers
 import android.graphics.Color
 import com.compdfkit.core.annotation.CPDFAnnotation
 import com.compdfkit.core.annotation.CPDFLineAnnotation
+import com.compdfkit.core.annotation.CPDFTextAttribute
+import com.compdfkit.core.annotation.CPDFTextAttribute.FontNameHelper.FontType
+import com.compdfkit.ui.attribute.CPDFFreetextAttr
 import com.compdfkit.ui.reader.CPDFReaderView
 
 
@@ -170,6 +173,41 @@ object AnnotAttributeUtil {
                         }
                     }
                 }
+                AnnotType.freetext ->{
+                    cpdfReaderView.readerAttribute.annotAttribute.freetextAttr.let {cpdfFreetextAttr ->
+                        val fontBold = entry.value.getBoolean(PluginUtils.EVENT_ANNOT_ATTR_FONT_BOLD)?:false
+                        val fontItalic = entry.value.getBoolean(PluginUtils.EVENT_ANNOT_ATTR_FONT_ITALIC)?:false
+                        val textColor = entry.value.getString(PluginUtils.EVENT_ANNOT_ATTR_TEXT_COLOR)?:Color.BLACK.toHexColor()
+                        val textColorAlpha = entry.value.getInt(PluginUtils.EVENT_ANNOT_ATTR_TEXT_COLOR_ALPHA)
+                        val fontSize = entry.value.getInt(PluginUtils.EVENT_ANNOT_ATTR_FONT_SIZE)?:40
+                        val fontTypeStr = entry.value.getString(PluginUtils.EVENT_ANNOT_ATTR_FONT_TYPE)
+                        val fontType = when(fontTypeStr){
+                            "courier" -> FontType.Courier
+                            "helvetica" -> FontType.Helvetica
+                            "times_roman" -> FontType.Times_Roman
+                            else -> FontType.Unknown
+                        }
+                        textColorAlpha?.let {
+                            cpdfFreetextAttr.alpha =it
+                        }
+
+                        val fontName =   CPDFTextAttribute.FontNameHelper.obtainFontName(fontType, fontBold, fontItalic)
+                        cpdfFreetextAttr.textAttribute = CPDFTextAttribute(fontName, fontSize.toFloat(), textColor.fromHex())
+                        cpdfFreetextAttr.onstore()
+                    }
+                }
+                AnnotType.signature , AnnotType.stamp->{
+                    val imagePath = entry.value.getString(PluginUtils.EVENT_ANNOT_ATTR_IMAGE_PATH)
+                    val isSignature = entry.value.getBoolean(PluginUtils.EVENT_ANNOT_ATTR_IS_SIGNATURE)?:false
+                    cpdfReaderView.readerAttribute.annotAttribute.stampAttr.let {
+                        if (imagePath.isNullOrEmpty().not()){
+                            it.setImagePath(imagePath, isSignature)
+                        }
+                    }
+                }
+                else->{
+
+                }
             }
         }
     }
@@ -234,6 +272,17 @@ object AnnotAttributeUtil {
                     PluginUtils.EVENT_ANNOT_ATTR_SHAPE_TYPE to ShapeType.square.name
                 )
             }
+            AnnotType.freetext ->{
+                val freeTextAttr = annotAttribute.freetextAttr
+                mapOf(
+                    PluginUtils.EVENT_ANNOT_ATTR_FONT_BOLD to CPDFTextAttribute.FontNameHelper.isBold(freeTextAttr.textAttribute.fontName),
+                    PluginUtils.EVENT_ANNOT_ATTR_FONT_ITALIC to CPDFTextAttribute.FontNameHelper.isItalic(freeTextAttr.textAttribute.fontName),
+                    PluginUtils.EVENT_ANNOT_ATTR_TEXT_COLOR to freeTextAttr.textAttribute.color.toHexColor(),
+                    PluginUtils.EVENT_ANNOT_ATTR_TEXT_COLOR_ALPHA to freeTextAttr.alpha,
+                    PluginUtils.EVENT_ANNOT_ATTR_FONT_SIZE to freeTextAttr.textAttribute.fontSize,
+                    PluginUtils.EVENT_ANNOT_ATTR_FONT_TYPE to CPDFTextAttribute.FontNameHelper.getFontType(freeTextAttr.textAttribute.fontName).name
+                )
+            }
             else -> {
                 emptyMap<String, Any>()
             }

+ 3 - 0
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/AnnotType.kt

@@ -24,6 +24,9 @@ enum class AnnotType {
     square,
     circle,
     arrow,
+    freetext,
+    signature,
+    stamp
 
 }
 

+ 9 - 1
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/PluginUtils.kt

@@ -43,6 +43,15 @@ object PluginUtils {
     const val EVENT_ANNOT_ATTR_FILL_COLOR = "fillColor"
     const val EVENT_ANNOT_ATTR_FILL_COLOR_ALPHA = "fillColorAlpha"
     const val EVENT_ANNOT_ATTR_SHAPE_TYPE = "shapeType"
+    const val EVENT_ANNOT_ATTR_FONT_BOLD = "fontBold"
+    const val EVENT_ANNOT_ATTR_FONT_ITALIC = "fontItalic"
+    const val EVENT_ANNOT_ATTR_TEXT_COLOR = "textColor"
+    const val EVENT_ANNOT_ATTR_TEXT_COLOR_ALPHA = "textColorAlpha"
+    const val EVENT_ANNOT_ATTR_FONT_SIZE = "fontSize"
+    const val EVENT_ANNOT_ATTR_FONT_TYPE = "fontType"
+    const val EVENT_ANNOT_ATTR_IMAGE_PATH = "imagePath"
+    const val EVENT_ANNOT_ATTR_IS_SIGNATURE = "isSignature"
+
 
     const val KEY_SCROLL_DIRECTION = "scrollDirection"
     const val KEY_IS_DOUBLE_PAGE = "isDoublePage"
@@ -107,7 +116,6 @@ object PluginUtils {
 
     fun onCallMethod(pdfReaderView: PDFReaderView, call: MethodCall, result: MethodChannel.Result) {
         val configuration = call.arguments as? HashMap<String, Any>
-        print(call.method)
         when (call.method) {
             FUNCTION_GET_SCROLL_DIRECTION -> {
                 result.success(if (pdfReaderView.pdfReaderView.isVerticalMode) SCROLL_DIRECTION_VERTICAL else SCROLL_DIRECTION_HORIZONTAL)

+ 44 - 34
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/helpers/SampleContextMenuHelper.kt

@@ -36,7 +36,13 @@ import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_COLO
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_BORDER_WIDTH
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FILL_COLOR
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FILL_COLOR_ALPHA
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FONT_BOLD
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FONT_ITALIC
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FONT_SIZE
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_FONT_TYPE
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_SHAPE_TYPE
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_TEXT_COLOR
+import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.EVENT_ANNOT_ATTR_TEXT_COLOR_ALPHA
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.KEY_ANNOT_TYPE
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.KEY_DISMISS_MODIFY_ANNOTATION_ATTRIBUTE
 import com.compdfkit.pdfviewer.flutter.helpers.PluginUtils.KEY_MODIFY_ANNOTATION_ATTRIBUTE
@@ -96,7 +102,12 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                     val annotAttrBorderAlpha = configuration.getInt(EVENT_ANNOT_ATTR_BORDER_COLOR_ALPHA)
                     val annotAttrFillColor = configuration.getString(EVENT_ANNOT_ATTR_FILL_COLOR)
                     val annotAttrFillColorAlpha = configuration.getInt(EVENT_ANNOT_ATTR_FILL_COLOR_ALPHA)
-
+                    val fontBold = configuration.getBoolean(EVENT_ANNOT_ATTR_FONT_BOLD) ?: false
+                    val fontItalic = configuration.getBoolean(EVENT_ANNOT_ATTR_FONT_ITALIC) ?: false
+                    val textColor = configuration.getString(EVENT_ANNOT_ATTR_TEXT_COLOR) ?: Color.BLACK.toHexColor()
+                    val textColorAlpha = configuration.getInt(EVENT_ANNOT_ATTR_TEXT_COLOR_ALPHA)
+                    val fontSize = configuration.getInt(EVENT_ANNOT_ATTR_FONT_SIZE) ?: 40
+                    val fontTypeStr = configuration.getString(EVENT_ANNOT_ATTR_FONT_TYPE)
 
                     selectMarkupAnnotImpl?.let {
                         when (it) {
@@ -195,6 +206,24 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                                     selectPageView?.invalidate()
                                 }
                             }
+                            is CPDFFreetextAnnotImpl -> {
+                                it.onGetAnnotation()?.let { cpdfFreetextAnnotation ->
+                                    textColorAlpha?.let {
+                                        cpdfFreetextAnnotation.alpha = it
+                                    }
+                                    val fontType = when (fontTypeStr) {
+                                        "courier" -> CPDFTextAttribute.FontNameHelper.FontType.Courier
+                                        "helvetica" -> CPDFTextAttribute.FontNameHelper.FontType.Helvetica
+                                        "times_roman" -> CPDFTextAttribute.FontNameHelper.FontType.Times_Roman
+                                        else -> CPDFTextAttribute.FontNameHelper.FontType.Unknown
+                                    }
+                                    val fontName = CPDFTextAttribute.FontNameHelper.obtainFontName(fontType, fontBold, fontItalic)
+                                    cpdfFreetextAnnotation.freetextDa = CPDFTextAttribute(fontName, fontSize.toFloat(), textColor.fromHex())
+                                    cpdfFreetextAnnotation.updateAp()
+                                    selectMarkupAnnotImpl?.onAnnotAttrChange()
+                                    selectPageView?.invalidate()
+                                }
+                            }
                             else -> {
 
                             }
@@ -328,40 +357,21 @@ class SampleContextMenuHelper(readerView: CPDFReaderView, mContext: Context, mes
                     pageView.createInputBox(annotImpl, ContextMenuType.FreeTextEdit)
                     dismissContextMenu()
                 } else if (id == R.id.attr) {
-                    if (freeTextPopupWindow == null) {
-                        freeTextPopupWindow = FreeTextPopupWindow(context, readerView, readerView.readerAttribute.annotAttribute, freetextAnnotation)
-                    }
-                    freeTextPopupWindow!!.setOnFreetextAttrChangeListener { textColor: Int, textAlpha: Int, textSize: Int, fontName: String? ->
-                        if (readerView == null) {
-                            return@setOnFreetextAttrChangeListener
-                        }
-                        val document = readerView.pdfDocument ?: return@setOnFreetextAttrChangeListener
-                        val page = document.pageAtIndex(pageView.pageNum) ?: return@setOnFreetextAttrChangeListener
-                        val size = readerView.getPageNoZoomSize(pageView.pageNum)
-                        if (size.isEmpty) {
-                            return@setOnFreetextAttrChangeListener
-                        }
-                        val textAttribute = CPDFTextAttribute(fontName, textSize / pageView.scaleValue, textColor)
-                        freetextAnnotation.freetextDa = textAttribute
-                        freetextAnnotation.alpha = textAlpha
-                        var rectF = freetextAnnotation.rect
-                        rectF = page.convertRectFromPage(readerView.isCropMode, size.width(), size.height(), rectF)
-                        val resRect = CPDFTextUtils.measureTextArea(
-                            readerView.context,
-                            fontName,
-                            textSize / pageView.scaleValue,
-                            freetextAnnotation.content,
-                            rectF.width().toInt(),
-                            PointF(rectF.left, rectF.top)
+                    selectMarkupAnnotImpl = annotImpl
+                    selectPageView = pageView
+
+                    val fontName = freetextAnnotation.freetextDa.fontName
+                    contextMenuHelperEventEmitter?.success(
+                        mapOf(
+                            KEY_ANNOT_TYPE to AnnotType.freetext.name,
+                            EVENT_ANNOT_ATTR_FONT_BOLD to CPDFTextAttribute.FontNameHelper.isBold(fontName),
+                            EVENT_ANNOT_ATTR_FONT_ITALIC to CPDFTextAttribute.FontNameHelper.isItalic(fontName),
+                            EVENT_ANNOT_ATTR_FONT_TYPE to CPDFTextAttribute.FontNameHelper.getFontType(fontName).name,
+                            EVENT_ANNOT_ATTR_TEXT_COLOR to freetextAnnotation.freetextDa.color.toHexColor(),
+                            EVENT_ANNOT_ATTR_TEXT_COLOR_ALPHA to freetextAnnotation.alpha,
+                            EVENT_ANNOT_ATTR_FONT_SIZE to freetextAnnotation.freetextDa.fontSize
                         )
-                        rectF[resRect.left, resRect.top, resRect.left + rectF.width()] = resRect.bottom
-                        rectF = page.convertRectToPage(readerView.isCropMode, size.width(), size.height(), rectF)
-                        freetextAnnotation.rect = rectF
-                        freetextAnnotation.updateAp()
-                        annotImpl.onAnnotAttrChange()
-                        pageView.invalidate()
-                    }
-                    freeTextPopupWindow!!.show(0)
+                    )
                 } else if (id == R.id.delete) {
                     pageView.deleteAnnotation(annotImpl)
                     popupWindow.dismiss()

+ 14 - 6
android/app/src/main/kotlin/com/compdfkit/pdfviewer/flutter/view/PDFReaderView.kt

@@ -90,18 +90,26 @@ class PDFReaderView(context: Context?, messenger: BinaryMessenger) : RelativeLay
      */
     fun setAnnotationType(touchMode: String?, annotationType: String?) {
         if (!touchMode.isNullOrEmpty() && !annotationType.isNullOrEmpty()) {
+            Log.e("PDFReaderView", "setAnnotationType:${annotationType}")
             pdfReaderView.apply {
                 // If the current focused type is ink, then save the annotation.
                 if (currentFocusedType == CPDFAnnotation.Type.INK) {
                     inkDrawHelper.onSave()
                 }
 
-                // If the annotation type is an arrow, change the line end type to [CPDFLineAnnotation.LineType.LINETYPE_ARROW].
-                if (AnnotType.arrow.name.equals(annotationType)) {
-                    currentFocusedType = CPDFAnnotation.Type.LINE
-                    readerAttribute.annotAttribute.lineAttr.setLineType(CPDFLineAnnotation.LineType.LINETYPE_NONE, CPDFLineAnnotation.LineType.LINETYPE_ARROW)
-                } else {
-                    currentFocusedType = CPDFAnnotation.Type.valueOf(annotationType!!.uppercase())
+                when {
+                    AnnotType.arrow.name.equals(annotationType) ->{
+                        // If the annotation type is an arrow, change the line end type to [CPDFLineAnnotation.LineType.LINETYPE_ARROW].
+                        currentFocusedType = CPDFAnnotation.Type.LINE
+                        readerAttribute.annotAttribute.lineAttr.setLineType(CPDFLineAnnotation.LineType.LINETYPE_NONE, CPDFLineAnnotation.LineType.LINETYPE_ARROW)
+                    }
+                    AnnotType.signature.name.equals(annotationType) ->{
+                        currentFocusedType = CPDFAnnotation.Type.STAMP
+                    }
+                    else->{
+                        currentFocusedType = CPDFAnnotation.Type.valueOf(annotationType!!.uppercase())
+
+                    }
                 }
 
                 // Set the current touch mode.

+ 4 - 0
assets/images/ic_reader_freetext.svg

@@ -0,0 +1,4 @@
+<svg id="vector" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <rect width="24" height="24" fill="#EFF4FD"/>
+    <path fill="#273C62" fill-rule="evenodd" d="M18.75,4.75V8H17.25V6.25H12.75V18.25H14.3333V19.75H9.6667V18.25H11.25V6.25H6.75V8H5.25V4.75H18.75Z" id="path_0" />
+</svg>

+ 4 - 0
assets/images/ic_reader_freetext_select.svg

@@ -0,0 +1,4 @@
+<svg id="vector" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <rect width="24" height="24" fill="#D5E3FE"/>
+    <path fill="#273C62" fill-rule="evenodd" d="M18.75,4.75V8H17.25V6.25H12.75V18.25H14.3333V19.75H9.6667V18.25H11.25V6.25H6.75V8H5.25V4.75H18.75Z" id="path_0" />
+</svg>

File diff suppressed because it is too large
+ 6 - 0
assets/images/ic_reader_signature.svg


File diff suppressed because it is too large
+ 6 - 0
assets/images/ic_reader_signature_select.svg


+ 6 - 0
assets/images/ic_reader_stamp.svg

@@ -0,0 +1,6 @@
+<svg id="vector" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <rect width="24" height="24" fill="#EFF4FD"/>
+    <path fill="#273C62"
+        d="M13.982,11.9752C15.1875,11.2862 16,9.988 16,8.5C16,6.2909 14.2091,4.5 12,4.5C9.7909,4.5 8,6.2909 8,8.5C8,9.988 8.8125,11.2862 10.018,11.9752C10.1075,12.1032 10.5,12.6962 10.5,13.25C10.5,13.875 10,14.5 10,14.5H4V16H20V14.5H14C14,14.5 13.5,13.875 13.5,13.25C13.5,12.6962 13.8926,12.1032 13.982,11.9752ZM20,19.5V18H4V19.5H20Z"
+        fill-rule="evenodd" id="path_0" />
+</svg>

+ 6 - 0
assets/images/ic_reader_stamp_select.svg

@@ -0,0 +1,6 @@
+<svg id="vector" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <rect width="24" height="24" fill="#D5E3FE"/>
+    <path fill="#273C62"
+        d="M13.982,11.9752C15.1875,11.2862 16,9.988 16,8.5C16,6.2909 14.2091,4.5 12,4.5C9.7909,4.5 8,6.2909 8,8.5C8,9.988 8.8125,11.2862 10.018,11.9752C10.1075,12.1032 10.5,12.6962 10.5,13.25C10.5,13.875 10,14.5 10,14.5H4V16H20V14.5H14C14,14.5 13.5,13.875 13.5,13.25C13.5,12.6962 13.8926,12.1032 13.982,11.9752ZM20,19.5V18H4V19.5H20Z"
+        fill-rule="evenodd" id="path_0" />
+</svg>

+ 8 - 0
lib/widgets/config.dart

@@ -42,6 +42,14 @@ Map<String, dynamic> applyNormalConfiguration() => {
       'fillColor' : Colors.red.toHex(),
       'fillColorAlpha' : 0,
       'borderWidth' : 2
+    },
+    'freetext' : {
+      'fontBold' : false,
+      'fontItalic' : false,
+      'textColor' : Colors.black.toHex(),
+      'textColorAlpha' : 255,
+      'fontSize' : 40,
+      'fontType' : FontType.helvetica.name
     }
   }
 };

+ 22 - 3
lib/widgets/constains.dart

@@ -46,6 +46,8 @@ class EventParameters {
   static const isCoverPageMode = 'isCoverPageMode';
   static const isCropPageMode = 'isCropPageMode';
   static const readBackgroundColor = 'readBackgroundColor';
+  static const touchMode = 'touchMode';
+  static const focusedType = 'focusedType';
   static const annotType = 'annotType';
   static const annotAttribute = 'annotAttribute';
   static const annotAttrColor = 'color';
@@ -56,8 +58,15 @@ class EventParameters {
   static const annotAttrFillColor = 'fillColor';
   static const annotAttrFillColorAlpha = 'fillColorAlpha';
   static const annotAttrShapeType = 'shapeType';
-  static const touchMode = 'touchMode';
-  static const focusedType = 'focusedType';
+  static const annotAttrFontBold = 'fontBold';
+  static const annotAttrFontItalic = 'fontItalic';
+  static const annotAttrTextColor = 'textColor';
+  static const annotAttrTextColorAlpha = 'textColorAlpha';
+  static const annotAttrFontSize = 'fontSize';
+  static const annotAttrFontType = 'fontType';
+  static const annotImagePath = 'imagePath';
+  static const annotIsSignature = 'isSignature';
+
 
 }
 
@@ -78,7 +87,10 @@ enum AnnotationType {
   circle,
   square,
   line,
-  arrow
+  arrow,
+  freetext,
+  signature,
+  stamp
 
 }
 
@@ -94,3 +106,10 @@ enum ShapeType {
   line,
   arrow }
 
+///freetext annotation font type
+enum FontType {
+  courier,
+  helvetica,
+  times_roman
+}
+

+ 13 - 78
lib/widgets/events.dart

@@ -1,5 +1,3 @@
-import 'dart:ffi';
-
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:kmpdfkit_demo/widgets/constains.dart';
@@ -106,9 +104,9 @@ CancelListener setReaderViewCallbackListener(
 /// ```dart
 ///     setReaderViewContextMenuHelperListener((annotBean) {
 ///       //show annotation attribute options widget
-///       _showAttributeOptionsModalBottomSheet(context, annotBean, (color, alpha) {
+///       _showAttributeOptionsModalBottomSheet(context, annotBean,(AnnotAttributeBean bean) {
 ///         modifyAnnotationAttribute(
-///             annotationType: annotBean.annotType, color: color, alpha: alpha);
+///             annotationType: annotBean.annotType, bean: bean);
 ///       }, (){
 ///         dismissModifyAnnotationAttribute();
 ///       });
@@ -123,31 +121,9 @@ void setReaderViewContextMenuHelperListener(
     Map<dynamic, dynamic> result = event;
     String annotType = result[EventParameters.annotType];
     AnnotationType type = AnnotationType.values.byName(annotType);
-    String? annotAttrColor = result[EventParameters.annotAttrColor];
-    int annotAttrAlpha = result[EventParameters.annotAttrAlpha]??255;
-    double borderWidth = result[EventParameters.annotAttrBorderWidth] ?? 2;
-    String? borderColor = result[EventParameters.annotAttrBorderColor];
-    int borderColorAlpha =
-        result[EventParameters.annotAttrBorderColorAlpha] ?? 255;
-    String? fillColor = result[EventParameters.annotAttrFillColor];
-    int fillColorAlpha = result[EventParameters.annotAttrFillColorAlpha] ?? 255;
-    String shapeTypeStr = result[EventParameters.annotAttrShapeType] ?? "";
-    AnnotationType shapeType = shapeTypeStr.isEmpty
-        ? AnnotationType.square
-        : AnnotationType.values.byName(shapeTypeStr);
-
     showAnnotationAttributeOptions(AnnotBean(
       annotType: type,
-      attributeBean: AnnotAttributeBean(
-          color: annotAttrColor != null ? HexColor.fromHex(annotAttrColor) : Colors.red,
-          alpha: annotAttrAlpha,
-          borderWidth: borderWidth,
-          borderColor: borderColor != null ? HexColor.fromHex(borderColor) : Colors.red,
-          borderColorAlpha: borderColorAlpha,
-          fillColor: fillColor != null ? HexColor.fromHex(fillColor) : Colors.red,
-          fillColorAlpha: fillColorAlpha,
-          shapeType: shapeType,
-      showShapeTypeWidget: false),
+      attributeBean: AnnotAttributeBean.parseMapValue(type, result),
     ));
   }, cancelOnError: true);
 }
@@ -158,10 +134,10 @@ void setReaderViewContextMenuHelperListener(
 /// ```dart
 ///     setReaderViewContextMenuHelperListener((annotBean) {
 ///       //show annotation attribute options widget
-///       _showAttributeOptionsModalBottomSheet(context, annotBean, (color, alpha) {
+///       _showAttributeOptionsModalBottomSheet(context, annotBean,(AnnotAttributeBean bean) {
 ///         //modify annotation attribute
 ///         modifyAnnotationAttribute(
-///             annotationType: annotBean.annotType, color: color, alpha: alpha);
+///             annotationType: annotBean.annotType, bean: bean);
 ///       }, (){
 ///         dismissModifyAnnotationAttribute();
 ///       });
@@ -171,16 +147,8 @@ void setReaderViewContextMenuHelperListener(
 void modifyAnnotationAttribute(
     {required AnnotationType annotationType,
     required AnnotAttributeBean bean}) async {
-  await _modifyAnnotAttrChannel.invokeMethod(Functions.modifyAnnotAttribute, {
-    EventParameters.annotAttrColor: bean.color.toHex(),
-    EventParameters.annotAttrAlpha: bean.alpha,
-    EventParameters.annotType: annotationType.name,
-    EventParameters.annotAttrBorderWidth: bean.borderWidth,
-    EventParameters.annotAttrBorderColor: bean.borderColor.toHex(),
-    EventParameters.annotAttrBorderColorAlpha: bean.borderColorAlpha,
-    EventParameters.annotAttrFillColor: bean.fillColor.toHex(),
-    EventParameters.annotAttrFillColorAlpha: bean.fillColorAlpha
-  });
+  await _modifyAnnotAttrChannel.invokeMethod(
+      Functions.modifyAnnotAttribute, bean.toMapValues(annotationType));
 }
 
 /// Please call this method after the annotation attribute adjustment interface is closed.
@@ -318,40 +286,16 @@ Future<int> setReadBackgroundColor(int backgroundColor) async {
       {EventParameters.readBackgroundColor: backgroundColor});
 }
 
-///Get annotation attributes based on annotation type
-///```dart
+/// Get annotation attributes based on annotation type
+///
+/// ```dart
 ///     AnnotAttributeBean highlight = await getAnnotAttribute(AnnotType.highlight);
-///```
+/// ```
 /// return annotation attributes color and alpha
 Future<AnnotAttributeBean> getAnnotAttribute(AnnotationType annotType) async {
   Map<dynamic, dynamic> annotAttrMap = await _methodChannel.invokeMethod(
       Functions.getAnnotAttribute, {EventParameters.annotType: annotType.name});
-  String color =
-      annotAttrMap[EventParameters.annotAttrColor] ?? Colors.red.toHex();
-  int alpha = annotAttrMap[EventParameters.annotAttrAlpha] ?? 255;
-  num borderWidth = annotAttrMap[EventParameters.annotAttrBorderWidth] ?? 2;
-  String borderColor = annotAttrMap[EventParameters.annotAttrBorderColor] ??
-      Colors.red.toHex();
-  int borderColorAlpha =
-      annotAttrMap[EventParameters.annotAttrBorderColorAlpha] ?? 255;
-  String fillColor = annotAttrMap[EventParameters.annotAttrFillColor] ??
-      Colors.red.toHex();
-  int fillColorAlpha =
-      annotAttrMap[EventParameters.annotAttrFillColorAlpha] ?? 255;
-
-  String shapeType = annotAttrMap[EventParameters.annotAttrShapeType] ?? "";
-  AnnotationType type =
-      shapeType.isEmpty ? annotType : AnnotationType.values.byName(shapeType);
-
-  return AnnotAttributeBean(
-      color: HexColor.fromHex(color),
-      alpha: alpha,
-      borderWidth: borderWidth.toDouble(),
-      borderColor: HexColor.fromHex(borderColor),
-      borderColorAlpha: borderColorAlpha,
-      fillColor: HexColor.fromHex(fillColor),
-      fillColorAlpha: fillColorAlpha,
-      shapeType: type);
+  return AnnotAttributeBean.parseMapValue(annotType, annotAttrMap);
 }
 
 ///set annotation attributes
@@ -365,16 +309,7 @@ void setAnnotAttribute(
     required AnnotAttributeBean bean}) async {
   await _methodChannel.invokeMethod(Functions.setAnnotAttribute, {
     EventParameters.annotType: annotationType.name,
-    EventParameters.annotAttribute: {
-      EventParameters.annotAttrColor: bean.color.toHex(),
-      EventParameters.annotAttrAlpha: bean.alpha,
-      EventParameters.annotAttrBorderWidth: bean.borderWidth,
-      EventParameters.annotAttrBorderColor: bean.borderColor.toHex(),
-      EventParameters.annotAttrBorderColorAlpha: bean.borderColorAlpha,
-      EventParameters.annotAttrFillColor: bean.fillColor.toHex(),
-      EventParameters.annotAttrFillColorAlpha: bean.fillColorAlpha,
-      EventParameters.annotAttrShapeType: bean.shapeType.name
-    }
+    EventParameters.annotAttribute: bean.toMapValues(annotationType)
   });
 }
 

+ 43 - 22
lib/widgets/function/annot_attribute_options_widget.dart

@@ -1,12 +1,12 @@
 import 'package:flutter/material.dart';
 import 'package:kmpdfkit_demo/widgets/constains.dart';
-import 'package:kmpdfkit_demo/widgets/events.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_slider_widgets.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_free_text_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_signature_list_widget.dart';
 import 'package:kmpdfkit_demo/widgets/function/attrwidget/base_slider_widget.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/color_list_widget.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/ink_pen_wave_widget.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/ink_pen_line_width_widget.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/shape_attr_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_color_list_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_ink_pen_wave_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_ink_line_width_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_shape_type_widget.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_attribute_bean.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_bean.dart';
 
@@ -25,9 +25,10 @@ class AnnotAttributeOptionsWidget extends StatefulWidget {
   AnnotBean annotBean;
   final AnnotAttributeOptionsCallback attributeOptionsCallback;
 
-  AnnotAttributeOptionsWidget({Key? key,
-    required this.annotBean,
-    required this.attributeOptionsCallback})
+  AnnotAttributeOptionsWidget(
+      {Key? key,
+      required this.annotBean,
+      required this.attributeOptionsCallback})
       : super(key: key);
 
   @override
@@ -44,24 +45,23 @@ class _AnnotAttributeOptionsWidgetState
 
   @override
   Widget build(BuildContext context) {
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      children: annotationAttrWidget(),
-    );
+    return annotationAttrWidget();
   }
 
-  List<Widget> annotationAttrWidget() {
+  Widget annotationAttrWidget() {
     switch (widget.annotBean.annotType) {
       case AnnotationType.highlight:
       case AnnotationType.underline:
       case AnnotationType.squiggly:
       case AnnotationType.strikeout:
         {
-          return [_colorWidget(), _colorAlphaWidget()];
+          return Column(
+              mainAxisSize: MainAxisSize.min,
+              children: [_colorWidget(), _colorAlphaWidget()]);
         }
       case AnnotationType.ink:
         {
-          return [
+          return Column(mainAxisSize: MainAxisSize.min, children: [
             InkCurvedWidget(
               color: widget.annotBean.attributeBean.color,
               lineWidth: widget.annotBean.attributeBean.borderWidth,
@@ -70,11 +70,11 @@ class _AnnotAttributeOptionsWidgetState
             _colorWidget(),
             _colorAlphaWidget(),
             _inkPenSwitchWidget()
-          ];
+          ]);
         }
       case AnnotationType.shape:
         {
-          return [
+          return Column(mainAxisSize: MainAxisSize.min, children: [
             ShapeAttrWidget(
               bean: widget.annotBean.attributeBean,
               callback: (AnnotAttributeBean? bean) {
@@ -82,11 +82,33 @@ class _AnnotAttributeOptionsWidgetState
                   widget.annotBean.attributeBean = bean;
                 }
                 widget.attributeOptionsCallback(widget.annotBean.attributeBean);
-              },)
-          ];
+              },
+            )
+          ]);
+        }
+      case AnnotationType.freetext:
+        {
+          return Column(mainAxisSize: MainAxisSize.min, children: [
+            AttrFreeTextWidget(
+              bean: widget.annotBean.attributeBean,
+              callback: widget.attributeOptionsCallback,
+            )
+          ]);
+        }
+      case AnnotationType.signature:
+        {
+          return AttrSignatureListWidget(
+            callback: (imagePath) {
+              widget.annotBean.attributeBean
+                ..imagePath = imagePath
+                ..isSignature = true;
+              widget.attributeOptionsCallback(widget.annotBean.attributeBean);
+              Navigator.pop(context);
+            },
+          );
         }
       default:
-        return [];
+        return const Placeholder();
     }
   }
 
@@ -112,7 +134,6 @@ class _AnnotAttributeOptionsWidgetState
         });
   }
 
-
   Widget _inkPenSwitchWidget() {
     return InkPenLineWidthWidget(
         borderWidth: widget.annotBean.attributeBean.borderWidth,

+ 2 - 2
lib/widgets/function/attrwidget/color_list_widget.dart

@@ -1,6 +1,6 @@
 import 'package:flutter/material.dart';
 
-///  color_list_widget.dart
+///  attr_color_list_widget.dart
 ///
 ///  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
 ///
@@ -21,7 +21,7 @@ var annotColorList = [
   Colors.redAccent,
   Colors.blueGrey,
   Colors.white,
-  Colors.black38
+  Colors.black
 ];
 
 typedef AnnotColorOptionsCallback = void Function(Color color);

+ 165 - 0
lib/widgets/function/attrwidget/attr_free_text_widget.dart

@@ -0,0 +1,165 @@
+import 'package:flutter/material.dart';
+import 'package:kmpdfkit_demo/widgets/constains.dart';
+import 'package:kmpdfkit_demo/widgets/models/annot_attribute_bean.dart';
+
+import 'attr_color_list_widget.dart';
+import 'base_slider_widget.dart';
+
+typedef AttrFreeTextCallback = Function(AnnotAttributeBean);
+
+///  attr_free_text_widget.dart
+///
+///  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.
+
+class AttrFreeTextWidget extends StatefulWidget {
+  AnnotAttributeBean bean;
+  AttrFreeTextCallback callback;
+
+  AttrFreeTextWidget({Key? key, required this.bean, required this.callback})
+      : super(key: key);
+
+  @override
+  State<AttrFreeTextWidget> createState() => _AttrFreeTextWidgetState();
+}
+
+class _AttrFreeTextWidgetState extends State<AttrFreeTextWidget> {
+  bool _isFontWidget = true;
+  bool isBold = false;
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      children: [
+        Row(
+          children: [
+            Expanded(
+                child: TextButton(
+                    onPressed: () {
+                      setState(() {
+                        _isFontWidget = true;
+                      });
+                    },
+                    child: Text(
+                      'FONT',
+                      style: TextStyle(
+                          color: _isFontWidget ? Colors.blue : Colors.grey,
+                          fontWeight: _isFontWidget
+                              ? FontWeight.bold
+                              : FontWeight.normal),
+                    ))),
+            Expanded(
+                child: TextButton(
+                    onPressed: () {
+                      setState(() {
+                        _isFontWidget = false;
+                      });
+                    },
+                    child: Text('STYLE',
+                        style: TextStyle(
+                            color: !_isFontWidget ? Colors.blue : Colors.grey,
+                            fontWeight: !_isFontWidget
+                                ? FontWeight.bold
+                                : FontWeight.normal))))
+          ],
+        ),
+        _isFontWidget ? _fontWidget() : _styleWidget()
+      ],
+    );
+  }
+
+  Widget _fontWidget() {
+    return Column(
+      key: const ValueKey('free_text_font'),
+      children: [
+        Row(
+          children: [
+            TextButton(
+                onPressed: () {
+                  setState(() {
+                    widget.bean.fontBold = !widget.bean.fontBold;
+                    widget.callback(widget.bean);
+                  });
+                },
+                child: Text('B',
+                    style: TextStyle(
+                        fontWeight: FontWeight.bold,
+                        fontSize: 16,
+                        color:
+                            widget.bean.fontBold ? Colors.blue : Colors.grey))),
+            TextButton(
+                onPressed: () {
+                  setState(() {
+                    widget.bean.fontItalic = !widget.bean.fontItalic;
+                    widget.callback(widget.bean);
+                  });
+                },
+                child: Text('I',
+                    style: TextStyle(
+                        fontWeight: FontWeight.bold,
+                        fontSize: 16,
+                        fontStyle: FontStyle.italic,
+                        color: widget.bean.fontItalic
+                            ? Colors.blue
+                            : Colors.grey)))
+          ],
+        ),
+        ListView(
+          primary: true,
+          shrinkWrap: true,
+          children: [
+            for (var value in FontType.values) ...{
+              ListTile(
+                title: Text(value.name),
+                trailing: widget.bean.fontType == value
+                    ? const Icon(Icons.check)
+                    : null,
+                onTap: () {
+                  setState(() {
+                    widget.bean.fontType = value;
+                    widget.callback(widget.bean);
+                  });
+                },
+              ),
+              const Divider(color: Colors.grey, height: 1)
+            }
+          ],
+        )
+      ],
+    );
+  }
+
+  Widget _styleWidget() {
+    return Column(
+      key: const ValueKey('free_text_style'),
+      children: [
+        ColorListWidget(
+            color: widget.bean.textColor,
+            colorOptionsCallback: (textColor) {
+              widget.bean.textColor = textColor;
+              widget.callback(widget.bean);
+            }),
+        colorAlphaWidget(
+            currentAlphaValue: widget.bean.textColorAlpha,
+            alphaOptionsCallback: (textColorAlpha) {
+              widget.bean.textColorAlpha = textColorAlpha.round();
+              widget.callback(widget.bean);
+            }),
+        BaseSliderWidget(
+            sliderCurrentValue: widget.bean.fontSize.toDouble(),
+            sliderMinValue: 1,
+            sliderMaxValue: 100,
+            icon: Icons.format_size,
+            valueShowType: ValueShowType.sourceValue,
+            sliderValueCallback: (fontSize) {
+              widget.bean.fontSize = fontSize.round();
+              widget.callback(widget.bean);
+            })
+      ],
+    );
+  }
+}

+ 1 - 1
lib/widgets/function/attrwidget/ink_pen_line_width_widget.dart

@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
 
 import 'base_slider_widget.dart';
 
-///  ink_pen_line_width_widget.dart
+///  attr_ink_line_width_widget.dart
 ///
 ///  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
 ///

+ 1 - 1
lib/widgets/function/attrwidget/ink_pen_wave_widget.dart

@@ -1,7 +1,7 @@
 import 'package:flutter/material.dart';
 
 
-///  ink_pen_wave_widget.dart
+///  attr_ink_pen_wave_widget.dart
 ///
 ///  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
 ///

+ 2 - 3
lib/widgets/function/attrwidget/shape_attr_widget.dart

@@ -1,13 +1,12 @@
 import 'package:flutter/material.dart';
 import 'package:kmpdfkit_demo/widgets/constains.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_slider_widgets.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/color_list_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_color_list_widget.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_attribute_bean.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_shape_bean.dart';
 
 import 'base_slider_widget.dart';
 
-///  shape_attr_widget.dart
+///  attr_shape_type_widget.dart
 ///
 ///  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
 ///

+ 86 - 0
lib/widgets/function/attrwidget/attr_signature_edit_widget.dart

@@ -0,0 +1,86 @@
+import 'dart:ui' as ui;
+import 'package:flutter/material.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_color_list_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/base_slider_widget.dart';
+import 'package:kmpdfkit_demo/widgets/util/signature_image_util.dart';
+import 'package:syncfusion_flutter_signaturepad/signaturepad.dart';
+
+class AttrSignatureEditWidget extends StatefulWidget {
+  const AttrSignatureEditWidget({Key? key}) : super(key: key);
+
+  @override
+  State<AttrSignatureEditWidget> createState() =>
+      _AttrSignatureEditWidgetState();
+}
+
+class _AttrSignatureEditWidgetState extends State<AttrSignatureEditWidget> {
+  GlobalKey<SfSignaturePadState> _signaturePadKey = GlobalKey();
+  double strokeWidth = 5;
+  Color strokeColor = Colors.red;
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: const Text('Create signature'),
+        actions: [
+          TextButton(
+              onPressed: () async {
+                String? path =
+                await SignatureImageUtil.saveByteDataImage(await _signaturePadKey.currentState?.toImage());
+                Navigator.pop(context, path);
+              },
+              child: const Text(
+                'Done',
+                style: TextStyle(color: Colors.white),
+              ))
+        ],
+      ),
+      body: Column(
+        children: [
+          ColorListWidget(
+              color: strokeColor,
+              colorOptionsCallback: (color) {
+                setState(() {
+                  strokeColor = color;
+                });
+              }),
+          BaseSliderWidget(
+              sliderCurrentValue: strokeWidth,
+              sliderMinValue: 1,
+              sliderMaxValue: 50,
+              icon: Icons.line_weight,
+              valueText: '${strokeWidth.round()}',
+              valueShowType: ValueShowType.sourceValue,
+              sliderValueCallback: (lineWidth) {
+                setState(() {
+                  strokeWidth = lineWidth;
+                });
+              }),
+          Expanded(
+            child: Stack(
+              children: [
+                Positioned(
+                    child: SfSignaturePad(
+                  key: _signaturePadKey,
+                  minimumStrokeWidth: strokeWidth,
+                  maximumStrokeWidth: strokeWidth,
+                  backgroundColor: Colors.transparent,
+                  strokeColor: strokeColor,
+                )),
+                Positioned(
+                    bottom: 10,
+                    right: 20,
+                    child: IconButton(
+                        onPressed: () {
+                          _signaturePadKey.currentState?.clear();
+                        },
+                        icon: const Icon(Icons.delete)))
+              ],
+            ),
+          )
+        ],
+      ),
+    );
+  }
+}

+ 142 - 0
lib/widgets/function/attrwidget/attr_signature_list_widget.dart

@@ -0,0 +1,142 @@
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:kmpdfkit_demo/widgets/util/signature_image_util.dart';
+
+import 'attr_signature_edit_widget.dart';
+
+
+///  attr_signature_list_widget.dart
+///
+///  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.
+
+typedef AttrSignatureCallback = Function(String imagePath);
+
+class AttrSignatureListWidget extends StatefulWidget {
+  AttrSignatureCallback callback;
+  AttrSignatureListWidget({Key? key, required this.callback}) : super(key: key);
+
+  @override
+  State<AttrSignatureListWidget> createState() =>
+      _AttrSignatureListWidgetState();
+}
+
+class _AttrSignatureListWidgetState extends State<AttrSignatureListWidget> {
+  bool _isEditMode = false;
+  List<SignatureImageBean> _signatureImageList = [];
+
+  @override
+  void initState() {
+    super.initState();
+    _refreshSignatureImageList();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        appBar: AppBar(
+          actions: [
+            IconButton(
+                onPressed: () async {
+                  if(_isEditMode){
+                    SignatureImageUtil.delete(_signatureImageList.where((element) => element.select).toList());
+                    setState(() {
+                      _isEditMode = false;
+                    });
+                    _refreshSignatureImageList();
+                  }else{
+                    setState(() {
+                      _isEditMode = true;
+                    });
+                  }
+                  
+                },
+                icon: Icon(_isEditMode ? Icons.delete : Icons.edit))
+          ],
+        ),
+        body: ListView.separated(
+          itemCount: _signatureImageList.length,
+          shrinkWrap: true,
+          primary: true,
+          itemBuilder: (BuildContext context, int index) {
+            return ListTile(
+              title: Container(
+                height: 80,
+                child: Stack(
+                  children: [
+                    Positioned(
+                      top: 0,
+                      bottom: 0,
+                      left: 0,
+                      right: 0,
+                      child: Image.file(
+                        _signatureImageList[index].file,
+                        height: 80,
+                      ),
+                    ),
+                    if (_isEditMode) ...{
+                      Positioned(
+                          top: 0,
+                          bottom: 0,
+                          right: 10,
+                          child: Checkbox(
+                            value: _signatureImageList[index].select,
+                            onChanged: (value) async {
+                              setState(() {
+                                _signatureImageList[index].select = !_signatureImageList[index].select;
+                              });
+                            },
+                          ))
+                    }
+                  ],
+                ),
+              ),
+              onTap: (){
+                widget.callback(_signatureImageList[index].file.path);
+              },
+            );
+          },
+          separatorBuilder: (BuildContext context, int index) {
+            return Divider(
+              height: 1,
+              color: Colors.grey[300],
+            );
+          },
+        ),
+        floatingActionButton: FloatingActionButton(
+          onPressed: () async {
+            String? path = await Navigator.push(
+                context,
+                MaterialPageRoute(
+                    builder: (context) => const AttrSignatureEditWidget()));
+            if (path?.isNotEmpty == true) {
+              _refreshSignatureImageList();
+            }
+          },
+          child: const Icon(Icons.add),
+        ));
+  }
+
+  void _refreshSignatureImageList() async {
+    final newList = await SignatureImageUtil.signatureImages();
+    setState(() {
+      _signatureImageList = newList;
+    });
+  }
+}
+
+
+class SignatureImageBean{
+
+  File file;
+  bool select;
+  
+  SignatureImageBean(this.file, this.select);
+  
+  
+}

+ 0 - 19
lib/widgets/function/attrwidget/attr_slider_widgets.dart

@@ -1,19 +0,0 @@
-
-
-import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/base_slider_widget.dart';
-
-
-///  attr_slider_widgets.dart
-///
-///  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.
-
-Widget colorAlphaWidget({int currentAlphaValue = 0, double sliderMaxValue = 255, required AnnotSliderValueOptionsCallback alphaOptionsCallback}){
-  return BaseSliderWidget(sliderCurrentValue: currentAlphaValue.toDouble(),sliderMinValue: 0, sliderMaxValue: sliderMaxValue, icon:  Icons.invert_colors, sliderValueCallback: alphaOptionsCallback);
-}
-

+ 6 - 1
lib/widgets/function/attrwidget/base_slider_widget.dart

@@ -1,5 +1,5 @@
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/function/attrwidget/color_list_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_color_list_widget.dart';
 
 ///  annot_attribute_options_widget.dart
 ///
@@ -84,3 +84,8 @@ class _BaseSliderWidgetState extends State<BaseSliderWidget> {
         ));
   }
 }
+
+
+Widget colorAlphaWidget({int currentAlphaValue = 0, double sliderMaxValue = 255, required AnnotSliderValueOptionsCallback alphaOptionsCallback}){
+  return BaseSliderWidget(sliderCurrentValue: currentAlphaValue.toDouble(),sliderMinValue: 0, sliderMaxValue: sliderMaxValue, icon:  Icons.invert_colors, sliderValueCallback: alphaOptionsCallback);
+}

+ 66 - 0
lib/widgets/function/attrwidget/signature_draw_board_widget.dart

@@ -0,0 +1,66 @@
+import 'package:flutter/material.dart';
+
+
+class SignatureDrawBoard extends StatefulWidget {
+  @override
+  _SignatureDrawBoardState createState() => _SignatureDrawBoardState();
+}
+
+class _SignatureDrawBoardState extends State<SignatureDrawBoard> {
+  List<Offset> points = [];
+
+  @override
+  Widget build(BuildContext context) {
+    return GestureDetector(
+      onPanUpdate: (DragUpdateDetails details) {
+        setState(() {
+          RenderBox renderBox = context.findRenderObject() as RenderBox;
+          Offset localPosition = renderBox.globalToLocal(details.globalPosition);
+          points = List.from(points)..add(localPosition);
+        });
+      },
+      onPanEnd: (DragEndDetails details) {
+        // points.add(Offset.zero);
+      },
+      child: CustomPaint(
+        painter: SignaturePainter(
+          color: Colors.black,
+          strokeWidth: 5.0,
+          points: points,
+        ),
+        size: Size.infinite,
+      ),
+    );
+  }
+}
+
+
+
+
+
+
+class SignaturePainter extends CustomPainter {
+  Color color;
+  double strokeWidth;
+  List<Offset> points;
+
+  SignaturePainter({required this.color, required this.strokeWidth, required this.points});
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    Paint paint = Paint()
+      ..color = color
+      ..strokeWidth = strokeWidth
+      ..strokeCap = StrokeCap.round;
+
+    for (int i = 0; i < points.length - 1; i++) {
+      canvas.drawLine(points[i], points[i + 1], paint);
+    }
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) {
+    return true;
+  }
+}
+

+ 56 - 17
lib/widgets/function/pdf_bottom_annot_fun_widget.dart

@@ -3,6 +3,7 @@ import 'package:flutter_svg/flutter_svg.dart';
 import 'package:kmpdfkit_demo/widgets/constains.dart';
 import 'package:kmpdfkit_demo/widgets/events.dart';
 import 'package:kmpdfkit_demo/widgets/function/annot_attribute_options_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_signature_list_widget.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_attribute_bean.dart';
 import 'package:kmpdfkit_demo/widgets/models/annot_bean.dart';
 
@@ -58,7 +59,22 @@ class _PDFBottomAnnotFunWidgetState extends State<PDFBottomAnnotFunWidget> {
         annotType: AnnotationType.shape,
         normalImagePath: 'assets/images/ic_reader_shape.svg',
         selectImagePath: 'assets/images/ic_reader_shape_select.svg',
-        attributeBean: AnnotAttributeBean(color: Colors.transparent))
+        attributeBean: AnnotAttributeBean(color: Colors.transparent)),
+    AnnotBean(
+        annotType: AnnotationType.freetext,
+        normalImagePath: 'assets/images/ic_reader_freetext.svg',
+        selectImagePath: 'assets/images/ic_reader_freetext_select.svg',
+        attributeBean: AnnotAttributeBean(color: Colors.transparent)),
+    AnnotBean(
+        annotType: AnnotationType.signature,
+        normalImagePath: 'assets/images/ic_reader_signature.svg',
+        selectImagePath: 'assets/images/ic_reader_signature_select.svg',
+        attributeBean: AnnotAttributeBean(color: Colors.transparent)),
+    AnnotBean(
+        annotType: AnnotationType.stamp,
+        normalImagePath: 'assets/images/ic_reader_stamp.svg',
+        selectImagePath: 'assets/images/ic_reader_stamp_select.svg',
+        attributeBean: AnnotAttributeBean(color: Colors.transparent)),
   ];
 
   @override
@@ -66,7 +82,7 @@ class _PDFBottomAnnotFunWidgetState extends State<PDFBottomAnnotFunWidget> {
     super.initState();
     initAnnotAttr();
     setReaderViewContextMenuHelperListener((annotBean) {
-      _showAttributeOptionsModalBottomSheet(context, annotBean,
+      _attributeOptionsModalBottomSheet(context, annotBean,
           (AnnotAttributeBean bean) {
         modifyAnnotationAttribute(
             annotationType: annotBean.annotType, bean: bean);
@@ -89,26 +105,19 @@ class _PDFBottomAnnotFunWidgetState extends State<PDFBottomAnnotFunWidget> {
             ? AnnotationType.unknown
             : annotBean.annotType;
       });
+
+      if (selectAnnot == AnnotationType.signature) {
+        showAttributeModalBottomSheet(context, annotBean);
+      }
     }, (annotBean) {
       setCPDFReaderViewFocusType(annotBean.attributeBean.shapeType);
       setState(() {
         selectAnnot = annotBean.annotType;
       });
-
-      _showAttributeOptionsModalBottomSheet(context, annotBean,
-          (AnnotAttributeBean attributeBean) async {
-        setAnnotAttribute(
-            annotationType: annotBean.annotType, bean: attributeBean);
-        AnnotBean bean = annotFunList
-            .firstWhere((element) => element.annotType == annotBean.annotType);
-        setState(() {
-          bean.attributeBean = attributeBean;
-        });
-      }, () {});
+      showAttributeModalBottomSheet(context, annotBean);
     });
   }
 
-
   Widget annotFunctionMenuListWidget(
       AnnotationType selectAnnotType,
       Function(AnnotBean annotBean) onTap,
@@ -170,12 +179,33 @@ class _PDFBottomAnnotFunWidgetState extends State<PDFBottomAnnotFunWidget> {
             }));
   }
 
-  void _showAttributeOptionsModalBottomSheet(context, AnnotBean annotBean,
+  void showAttributeModalBottomSheet(
+      BuildContext context, AnnotBean annotBean) {
+    _attributeOptionsModalBottomSheet(context, annotBean,
+        (AnnotAttributeBean attributeBean) async {
+      setAnnotAttribute(
+          annotationType: annotBean.annotType, bean: attributeBean);
+      AnnotBean bean = annotFunList
+          .firstWhere((element) => element.annotType == annotBean.annotType);
+      setState(() {
+        bean.attributeBean = attributeBean;
+      });
+    }, () {
+      setState(() {
+        if (selectAnnot == AnnotationType.signature) {
+          selectAnnot = AnnotationType.unknown;
+        }
+      });
+    });
+  }
+
+  void _attributeOptionsModalBottomSheet(context, AnnotBean annotBean,
       AnnotAttributeOptionsCallback callback, VoidCallback? closeCallback) {
     Future<void> close = showModalBottomSheet<int>(
         context: context,
         barrierColor: Colors.transparent,
-        isScrollControlled: false,
+        isScrollControlled: true,
+        useSafeArea: true,
         builder: (BuildContext context) {
           return AnnotAttributeOptionsWidget(
             attributeOptionsCallback: callback,
@@ -200,7 +230,10 @@ class _PDFBottomAnnotFunWidgetState extends State<PDFBottomAnnotFunWidget> {
         await getAnnotAttribute(AnnotationType.squiggly);
     AnnotAttributeBean ink = await getAnnotAttribute(AnnotationType.ink);
     AnnotAttributeBean shape = await getAnnotAttribute(AnnotationType.shape);
-    print(shape.toString());
+    AnnotAttributeBean freeText =
+        await getAnnotAttribute(AnnotationType.freetext);
+    AnnotAttributeBean signature =
+        await getAnnotAttribute(AnnotationType.signature);
     setState(() {
       for (var element in annotFunList) {
         switch (element.annotType) {
@@ -224,6 +257,12 @@ class _PDFBottomAnnotFunWidgetState extends State<PDFBottomAnnotFunWidget> {
           case AnnotationType.shape:
             element.attributeBean = shape;
             break;
+          case AnnotationType.freetext:
+            element.attributeBean = freeText;
+            break;
+          case AnnotationType.signature:
+            element.attributeBean = signature;
+            break;
           default:
             break;
         }

+ 1 - 2
lib/widgets/function/pdf_page_turning_widget.dart

@@ -3,7 +3,7 @@ import 'package:kmpdfkit_demo/widgets/constains.dart';
 import 'package:kmpdfkit_demo/widgets/events.dart';
 
 
-///  pdf_page_turning_widget.dart
+///  setting_pdf_page_turning_widget.dart
 ///
 ///  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
 ///
@@ -49,7 +49,6 @@ class _PDFPageTurningWidgetState extends State<PDFPageTurningWidget> {
         }),
         item('Continue', _isContinue, (value) {
           setIsContinueMode(value).then((value) {
-            print('isContinue:$value');
             setState(() {
               _isContinue = value;
             });

+ 1 - 1
lib/widgets/function/pdf_themes_widget.dart

@@ -1,7 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:kmpdfkit_demo/widgets/events.dart';
 
-///  pdf_themes_widget.dart
+///  setting_pdf_themes_widget.dart
 ///
 ///  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
 ///

+ 107 - 3
lib/widgets/models/annot_attribute_bean.dart

@@ -3,6 +3,7 @@ import 'dart:ui';
 import 'package:flutter/material.dart';
 
 import '../constains.dart';
+import '../extension/color_extension.dart';
 
 ///  annot_attribute_bean.dart
 ///  Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
@@ -17,6 +18,7 @@ class AnnotAttributeBean {
   int alpha;
   double borderWidth;
 
+  ///only shape annotation [AnnotationType.square],[AnnotationType.circle],[AnnotationType.line],[AnnotationType.arrow] ----->
   AnnotationType shapeType;
   Color borderColor;
   int borderColorAlpha;
@@ -24,6 +26,20 @@ class AnnotAttributeBean {
   int fillColorAlpha;
   bool showShapeTypeWidget;
 
+  /// <------
+
+  /// freetext only
+  bool fontBold;
+  bool fontItalic = false;
+  Color textColor;
+  int textColorAlpha;
+  int fontSize;
+  FontType fontType;
+
+  /// signature, stamp
+  String imagePath;
+  bool isSignature;
+
   AnnotAttributeBean(
       {this.color = Colors.red,
       this.alpha = 255,
@@ -33,11 +49,99 @@ class AnnotAttributeBean {
       this.borderColorAlpha = 255,
       this.fillColor = Colors.red,
       this.fillColorAlpha = 0,
-      this.showShapeTypeWidget = true});
-
+      this.showShapeTypeWidget = true,
+      this.fontBold = false,
+      this.fontItalic = false,
+      this.textColor = Colors.black,
+      this.textColorAlpha = 255,
+      this.fontSize = 40,
+      this.fontType = FontType.helvetica,
+      this.imagePath = "",
+      this.isSignature = false});
 
   @override
   String toString() {
-    return "color:${color}, alpha:${alpha}, shapeType:${shapeType.name}, borderWidth:${borderWidth},borderColor:${borderColor}, borderColorAlpha:${borderColorAlpha}, fillColor:${fillColor}, fillColorAlpha:${fillColorAlpha}";
+    return "color:$color,"
+        " alpha:$alpha, "
+        "shapeType:${shapeType.name}, "
+        "borderWidth:$borderWidth,"
+        "borderColor:$borderColor, "
+        "borderColorAlpha:$borderColorAlpha, "
+        "fillColor:$fillColor, "
+        "fillColorAlpha:$fillColorAlpha,"
+        "fontBold:$fontBold,"
+        "fontItalic:$fontItalic,"
+        "textColor:${textColor},"
+        "textColorAlpha:${textColorAlpha},"
+        "fontSize:$fontSize,"
+        "fontType:${fontType.name},"
+        "imagePath:${imagePath},"
+        "isSignature:${isSignature}";
+  }
+
+  static AnnotAttributeBean parseMapValue(AnnotationType annotationType, Map<dynamic, dynamic> event) {
+    Map<dynamic, dynamic> result = event;
+    String annotAttrColor =
+        result[EventParameters.annotAttrColor] ?? Colors.red.toHex();
+    int annotAttrAlpha = result[EventParameters.annotAttrAlpha] ?? 255;
+    num borderWidth = result[EventParameters.annotAttrBorderWidth] ?? 2.0;
+    String borderColor =
+        result[EventParameters.annotAttrBorderColor] ?? Colors.red.toHex();
+    int borderColorAlpha =
+        result[EventParameters.annotAttrBorderColorAlpha] ?? 255;
+    String fillColor =
+        result[EventParameters.annotAttrFillColor] ?? Colors.red.toHex();
+    int fillColorAlpha = result[EventParameters.annotAttrFillColorAlpha] ?? 255;
+    String shapeTypeStr = result[EventParameters.annotAttrShapeType] ?? "";
+    AnnotationType shapeType = shapeTypeStr.isEmpty
+        ? annotationType
+        : AnnotationType.values.byName(shapeTypeStr);
+
+    bool fontBold = result[EventParameters.annotAttrFontBold] ?? false;
+    bool fontItalic = result[EventParameters.annotAttrFontItalic] ?? false;
+    String textColor =
+        result[EventParameters.annotAttrTextColor] ?? Colors.black.toHex();
+    int textColorAlpha = result[EventParameters.annotAttrTextColorAlpha] ?? 255;
+    num fontSize = result[EventParameters.annotAttrFontSize] ?? 40;
+    String fontType =
+        result[EventParameters.annotAttrFontType] ?? FontType.helvetica.name;
+
+    return AnnotAttributeBean(
+        color: HexColor.fromHex(annotAttrColor),
+        alpha: annotAttrAlpha,
+        borderWidth: borderWidth.toDouble(),
+        borderColor: HexColor.fromHex(borderColor),
+        borderColorAlpha: borderColorAlpha,
+        fillColor: HexColor.fromHex(fillColor),
+        fillColorAlpha: fillColorAlpha,
+        shapeType: shapeType,
+        showShapeTypeWidget: false,
+        fontBold: fontBold,
+        fontItalic: fontItalic,
+        textColor: HexColor.fromHex(textColor),
+        textColorAlpha: textColorAlpha,
+        fontSize: fontSize.toInt(),
+        fontType: FontType.values.byName(fontType.toLowerCase()));
+  }
+
+  Map<dynamic, dynamic> toMapValues(AnnotationType annotationType) {
+    return {
+      EventParameters.annotAttrColor: color.toHex(),
+      EventParameters.annotAttrAlpha: alpha,
+      EventParameters.annotType: annotationType.name,
+      EventParameters.annotAttrBorderWidth: borderWidth,
+      EventParameters.annotAttrBorderColor: borderColor.toHex(),
+      EventParameters.annotAttrBorderColorAlpha: borderColorAlpha,
+      EventParameters.annotAttrFillColor: fillColor.toHex(),
+      EventParameters.annotAttrFillColorAlpha: fillColorAlpha,
+      EventParameters.annotAttrFontBold : fontBold,
+      EventParameters.annotAttrFontItalic : fontItalic,
+      EventParameters.annotAttrTextColor : textColor.toHex(),
+      EventParameters.annotAttrTextColorAlpha : textColorAlpha,
+      EventParameters.annotAttrFontSize : fontSize,
+      EventParameters.annotAttrFontType : fontType.name,
+      EventParameters.annotImagePath : imagePath,
+      EventParameters.annotIsSignature : isSignature
+    };
   }
 }

+ 2 - 2
lib/widgets/page/setting_page_widget.dart

@@ -1,6 +1,6 @@
 import 'package:flutter/material.dart';
-import 'package:kmpdfkit_demo/widgets/function/pdf_page_turning_widget.dart';
-import 'package:kmpdfkit_demo/widgets/function/pdf_themes_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/setting/setting_pdf_page_turning_widget.dart';
+import 'package:kmpdfkit_demo/widgets/function/setting/setting_pdf_themes_widget.dart';
 
 
 ///  setting_page_widget.dart

+ 57 - 0
lib/widgets/util/signature_image_util.dart

@@ -0,0 +1,57 @@
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+import 'dart:ui' as ui;
+import 'dart:ui';
+
+import 'package:kmpdfkit_demo/widgets/function/attrwidget/attr_signature_list_widget.dart';
+import 'package:path_provider/path_provider.dart';
+
+///  signature_image_util.dart
+///
+///  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.
+
+class SignatureImageUtil {
+  static Future<String?> saveByteDataImage(ui.Image? image) async {
+    ByteData? byteData = await image?.toByteData(format: ImageByteFormat.png);
+    final pngBytes = byteData?.buffer.asUint8List();
+
+    // 写入文件
+    final directory = await getApplicationDocumentsDirectory();
+    Directory folder = Directory('${directory.path}/pdfview/signature/');
+    folder.createSync(recursive: true);
+    String path =
+        '${folder.path}/signature_image_${DateTime.now().millisecond}.png';
+    final file = File(path);
+    await file.writeAsBytes(pngBytes!.toList());
+    return file.existsSync() ? path : null;
+  }
+
+  static Future<List<SignatureImageBean>> signatureImages() async {
+    final directory = await getApplicationDocumentsDirectory();
+    String path = '${directory.path}/pdfview/signature/';
+    final folder = Directory(path);
+    if (!await folder.exists()) {
+      return [];
+    }
+    final fileList = await folder.list().toList();
+    final files = <SignatureImageBean>[];
+    for (final entity in fileList) {
+      if (entity is File) {
+        files.add(SignatureImageBean(File(entity.path), false));
+      }
+    }
+    return files;
+  }
+
+  static void delete(List<SignatureImageBean> list) async {
+    for (var value in list) {
+      value.file.delete();
+    }
+  }
+}

+ 2 - 0
macos/Flutter/GeneratedPluginRegistrant.swift

@@ -5,6 +5,8 @@
 import FlutterMacOS
 import Foundation
 
+import path_provider_foundation
 
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+  PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
 }

+ 96 - 0
pubspec.lock

@@ -73,6 +73,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.0.1"
+  file:
+    dependency: transitive
+    description:
+      name: file
+      sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+      url: "https://pub.dev"
+    source: hosted
+    version: "6.1.4"
   file_picker:
     dependency: "direct main"
     description:
@@ -184,6 +192,54 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.1"
+  path_provider:
+    dependency: "direct main"
+    description:
+      name: path_provider
+      sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.14"
+  path_provider_android:
+    dependency: transitive
+    description:
+      name: path_provider_android
+      sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.24"
+  path_provider_foundation:
+    dependency: transitive
+    description:
+      name: path_provider_foundation
+      sha256: "12eee51abdf4d34c590f043f45073adbb45514a108bd9db4491547a2fd891059"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.0"
+  path_provider_linux:
+    dependency: transitive
+    description:
+      name: path_provider_linux
+      sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.10"
+  path_provider_platform_interface:
+    dependency: transitive
+    description:
+      name: path_provider_platform_interface
+      sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.6"
+  path_provider_windows:
+    dependency: transitive
+    description:
+      name: path_provider_windows
+      sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.5"
   permission_handler:
     dependency: "direct main"
     description:
@@ -232,6 +288,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "5.1.0"
+  platform:
+    dependency: transitive
+    description:
+      name: platform
+      sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.1.0"
   plugin_platform_interface:
     dependency: transitive
     description:
@@ -240,6 +304,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.1.4"
+  process:
+    dependency: transitive
+    description:
+      name: process
+      sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
+      url: "https://pub.dev"
+    source: hosted
+    version: "4.2.4"
   provider:
     dependency: "direct main"
     description:
@@ -285,6 +357,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.2.0"
+  syncfusion_flutter_core:
+    dependency: transitive
+    description:
+      name: syncfusion_flutter_core
+      sha256: "3979f0b1c5a97422cadae52d476c21fa3e0fb671ef51de6cae1d646d8b99fe1f"
+      url: "https://pub.dev"
+    source: hosted
+    version: "20.4.54"
+  syncfusion_flutter_signaturepad:
+    dependency: "direct main"
+    description:
+      name: syncfusion_flutter_signaturepad
+      sha256: bddbb370533dd238af45ae787af8ca751195f4ffe9ca09e18c0f75a7683630fc
+      url: "https://pub.dev"
+    source: hosted
+    version: "20.4.54"
   term_glyph:
     dependency: transitive
     description:
@@ -341,6 +429,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "3.1.3"
+  xdg_directories:
+    dependency: transitive
+    description:
+      name: xdg_directories
+      sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.0.0"
   xml:
     dependency: transitive
     description:

+ 2 - 0
pubspec.yaml

@@ -40,6 +40,8 @@ dependencies:
   # open_file: ^3.2.1
   permission_handler: ^10.2.0
   flutter_svg: ^2.0.3
+  syncfusion_flutter_signaturepad: ^20.4.54
+  path_provider: ^2.0.14
 
 
 dev_dependencies: