Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

OpenMathPad 📐✨

License: MIT Platform Target SDK Kotlin Compose Material 3 Display Tests Diagnostics

Lightweight, high-performance Infinite Canvas Math & Physics Scratchpad for Android tablets.


🎯 Mission & Overview

OpenMathPad is a 100% local, privacy-first infinite scratchpad designed specifically for solving STEM problems, derivations, and physics diagrams on Android tablets:

  • 144Hz Low-Latency Inking & Viewport Culling: Ultra-responsive drawing loop profiling with $O(1)$ viewport bounding box culling (visibleRect = Rect(-panX/zoom, -panY/zoom, (-panX + width)/zoom, (-panY + height)/zoom)) and RenderNode hardware graphics layer decoupling. Zero per-frame heap allocations inside DrawScope for solid 144 FPS stylus tracking on large documents.
  • Fast-Stroke "Hook" / "Serif" Elimination: Micro-jitter landing filter detects and eliminates sharp direction reversals (>110° within 5dp of landing), snapping stroke origins cleanly to the dominant trajectory. Zero-latency linear start for the first 2 points blends smoothly into midpoint Quadratic Beziers once velocity stabilizes.
  • Authentic Uniform Ballpoint Pen: Crisp, constant-width ballpoint/gel pen strokes (presets: Thin 1.0dp, Normal 1.5dp, Thick 2.5dp) and semi-transparent highlighters (50% alpha). Zero post-stroke morphing or styling deformation upon ACTION_UP.
  • Interactive Geometric Shapes (CanvasShape): First-class selectable geometric objects (Vector Arrow, Rectangle Box, Circle, Line). Tapping selects a shape, revealing a high-contrast bounding frame with corner/endpoint resize handles and a quick-delete button. Dragging moves the body; handles resize/transform in real-time with full Undo/Redo history.
  • Dynamic Theme-Aware Adaptive Ink (AdaptiveInkColor): Intelligent contrast inversion engine guarantees strokes remain 100% visible across Light and Dark themes. Default ink dynamically renders as Deep Charcoal (#0F172A) on light backgrounds and Crisp Chalk White (#F8FAFC) on dark backgrounds, while custom STEM palette colors maintain distinctive hue with calibrated luminance.
  • Classic Squared Paper Grid (Тетрадь в клеточку): Standard 5mm school notebook grid lines dynamically scaled and shifted with canvas zoom and pan. Easily toggle between Squared Grid and Blank canvas.
  • GeoGebra-Lite Smart Geometry & Snapping:
    • Draw & Hold Line Straightening: Holding the pen stationary at the end of a stroke for $\ge 450\text{ms}$ automatically straightens it into a crisp line segment.
    • Endpoint Magnetic Snapping: Snaps stroke endpoints to nearby vertices ($\le 24\text{px}$) or grid intersections to draw closed polygons, triangles, coordinate axes, and vectors effortlessly.
    • Cartesian Coordinate Axes (XY): Quick action toggle to project an aligned Cartesian coordinate system with directional arrows, numerical ticks, and origin $(0, 0)$.
    • Ruler Mode: Restricts inking strictly to straight line segments.
  • 100% Hardware Palm Rejection: Active stylus (TOOL_TYPE_STYLUS, TOOL_TYPE_ERASER) draws freely while capacitive palm touches are cleanly rejected. An optional touch-drawing toggle is available for finger sketching.
  • Infinite Canvas Navigation: Smooth two-finger panning and pinch-to-zoom (0.2x to 5.0x) with coordinate scene transformations.
  • Task & Problem Image Insertion: Import textbook or assignment screenshots directly onto the canvas, automatically centered in the current viewport, with persistent sandbox storage (context.filesDir/task_images/) and interactive 4-corner proportional resize handles.

🏗️ Architecture Overview

OpenMathPad uses a clean, reactive architecture with Android Jetpack Compose and StateFlow:

┌────────────────────────────────────────────────────────────────────────┐
│                        Jetpack Compose UI Layer                        │
│   InfiniteCanvas  •  CanvasToolbar  •  CanvasImageCard  • CanvasShape  │
└────────────────────────────────────┬───────────────────────────────────┘
                                     │ StateFlow / MotionEvents
┌────────────────────────────────────▼───────────────────────────────────┐
│                      CanvasViewModel State Holder                      │
│   Undo/Redo History • Telemetry • Coordinate Mapping • Hold-to-Straight│
│   Interactive Shapes • Viewport Bounds • Theme-Aware Ink Engine        │
└──────────────┬──────────────────────────────────────────┬──────────────┘
               │ Screen to Scene Transform                │ Persistent Images
┌──────────────▼─────────────┐             ┌──────────────▼──────────────┐
│  Low-Latency Inking Engine │             │    Task Media Management    │
│ • PalmRejectionFilter      │             │ • TaskImageManager          │
│ • GeometrySnapper (Snap/XY)│             │ • Downscale & EXIF rotation │
│ • Landing Hook Filter      │             │ • Internal Storage Sandbox  │
│ • BezierSmoother (Midpoint)│             │ • Proportional 4-Corner Box │
│ • Cached Path & Bounds Rect│             └─────────────────────────────┘
│ • AdaptiveInkColor Contrast│
└────────────────────────────┘

1. Low-Latency Inking & Geometry Engine (BezierSmoother, GeometrySnapper, DrawingStroke, CanvasShape)

  • Real-Time Midpoint Quadratic Bezier Interpolation: Interpolates smooth C1 curves between point midpoints using control points. Smooths high-frequency hardware jitter without deforming mathematical symbols or numbers.
  • Landing Hook Elimination: First 3-4 points are checked for high-angle reversals (>110°) within landing distance, discarding landing jitter and snapping origin directly to dominant trajectory.
  • Uniform Ballpoint Pen Rendering: Clean, constant-width lines with StrokeCap.Round and StrokeJoin.Round. Eliminates erratic width variation for readable mathematical formulas.
  • Smart Line Straightening & Magnetic Snapping: Real-time draw-and-hold timer converts strokes into straight lines, snapping to vertices and grid intersections.
  • Precomputed Path & Bounds Caching: Finished strokes lazily cache their rendered Path, Stroke style, and Rect bounding box for $O(1)$ viewport culling and zero-cost pans and zooms.
  • Interactive Geometric Shapes: First-class CanvasShape objects for Vectors, Boxes, Circles, and Lines with hit testing, body dragging, handle transforms, and delete overlay.
  • Adaptive Ink Engine: Dynamically maps stroke colors based on theme luminance, preventing black ink from vanishing on dark backgrounds.

2. Infinite Canvas & Squared Paper Grid (InfiniteCanvas, CanvasViewModel)

  • Coordinate Transformations: Converts screen pixel coordinates to infinite scene coordinates: $$\text{sceneX} = \frac{\text{screenX} - \text{panOffsetX}}{\text{zoomScale}}, \quad \text{sceneY} = \frac{\text{screenY} - \text{panOffsetY}}{\text{zoomScale}}$$
  • 144Hz Viewport Culling: In DrawScope, strokes and shapes outside visibleRect are bypassed, keeping frame render times strictly within the 6.9ms frame budget on 144Hz displays.
  • Two-Finger Navigation: Distinguishes single-pointer stylus inking from two-finger gestures (pan and pinch-to-zoom clamped between 0.2x and 5.0x).
  • Infinite Squared Grid: Renders subtle notebook grid lines in $O(1)$ constant time strictly within the active viewport bounds.
  • Cartesian Axes: Displays scaled X and Y axes with directional arrows and $(0, 0)$ origin mark.

3. Task Image Import & Resizing (TaskImageManager, CanvasImageCard)

  • Secure Sandbox Storage: Problem images are copied directly to context.filesDir/task_images/ to prevent URI permission expiration.
  • Viewport Centered Insertion: Spawns newly inserted tasks at the center of the user's current view.
  • Memory-Safe Downscaling: Automatically decodes images with sample sizing to avoid Out-Of-Memory errors with high-resolution photos.
  • Interactive Geometry: Move images anywhere on the infinite canvas; resize proportionally via 4 circular corner handles.

⚡ Performance & Hardware Optimization

OpenMathPad is optimized for modern large-screen tablets (e.g., Xiaomi Pad 7 Pro with 144Hz display, Samsung Galaxy Tab S-series, Lenovo Tab Pen Plus):

Optimization Vector Implementation Strategy Impact
144Hz Viewport Culling Precomputed bounds: Rect cached on all DrawingStroke and CanvasShape instances. In DrawScope, objects outside visibleRect are skipped. Keeps render time under 6.9ms even with 1,000+ strokes on canvas.
Hot-Path Allocations Completely eliminated polygon meshing, per-segment line loops, and heap allocations inside Canvas / DrawScope. Cached Path and Stroke styles. Decoupled via Modifier.graphicsLayer(). Eliminates GC churn and frame drops; maintains solid 144 FPS drawing.
Stroke Hook Filter Vector angle analysis at stroke start detects micro-jitter direction reversals (>110°) and snaps origin to dominant vector. Top-to-bottom lines no longer look like "1" with backwards hooks.
Input Latency Direct real-time coordinate streaming without pull-string delay. Historical batching via MotionEvent.getHistoricalX/Y/Pressure. Zero pen tip trailing lag.
WYSIWYG Fidelity Active stroke committed directly to stroke list upon ACTION_UP without post-processing mutations. Zero visual morphing or jarring deformation upon stylus release.
Grid Rendering Dot grid calculated only within visible viewport bounding box. Constant-time rendering regardless of canvas pan offset.
Memory Safeguards Undo snapshot stack capped to 50 levels (MAX_UNDO_STACK_SIZE). Image bitmaps decoded with memory downscaling. Zero memory leaks across extended drawing sessions.

📱 Hardware & Stylus Compatibility

  • Active Stylus Protocols:
    • Xiaomi Smart Pen / Focus Pen (Xiaomi Pad 6 / 7 / Pro series)
    • Samsung S-Pen (Wacom EMR protocol)
    • Lenovo Precision Pen / Tab Pen Plus
    • Universal Stylus Initiative (USI 2.0)
  • Capacitive Styluses & Finger Drawing: Supported when toggling Touch Mode in the toolbar.

🚀 Getting Started & Build Instructions

Prerequisites

  1. Java Development Kit (JDK): Version 17 or 21.
  2. Android SDK: Compile SDK 37, Min SDK 24 (Android 7.0+).
  3. Android Studio: Ladybug (2024.2.1+) or Meerkat (2024.3.1+).

Clone & Build

# Clone the repository
git clone https://github.com/pochemu-august/OpenMathPad.git
cd OpenMathPad

# Build debug APK
./gradlew :app:assembleDebug

# Run unit tests
./gradlew :app:testDebugUnitTest

🔍 Diagnostics & Memory Profiling

  • In-App Telemetry Badge: Real-time HUD displaying active tool type (STYLUS, FINGER, ERASER), live hardware pressure, zoom factor, pan coordinates, accepted events, and rejected palm touches.
  • LeakCanary 2.14: Integrated in debug builds to monitor view models, Compose trees, and context leaks.
  • Clean Git Tracking: .gitignore configured to exclude IDE caches, build outputs, .agent/ directories, and analysis dumps.

📄 License

This project is open-source and licensed under the MIT License.

Copyright (c) 2026 augustuz / OpenMathPad Contributors

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages