signature-pad
1.0.1indexedSmooth, pressure-aware signature capture offering UNDO/REDO, velocity-based stroke widths, Catmull-Rom Bézier smoothing, presets, tunable parameters, SVG/bitmap export and smart auto-crop.
Smooth, pressure-aware signature capture offering UNDO/REDO, velocity-based stroke widths, Catmull-Rom Bézier smoothing, presets, tunable parameters, SVG/bitmap export and smart auto-crop.
A modern Kotlin Multiplatform library for capturing smooth signature drawings with UNDO/REDO functionality, built with Compose Multiplatform.
✅ Fully Supported: Android • Desktop (JVM) • iOS • Web (Wasm/JS)
Enhanced fork of gcacace/android-signaturepad, completely rewritten in Kotlin for KMP with Compose Multiplatform.
-Xexplicit-api=strictdependencies {
implementation("com.tuppersoft:signature-pad:$lastVersion")
}
@Composable
fun SignatureScreen() {
val state = rememberSignaturePadState()
Column(modifier = Modifier.fillMaxSize()) {
SignaturePad(
state = state,
config = SignaturePadConfig.fountainPen(),
modifier = Modifier.fillMaxWidth()
)
}
}
Three carefully tuned presets for different signature styles:
// 🖋️ Fountain Pen (1-4dp) - Elegant, variable width
SignaturePad(
config = SignaturePadConfig.fountainPen(),
modifier = Modifier.fillMaxWidth()
)
// 🖊️ BIC Pen (1.8-2.8dp) - Nearly uniform with subtle ink accumulation
SignaturePad(
config = SignaturePadConfig.pen(),
modifier = Modifier.fillMaxWidth()
)
// 🖍️ Marker (5-7dp) - Bold, thick strokes
SignaturePad(
config = SignaturePadConfig.marker(),
modifier = Modifier.fillMaxWidth()
)
Full control over drawing behavior:
SignaturePad(
config = SignaturePadConfig(
penMinWidth = 2.dp, // Thinnest line (fast drawing)
penMaxWidth = 8.dp, // Thickest line (slow drawing)
penColor = Color.Blue,
velocitySmoothness = ,
widthSmoothness = ,
minVelocity = ,
maxVelocity = ,
widthVariation = ,
inputNoiseThreshold =
),
modifier = Modifier.fillMaxWidth().height(dp)
)
val state = rememberSignaturePadState()
// Check state
if (state.isEmpty) {
Text("Please sign above")
}
// UNDO/REDO capabilities
val canUndo: Boolean = state.canUndo()
val canRedo: Boolean = state.canRedo()
// Actions
val undoSuccess: Boolean = state.undo()
redoSuccess: = state.redo()
state.clear()
val svg: String = state.toSvg()
// Save or transmit the SVG string
// Bitmap with white background
val bitmap = state.toBitmap()
// Bitmap with transparent background
val transparentBitmap = state.toTransparentBitmap()
// Auto-crop to signature bounds with padding
val croppedBitmap = state.toBitmap(
crop = true,
paddingCrop = 16 // pixels of padding around signature
)
// Combine options
val finalBitmap = state.toTransparentBitmap(
crop = true,
paddingCrop = 20
)
React to user interactions:
SignaturePad(
state = state,
config = SignaturePadConfig.fountainPen(),
onStartSign = {
// User started drawing - disable submit button, etc.
println("User started signing")
},
onSign = {
// Signature updated - enable submit, show preview, etc.
println("Signature updated")
},
onClear = {
// Signature cleared - reset form state, etc.
println("Signature cleared")
},
modifier = Modifier.fillMaxWidth()
)
Complete reference for all configuration options:
signature-pad/
├── commonMain/ # Shared code (100% of library)
│ ├── compose/ # Compose UI components
│ ├── geometry/ # Bézier math, points
│ ├── rendering/ # Canvas rendering
│ └── export/ # Bitmap/SVG exporters
├── androidMain/ # Android manifest only
└── desktopMain/ # Desktop-specific (currently empty)
Note: All platforms share 100% of the code through
commonMain. Platform-specific folders (iosMain,jsMain,wasmJsMain) are intentionally empty as the library uses pure Compose Multiplatform APIs that work across all targets.
Contributions are welcome! Please follow these guidelines:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')# Clone the repository
git clone https://github.com/rulogarcillan/signature-pad.git
cd signature-pad
# Build the library
./gradlew :signature-pad:build
# Run the sample app (Android)
./gradlew :app:installDebug
# Run the sample app (Desktop)
./gradlew :app:run
# For iOS, use Xcode or Kotlin Multiplatform Mobile plugin in Android Studio
Copyright 2025 Tuppersoft by Rulo Garcillan
Copyright Gianluca Cacace
Licensed under the Apache License, Version (the );
you may use except compliance the License.
You may obtain a copy of the License at
http:
Unless applicable law agreed to writing, software
distributed under the License distributed an BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
See the License the specific language governing permissions
limitations under the License.
This is a derivative work based on android-signaturepad by Gianluca Cacace.
⭐ If you find this library useful, please star the repo!
| Parameter | Type | Range | Default | User Question | Description |
|---|
penMinWidth | Dp | > 0 | 1.0.dp | "What's the thinnest my line can be?" | Minimum stroke width (fast drawing) |
penMaxWidth | Dp | > 0 | 4.0.dp | "What's the thickest my line can be?" | Maximum stroke width (slow drawing) |
penColor | Color | - | Color(0xFF003D82) | "What color is my pen?" | Stroke color |
velocitySmoothness | Float | 0.0-1.0 | 0.85 | "How smooth should the drawing feel?" | Stroke smoothness (0.0 = jumpy, 1.0 = very smooth) |
widthSmoothness | Float | 0.0-1.0 | 0.7 | "How gradual should thickness changes be?" | Width transition smoothness (0.0 = abrupt, 1.0 = gradual) |
minVelocity | Float | ≥ 0 | 0.0 | "When does the line stop getting thicker?" | Velocity for maximum width (px/ms) |
maxVelocity | Float | ≥ 0 | 8.0 | "When does the line stop getting thinner?" | Velocity for minimum width (px/ms) |
widthVariation | Float | 0.5-3.0 | 1.5 | "How much should thickness vary with speed?" | Width contrast (1.0 = linear, >1.0 = more contrast, <1.0 = less) |
inputNoiseThreshold | Float | ≥ 0 | 0.8 | "How much should I filter hand shake?" | Min distance between points to filter tremor (px) |
| Platform | Status | Version | Notes |
|---|
| Android | ✅ Stable | API 21+ | Full support |
| Desktop (JVM) | ✅ Stable | Java 17+ | Windows, macOS, Linux |
| iOS | ✅ Stable | iOS 15+ | arm64, x64, simulator |
| Web (Wasm) | ✅ Stable | Modern browsers | Chrome, Firefox, Safari (experimental support) |
| Web (JS) | ✅ Stable | Modern browsers | Chrome, Firefox, Safari, Edge |
git push origin feature/amazing-feature)Surfaced from shared tags and platforms — no rankings paid for.