Skip to content

Commit

Permalink
add a hairy brush #116
Browse files Browse the repository at this point in the history
  • Loading branch information
maoschanz committed Feb 25, 2021
1 parent 0c9c135 commit 6b80544
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ If your language is not here, or is incompletely translated, you can
|------|--------------|--------|------------|----------------------------------|
| cs | Czech | 0.6.4 | 96% | [Vojtěch Perník](/~https://github.com/pervoj)
| da | Danish | 0.4.10 | 92% | [scootergrisen](/~https://github.com/scootergrisen)
| de_DE | German | 0.4.1 | 97% | [Onno Giesmann](/~https://github.com/Etamuk)
| de | German | 0.4.1 | 100% | [Onno Giesmann](/~https://github.com/Etamuk)
| | English | 0.2 | 100% | help welcome ** |
| es | Castillan | 0.2 | 97% | [Adolfo Jayme-Barrientos](/~https://github.com/fitojb) and [Xoan Sampaiño](/~https://github.com/xoan)
| eu | Basque | 0.4.14 | 81% | [alexgabi](/~https://github.com/alexgabi)
Expand Down Expand Up @@ -101,6 +101,7 @@ General options for these tools: colors, use antialiasing, size, …
- Pencil (options: dashes, line shape, …)
- *Brushes (pressure sensitive)*:
- *Simple round brush*
- *Hairy brush*
- *Airbrush*
- *Calligraphic nibs*
- *Eraser*
Expand Down
1 change: 1 addition & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
drawing (0.8.0) unstable; urgency=low

* brush supporting pressure-sensitive input (#69, #116)
* hairy brush supporting pressure-sensitive input (#69, #116)
* airbrush supporting pressure-sensitive input (#69, #116)
* calligraphic nip supporting pressure-sensitive input (#69, #116)
* improve the fullscreen mode, with a way to toggle the tools list (#265, #189)
Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ drawing_sources = [
'tools/classic_tools/brushes/abstract_brush.py',
'tools/classic_tools/brushes/brush_airbrush.py',
'tools/classic_tools/brushes/brush_nip.py',
'tools/classic_tools/brushes/brush_hairy.py',
'tools/classic_tools/brushes/brush_simple.py',

'tools/selection_tools/abstract_select.py',
Expand Down
58 changes: 58 additions & 0 deletions src/tools/classic_tools/brushes/brush_hairy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Licensed under GPL3 /~https://github.com/maoschanz/drawing/blob/master/LICENSE

import cairo, random
from .abstract_brush import AbstractBrush

class BrushHairy(AbstractBrush):
__gtype_name__ = 'BrushHairy'

def draw_preview(self, operation, cairo_context):
cairo_context.set_line_cap(cairo.LineCap.ROUND)
cairo_context.set_line_join(cairo.LineJoin.BEVEL)
rgba = operation['rgba']
cairo_context.set_source_rgba(rgba.red, rgba.green, rgba.blue, rgba.alpha)
super().draw_preview(operation, cairo_context)

############################################################################

def do_brush_operation(self, cairo_context, operation):
"""Straight-shaped brush, like an orientable feather pen. The width is
pressure-sensitive but otherwise it's NOT speed sensitive."""

if operation['is_preview']: # Previewing helps performance & debug
return self.draw_preview(operation, cairo_context)

self.operation_on_mask(operation, cairo_context)

def do_masked_brush_op(self, cairo_context, operation):
cairo_context.set_line_cap(cairo.LineCap.ROUND)
cairo_context.set_line_join(cairo.LineJoin.ROUND)
cairo_context.set_line_width(1)

line_width = int(operation['line_width'] / 2)

matrix = []
random.seed(1) # this hardcoded seed avoids the hairs changing their
# positions when the user undoes an following operation
for i in range(line_width * 2):
matrix.append({
'dx': random.randint(-1 * line_width, line_width),
'dy': random.randint(-1 * line_width, line_width)
})
# TODO other kinds of loops to define the matrix?

use_pressure = operation['path'][0]['p'] is not None
pressure = 1
for hair in matrix:
cairo_context.new_path()
for point in operation['path']:
if use_pressure and point['p'] > 0:
pressure = point['p'] * 2
px = point['x'] + hair['dx'] * pressure
py = point['y'] + hair['dy'] * pressure
cairo_context.line_to(px, py)
cairo_context.stroke()

############################################################################
################################################################################

2 changes: 2 additions & 0 deletions src/tools/classic_tools/tool_brush.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .brush_simple import BrushSimple
from .brush_airbrush import BrushAirbrush
from .brush_nip import BrushNip
from .brush_hairy import BrushHairy

class ToolBrush(AbstractClassicTool):
__gtype_name__ = 'ToolBrush'
Expand All @@ -36,6 +37,7 @@ def __init__(self, window, **kwargs):
'simple': BrushSimple('simple', self),
'airbrush': BrushAirbrush('airbrush', self),
'calligraphic': BrushNip('calligraphic', self),
'hairy': BrushHairy('hairy', self),
}

self._brush_type = 'simple'
Expand Down
5 changes: 5 additions & 0 deletions src/tools/ui/tool-brush.ui
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<attribute name="action">win.brush-type</attribute>
<attribute name="target">airbrush</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Hairy brush</attribute>
<attribute name="action">win.brush-type</attribute>
<attribute name="target">hairy</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Calligraphic nib</attribute>
<attribute name="action">win.brush-type</attribute>
Expand Down

0 comments on commit 6b80544

Please sign in to comment.