go_paint 0.1.0 copy "go_paint: ^0.1.0" to clipboard
go_paint: ^0.1.0 copied to clipboard

A high-performance 120 Hz vector drawing and painting canvas for Flutter with authentic crayon and graphite pencil brushes.

go_paint 🎨 #

pub package License: MIT

A high-performance, 120 Hz vector drawing and painting canvas for Flutter with authentic crayon and graphite pencil brushes, sub-millisecond incremental rendering, and advanced touch kinematics.


✨ Highlights #

  • ⚑ 120 Hz Incremental Pipeline: Sub-millisecond active tip rendering ($< 0.5\text{ ms}$) with $O(1)$ rollback and zero GC pressure during continuous drawing gestures.
  • ✏️ Authentic Graphite Pencil: Dual-pass vector graphite deposition (dense core vein + soft halo graphite bloom) with high-frequency paper tooth lead noise ($\lambda = 3.5\text{ px}$) and natural pressure opacity dynamics ($0.35 - 0.85$).
  • πŸ–οΈ Organic Crayon Brush: Multi-lobed waxy contour extrusion with high-frequency edge perturbation and dynamic exit-taper geometry.
  • πŸ“ Pure Vector Engine: No bitmap textures, raster hacks, or particle spam. Everything is resolution-independent vector geometry that scales crisply to 4K displays.
  • 🎯 Kinematics & Palm Rejection: Built-in velocity/acceleration tracking, corner preservation, low-latency smoothing, and single-finger multi-touch policies.
  • πŸ”„ Undo / Redo & Serialization: Full stroke history stack and JSON-serializable stroke structures.

πŸš€ Getting Started #

Add go_paint to your pubspec.yaml:

dependencies:
  go_paint: ^0.1.0

Then run:

flutter pub get

πŸ’‘ Quickstart #

import 'package:flutter/material.dart';
import 'package:go_paint/go_paint.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: DrawingScreen(),
    );
  }
}

class DrawingScreen extends StatefulWidget {
  const DrawingScreen({super.key});

  @override
  State<DrawingScreen> createState() => _DrawingScreenState();
}

class _DrawingScreenState extends State<DrawingScreen> {
  late final GoPaintController _controller;

  @override
  void initState() {
    super.initState();
    // Default controller with Pencil, Crayon, or Ink renderer
    _controller = GoPaintController();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Go Paint Canvas'),
        actions: [
          IconButton(
            icon: const Icon(Icons.undo),
            onPressed: () => _controller.undo(),
          ),
          IconButton(
            icon: const Icon(Icons.redo),
            onPressed: () => _controller.redo(),
          ),
          IconButton(
            icon: const Icon(Icons.delete_outline),
            onPressed: () => _controller.clear(),
          ),
        ],
      ),
      body: GoPaint(
        controller: _controller,
        backgroundColor: Colors.white,
      ),
    );
  }
}

πŸ–ŒοΈ Built-in Brushes #

1. Graphite Pencil (PencilRenderer) #

Simulates realistic 2B graphite on paper with a soft bloom halo and microscopic paper tooth grain:

_controller.strokeRenderer = PencilRenderer(
  const PencilConfig(
    enablePaperTooth: true,
    enableGraphiteHalo: true,
  ),
);

2. Wax Crayon (CrayonRenderer) #

Simulates textured wax deposition with pressure-sensitive width profile and edge jitter:

_controller.strokeRenderer = CrayonRenderer();

3. Smooth Vector Ink (OutlineInkRenderer) #

Provides clean, laser-crisp calligraphic outlines with smooth Catmull-Rom interpolation:

_controller.strokeRenderer = OutlineInkRenderer();

πŸ“Š Performance Benchmarks #

Measured on standard mobile/desktop hardware during continuous stylus drags:

Stroke Length Full Rebuild Frame Time Incremental Cache Frame Time Speedup
100 points $4.8 - 9.2\text{ ms}$ $0.27 - 0.67\text{ ms}$ $9.4\times$
500 points $27.8 - 37.6\text{ ms}$ $1.88 - 2.64\text{ ms}$ $14.5\times$
1,000 points $78.3 - 193.9\text{ ms}$ $2.31 - 4.33\text{ ms}$ $25.0\times$

Active drawing runs comfortably under $3\text{ ms}$, well below the $8.33\text{ ms}$ frame budget for 120 Hz ProMotion displays.


πŸ› οΈ Building Custom Brushes #

go_paint is fully modular. You can implement your own custom brush (e.g. watercolor, airbrush, chalk) simply by implementing [StrokeRenderer]:

class MyCustomBrushRenderer implements StrokeRenderer {
  @override
  void render(Canvas canvas, Stroke stroke) {
    if (stroke.points.isEmpty) return;
    
    // Your custom math, shaders, or vector paths here!
    final paint = Paint()
      ..color = stroke.color
      ..strokeWidth = stroke.baseWidth
      ..style = PaintingStyle.stroke;

    final path = Path();
    path.moveTo(stroke.points.first.position.dx, stroke.points.first.position.dy);
    for (final pt in stroke.points.skip(1)) {
      path.lineTo(pt.position.dx, pt.position.dy);
    }
    canvas.drawPath(path, paint);
  }
}

// Attach it to your canvas:
_controller.strokeRenderer = MyCustomBrushRenderer();

🀝 Contributing & Community #

Contributions from the open-source community are warmly welcomed!

  • πŸ’‘ Got an idea for a new brush? Open an issue or submit a Pull Request!
  • πŸ› Found a stylus/touch bug? Please report it via our issue tracker.
  • πŸš€ Want to help maintain? We welcome co-maintainers to help review PRs and guide the project.

See CONTRIBUTING.md for architecture guidelines, setup, and test commands.


πŸ“„ License #

MIT License β€” free for personal and commercial use. See LICENSE for details.

0
likes
160
points
61
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A high-performance 120 Hz vector drawing and painting canvas for Flutter with authentic crayon and graphite pencil brushes.

Repository (GitHub)
View/report issues
Contributing

Topics

#drawing #canvas #painting #vector #graphics

License

MIT (license)

Dependencies

flutter

More

Packages that depend on go_paint