Skip to content

Latest commit

 

History

52 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lunduke Paint

Lunduke Paint is a traditional Linux X11 paint program built with GTK 3.24 and gtkmm-3.0. Look and feel: classic MS Paint + KolourPaint, with Pinta-style user layers.

  • Binary: lunduke-paint
  • Application id: org.lunduke.LundukePaint
  • License: GPL-3.0-or-later
  • Language: C++17
  • Display: Linux X11 (GDK_BACKEND=x11)
  • Chrome: window-manager title bar, menu bar, and toolbars (no client-side decorations, no HeaderBar as main chrome)
  • Theme: follows the active GTK3 theme; the app is not skinned
  • Native project file: OpenRaster .ora (libarchive + pugixml)
  • Version: 0.3
  • Config: $XDG_CONFIG_HOME/lunduke-paint/lunduke-paint.ini via GKeyFile

0.3

Foreground/Background well labels, equal-width tool columns. Keeps the 0.2 feature set. (Howdy intro sources retained but launch-gated off by default.)

0.2

What works:

  • One or more user layers (bottom → top in storage; Layers list is reversed so the top of the list is the top of the stack)
  • Each layer: name, visible, locked, opacity 0–100%, blend, offset, RGBA8888 buffer sized to the document, thumbnail cache
  • Internal ToolLayer + SelectionLayer stay out of the Layers list
  • Compositor draws the visible viewport only with v1 blends: Normal, Multiply, Screen, Overlay, Darken, Lighten
  • Paint/effects affect active layer ∩ selection
  • Locked layer refuses pixel edits (status hint); hidden layers stay in the stack but are omitted from the composite
  • Layers dock: thumbnail, name, eye, lock, opacity; blend combo; New / Duplicate / Delete / Up / Down / Merge down / Flatten; right-click + rename
  • Layers menu: New (Ctrl+Shift+N), Duplicate, Delete, Raise, Lower, Merge down (Ctrl+E), Flatten (Ctrl+Shift+E), Properties
  • Each layer op is one named, undoable Command
  • OpenRaster .ora read/write (mimetype uncompressed first, stack.xml, data/layer-N.png, mergedimage.png; lock as lundukepaint:locked)
  • Non-ORA files still open as a single layer named after the file
  • Save As can pick ora/png/jpeg/bmp; multi-layer flat export warns and can also keep a .ora; never silently overwrites an .ora with a flat PNG
  • JPEG/BMP flatten onto white and warn
  • Multi-tab documents under the tool-options bar; File → Close (Ctrl+W); dirty tab close asks to save; New/Open add a tab (replace only an unused untitled placeholder)
  • Per-document history; the active document drives canvas, layers, colors, undo
  • Pencil, brush, eraser, fill, picker, rect select, line, rectangle, ellipse
  • Color eraser, spraycan, rounded rect, polyline, polygon, curve, text
  • Freeform (lasso) and ellipse select (same move / cut / copy / paste / delete / crop ops)
  • History dock: named list, click an older row to undo there, a newer row to redo
  • Transparent is a first-class FG/BG color (palette last cell + toolbox checker)
  • Canvas size / scale / crop / rotate / flip apply to every user layer
  • Adjustments (active layer, clipped to selection): Brightness/Contrast, Invert, Grayscale, Hue/Saturation, Posterize — each one undoable Command
  • Effects (active layer, clipped to selection): box blur, Sharpen, Emboss — each one undoable Command
  • Preferences: default new-document size, undo limit (default 50, cap 200), checker colors, grid threshold (default 400%)
  • Help: Keyboard Shortcuts window; About (Lunduke Paint, GPL-3.0-or-later, app id org.lunduke.LundukePaint)
  • Print: Gtk::PrintOperation, fit-to-page, Ctrl+P
  • AppStream metainfo (homepage https://lunduke.com, mimetypes), .desktop (%F, MimeType, StartupWMClass=lunduke-paint), hicolor 32/48/96 icons
  • Headless tests: dummy, fill, history, selection, transform, blend, ora, stroke, effects

Out of scope

  • Live text objects (text still rasterizes on commit)
  • Gradient tool
  • Clone stamp
  • ICO load/save
  • Tablet pressure

Development

Development happens in the agent environment; this repo is the published source. This tree is the working copy. Publishing to GitHub is a later joint step (see PUBLISH.md). You do not need to install a toolchain or an IDE on your own machine for day-to-day work.

How you build on X11 (Debian / Ubuntu)

These are the commands the agent runs. They also document how a human can optionally test-build after clone.

sudo apt install -y build-essential meson ninja-build \
  libgtkmm-3.0-dev libcairomm-1.0-dev libgdk-pixbuf-2.0-dev \
  libarchive-dev libpugixml-dev

cd lunduke-paint
meson setup build
meson compile -C build
meson test -C build
GDK_BACKEND=x11 ./build/lunduke-paint

On Debian 13 the pixbuf development package is libgdk-pixbuf-2.0-dev.

A missing DISPLAY is fine for compile and meson test. The GUI is not required for the headless gate.

Optional human test-build

After GitHub publish, a human may clone and run the same commands on an X11 machine if they want a local test-build. That is optional verification, not part of the development loop. Target runtime: Linux X11 / XLibre + XFCE.

Decisions

  • Flood-fill similarity is Chebyshev distance across RGBA (max(|Δr|,|Δg|,|Δb|,|Δa|)), matching classic Paint-style “how far from the seed color.”
  • Eraser always paints the current background color (transparent BG punches alpha); both mouse buttons erase.
  • JPEG and BMP flatten onto white (JPEG quality 90) and warn if the composite has transparency or more than one layer.
  • PNG export from a multi-layer document flattens visible layers and keeps alpha, after a warning.
  • Palette is an 8×6 Paint-like grid; the last swatch is transparent.
  • History stores 32×32 tiles that actually changed inside the stroke dirty rect, not the whole layer.
  • New canvas-resize pixels default to the current background color (Paint-like); the dialog also offers transparent.
  • Image → Clear fills the active layer with the current background color (Paint-like).
  • Delete/Backspace fills the selection with transparency, not the background.
  • Moving a selection is preview-only until deselect; Ctrl during the move copies (original stays).
  • Transparent move skips fully-transparent pixels while dragging and on drop; opaque move replaces the destination rect.
  • Paste creates a floating selection on the active layer at the pointer (viewport center if unknown).
  • Crop to selection uses the rectangle bounds (insensitive for an inverted selection).
  • Autocrop trims any outer row/column that is a single uniform color.
  • Rotate 90 is clockwise.
  • Scale dialog defaults to nearest neighbor and keep-aspect.
  • Pixel grid is on by default and drawn at zoom ≥ the configured threshold (default 400%).
  • Blend onto a fully transparent destination uses the source color (Paint/Pinta-like; Multiply does not go black).
  • Flatten discards hidden layers and composites the visible ones into one Background layer.
  • Merge down blends the active layer onto the one below using the upper layer’s blend and opacity.
  • Layer opacity in the dock commits on Enter or focus-out so a spin does not flood undo.
  • Canvas size, scale, crop, rotate, and flip transform every user layer (KolourPaint/Pinta document ops).
  • New/Open add a tab unless the only document is an unused untitled placeholder, which is replaced.
  • Zoom is stored per document/tab.
  • OpenRaster uses libarchive for the zip and pugixml for stack.xml.
  • History dock starts with “New document”; later rows are command names; click jumps the per-document stack (not saved in .ora).
  • Color eraser replaces FG-similar pixels (Chebyshev) with BG; right-drag swaps the roles.
  • Spraycan drops a disk of random dots; density 1–100 is dots per stamp.
  • Curve is the KolourPaint two-handle cubic: drag endpoints, then two control points.
  • Polyline / polygon take click vertices; Enter or double-click finishes (polygon closes).
  • Lasso and ellipse selections store an 8-bit mask; invert is still “canvas minus that region.”
  • Text is a popup Entry; Pango rasterizes onto the layer on Enter or click-away (not a live object).
  • Toolbox checker under the wells sets Transparent FG (left) or BG (right); painting with it punches alpha.
  • Brightness (−100..100) adds a channel offset; contrast (−100..100) scales around 128.
  • Hue/Saturation is a basic RGB↔HSV shift (hue ±180°, saturation ±100).
  • Posterize quantizes each RGB channel to 2–16 levels.
  • Box blur is separable with edge clamp; radius 1–16. Sharpen is a 3×3 unsharp kernel. Emboss is a 3×3 relief kernel with a +128 bias.
  • Preferences are $XDG_CONFIG_HOME/lunduke-paint/lunduke-paint.ini via GKeyFile (default size, undo limit, checker colors, grid threshold).
  • Print is a single fit-to-page Gtk::PrintOperation of the visible composite, painted on white.
  • File menu includes Recent (local paths in lunduke-paint.ini) and Revert. Edit includes Copy Merged. View includes Fullscreen (F11).
  • Toolbox tool icons are Pinta scalable symbolic SVGs (Paint.NET/Pinta/Fluent MIT, Material Apache-2.0, some GIMP CC-BY-4.0) plus original spray/curve/polyline icons; see data/icons/ATTRIBUTION.md.

Layout

Menu bar, main toolbar, tool-options bar (active tool only), document tabs when more than one file is open, 2-column toolbox with FG/BG wells, canvas with scrollbars, right dock (Colors / Layers / History), status bar (hint | x,y | sel w×h | canvas | zoom | modified). F12 toggles the right dock. History is a click-to-jump list for the active document.

About

Lunduke Paint

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages