mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-10-05 21:02:42 +02:00
core, paint, tools: Port to MyPaint Brushes2
This patch ports our MyPaint code to use the MyPaintSurface2 API, allowing us to support version 2 MyPaint Brushes correctly. The API update lets us take into account the zoom factor and rotation of the canvas when drawing. It also adds a "Gain" option to the GUI in order to control the strength of the input's pressure (tablet or mouse). As a caveat, this patch does not yet implement spectral/pigment blending.
This commit is contained in:
@@ -311,7 +311,7 @@ gimp_core_config_class_init (GimpCoreConfigClass *klass)
|
||||
#ifdef ENABLE_RELOCATABLE_RESOURCES
|
||||
mypaint_brushes = g_build_filename ("${gimp_installation_dir}",
|
||||
"share", "mypaint-data",
|
||||
"1.0", "brushes", NULL);
|
||||
"2.0", "brushes", NULL);
|
||||
#else
|
||||
mypaint_brushes = g_strdup (MYPAINT_BRUSHES_DIR);
|
||||
#endif
|
||||
|
@@ -69,7 +69,7 @@ gimp_mybrush_load (GimpContext *context,
|
||||
G_FILE_ATTRIBUTE_STANDARD_SIZE);
|
||||
g_object_unref (info);
|
||||
|
||||
if (size > 32768)
|
||||
if (size > G_MAXSHORT)
|
||||
{
|
||||
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
|
||||
_("MyPaint brush file is unreasonably large, skipping."));
|
||||
@@ -84,7 +84,7 @@ gimp_mybrush_load (GimpContext *context,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mypaint_brush = mypaint_brush_new ();
|
||||
mypaint_brush = mypaint_brush_new_with_buckets (64);
|
||||
mypaint_brush_from_defaults (mypaint_brush);
|
||||
|
||||
if (! mypaint_brush_from_string (mypaint_brush, (const gchar *) buffer))
|
||||
@@ -147,6 +147,23 @@ gimp_mybrush_load (GimpContext *context,
|
||||
mypaint_brush_get_base_value (mypaint_brush,
|
||||
MYPAINT_BRUSH_SETTING_OFFSET_BY_RANDOM);
|
||||
|
||||
brush->priv->gain =
|
||||
mypaint_brush_get_base_value (mypaint_brush,
|
||||
MYPAINT_BRUSH_SETTING_PRESSURE_GAIN_LOG);
|
||||
|
||||
/* Version 2 MyPaint Brush options */
|
||||
brush->priv->pigment =
|
||||
mypaint_brush_get_base_value (mypaint_brush,
|
||||
MYPAINT_BRUSH_SETTING_PAINT_MODE);
|
||||
|
||||
brush->priv->posterize =
|
||||
mypaint_brush_get_base_value (mypaint_brush,
|
||||
MYPAINT_BRUSH_SETTING_POSTERIZE);
|
||||
|
||||
brush->priv->posterize_num =
|
||||
mypaint_brush_get_base_value (mypaint_brush,
|
||||
MYPAINT_BRUSH_SETTING_POSTERIZE_NUM);
|
||||
|
||||
mypaint_brush_unref (mypaint_brush);
|
||||
|
||||
return g_list_prepend (NULL, brush);
|
||||
|
@@ -27,6 +27,10 @@ struct _GimpMybrushPrivate
|
||||
gdouble radius;
|
||||
gdouble opaque;
|
||||
gdouble hardness;
|
||||
gdouble gain;
|
||||
gdouble pigment;
|
||||
gdouble posterize;
|
||||
gdouble posterize_num;
|
||||
gdouble offset_by_random;
|
||||
gboolean eraser;
|
||||
};
|
||||
|
@@ -98,10 +98,14 @@ gimp_mybrush_init (GimpMybrush *brush)
|
||||
{
|
||||
brush->priv = gimp_mybrush_get_instance_private (brush);
|
||||
|
||||
brush->priv->radius = 1.0;
|
||||
brush->priv->opaque = 1.0;
|
||||
brush->priv->hardness = 1.0;
|
||||
brush->priv->eraser = FALSE;
|
||||
brush->priv->radius = 1.0;
|
||||
brush->priv->opaque = 1.0;
|
||||
brush->priv->hardness = 1.0;
|
||||
brush->priv->gain = 0.0;
|
||||
brush->priv->pigment = 0.0;
|
||||
brush->priv->posterize = 0.0;
|
||||
brush->priv->posterize_num = 1.0;
|
||||
brush->priv->eraser = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -262,6 +266,39 @@ gimp_mybrush_get_hardness (GimpMybrush *brush)
|
||||
return brush->priv->hardness;
|
||||
}
|
||||
|
||||
gdouble
|
||||
gimp_mybrush_get_gain (GimpMybrush *brush)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_MYBRUSH (brush), 0.0);
|
||||
|
||||
return brush->priv->gain;
|
||||
}
|
||||
|
||||
|
||||
gdouble
|
||||
gimp_mybrush_get_pigment (GimpMybrush *brush)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_MYBRUSH (brush), 0.0);
|
||||
|
||||
return brush->priv->pigment;
|
||||
}
|
||||
|
||||
gdouble
|
||||
gimp_mybrush_get_posterize (GimpMybrush *brush)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_MYBRUSH (brush), 0.0);
|
||||
|
||||
return brush->priv->posterize;
|
||||
}
|
||||
|
||||
gdouble
|
||||
gimp_mybrush_get_posterize_num (GimpMybrush *brush)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_MYBRUSH (brush), 0.05);
|
||||
|
||||
return brush->priv->posterize_num;
|
||||
}
|
||||
|
||||
gdouble
|
||||
gimp_mybrush_get_offset_by_random (GimpMybrush *brush)
|
||||
{
|
||||
|
@@ -59,6 +59,10 @@ const gchar * gimp_mybrush_get_brush_json (GimpMybrush *brush);
|
||||
gdouble gimp_mybrush_get_radius (GimpMybrush *brush);
|
||||
gdouble gimp_mybrush_get_opaque (GimpMybrush *brush);
|
||||
gdouble gimp_mybrush_get_hardness (GimpMybrush *brush);
|
||||
gdouble gimp_mybrush_get_gain (GimpMybrush *brush);
|
||||
gdouble gimp_mybrush_get_pigment (GimpMybrush *brush);
|
||||
gdouble gimp_mybrush_get_posterize (GimpMybrush *brush);
|
||||
gdouble gimp_mybrush_get_posterize_num (GimpMybrush *brush);
|
||||
gdouble gimp_mybrush_get_offset_by_random (GimpMybrush *brush);
|
||||
gboolean gimp_mybrush_get_is_eraser (GimpMybrush *brush);
|
||||
|
||||
|
@@ -80,7 +80,10 @@ static void gimp_mybrush_core_motion (GimpPaintCore *paint_core
|
||||
GimpDrawable *drawable,
|
||||
GimpPaintOptions *paint_options,
|
||||
GimpSymmetry *sym,
|
||||
guint32 time);
|
||||
guint32 time,
|
||||
gfloat view_zoom,
|
||||
gfloat view_rotation,
|
||||
gfloat barrel_rotation);
|
||||
static void gimp_mybrush_core_create_brushes (GimpMybrushCore *mybrush,
|
||||
GimpDrawable *drawable,
|
||||
GimpPaintOptions *paint_options,
|
||||
@@ -200,10 +203,11 @@ gimp_mybrush_core_paint (GimpPaintCore *paint_core,
|
||||
GimpPaintState paint_state,
|
||||
guint32 time)
|
||||
{
|
||||
GimpMybrushCore *mybrush = GIMP_MYBRUSH_CORE (paint_core);
|
||||
GimpContext *context = GIMP_CONTEXT (paint_options);
|
||||
gint offset_x;
|
||||
gint offset_y;
|
||||
GimpMybrushCore *mybrush = GIMP_MYBRUSH_CORE (paint_core);
|
||||
GimpMybrushOptions *mybrush_options = GIMP_MYBRUSH_OPTIONS (paint_options);
|
||||
GimpContext *context = GIMP_CONTEXT (paint_options);
|
||||
gint offset_x;
|
||||
gint offset_y;
|
||||
|
||||
g_return_if_fail (g_list_length (drawables) == 1);
|
||||
|
||||
@@ -229,7 +233,8 @@ gimp_mybrush_core_paint (GimpPaintCore *paint_core,
|
||||
|
||||
case GIMP_PAINT_STATE_MOTION:
|
||||
gimp_mybrush_core_motion (paint_core, drawables->data, paint_options,
|
||||
sym, time);
|
||||
sym, time, mybrush_options->view_zoom,
|
||||
mybrush_options->view_rotation, 1.0f);
|
||||
break;
|
||||
|
||||
case GIMP_PAINT_STATE_FINISH:
|
||||
@@ -249,10 +254,14 @@ gimp_mybrush_core_motion (GimpPaintCore *paint_core,
|
||||
GimpDrawable *drawable,
|
||||
GimpPaintOptions *paint_options,
|
||||
GimpSymmetry *sym,
|
||||
guint32 time)
|
||||
guint32 time,
|
||||
gfloat view_zoom,
|
||||
gfloat view_rotation,
|
||||
gfloat barrel_rotation)
|
||||
{
|
||||
GimpMybrushCore *mybrush = GIMP_MYBRUSH_CORE (paint_core);
|
||||
MyPaintRectangle rect;
|
||||
MyPaintRectangles rects = {1, &rect};
|
||||
GimpCoords origin;
|
||||
GList *iter;
|
||||
gdouble dt = 0.0;
|
||||
@@ -288,14 +297,17 @@ gimp_mybrush_core_motion (GimpPaintCore *paint_core,
|
||||
MyPaintBrush *brush = iter->data;
|
||||
GimpCoords coords = *(gimp_symmetry_get_coords (sym, i));
|
||||
|
||||
mypaint_brush_stroke_to (brush,
|
||||
(MyPaintSurface *) mybrush->private->surface,
|
||||
coords.x,
|
||||
coords.y,
|
||||
0.0f,
|
||||
coords.xtilt,
|
||||
coords.ytilt,
|
||||
1.0f /* Pretend the cursor hasn't moved in a while */);
|
||||
mypaint_brush_stroke_to_2 (brush,
|
||||
(MyPaintSurface2 *) mybrush->private->surface,
|
||||
coords.x,
|
||||
coords.y,
|
||||
0.0f,
|
||||
coords.xtilt,
|
||||
coords.ytilt,
|
||||
1.0f, /* Pretend the cursor hasn't moved in a while */
|
||||
view_zoom,
|
||||
view_rotation,
|
||||
barrel_rotation);
|
||||
}
|
||||
|
||||
dt = 0.015;
|
||||
@@ -356,29 +368,36 @@ gimp_mybrush_core_motion (GimpPaintCore *paint_core,
|
||||
gimp_symmetry_set_origin (sym, drawable, &origin);
|
||||
}
|
||||
|
||||
mypaint_brush_stroke_to (brush,
|
||||
(MyPaintSurface *) mybrush->private->surface,
|
||||
coords.x,
|
||||
coords.y,
|
||||
pressure,
|
||||
coords.xtilt,
|
||||
coords.ytilt,
|
||||
dt);
|
||||
mypaint_brush_stroke_to_2 (brush,
|
||||
(MyPaintSurface2 *) mybrush->private->surface,
|
||||
coords.x,
|
||||
coords.y,
|
||||
pressure,
|
||||
coords.xtilt,
|
||||
coords.ytilt,
|
||||
dt,
|
||||
view_zoom,
|
||||
view_rotation,
|
||||
barrel_rotation);
|
||||
}
|
||||
|
||||
mybrush->private->last_time = time;
|
||||
|
||||
mypaint_surface_end_atomic ((MyPaintSurface *) mybrush->private->surface,
|
||||
&rect);
|
||||
mypaint_surface2_end_atomic ((MyPaintSurface2 *) mybrush->private->surface,
|
||||
&rects);
|
||||
|
||||
if (rect.width > 0 && rect.height > 0)
|
||||
if (rects.rectangles[0].width > 0 && rects.rectangles[0].height > 0)
|
||||
{
|
||||
paint_core->x1 = MIN (paint_core->x1, rect.x);
|
||||
paint_core->y1 = MIN (paint_core->y1, rect.y);
|
||||
paint_core->x2 = MAX (paint_core->x2, rect.x + rect.width);
|
||||
paint_core->y2 = MAX (paint_core->y2, rect.y + rect.height);
|
||||
paint_core->x1 = MIN (paint_core->x1, rects.rectangles[0].x);
|
||||
paint_core->y1 = MIN (paint_core->y1, rects.rectangles[0].y);
|
||||
paint_core->x2 = MAX (paint_core->x2,
|
||||
rects.rectangles[0].x + rects.rectangles[0].width);
|
||||
paint_core->y2 = MAX (paint_core->y2,
|
||||
rects.rectangles[0].y + rects.rectangles[0].height);
|
||||
|
||||
gimp_drawable_update (drawable, rect.x, rect.y, rect.width, rect.height);
|
||||
gimp_drawable_update (drawable, rects.rectangles[0].x,
|
||||
rects.rectangles[0].y, rects.rectangles[0].width,
|
||||
rects.rectangles[0].height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,7 +432,7 @@ gimp_mybrush_core_create_brushes (GimpMybrushCore *mybrush,
|
||||
|
||||
for (i = 0; i < n_strokes; i++)
|
||||
{
|
||||
MyPaintBrush *brush = mypaint_brush_new ();
|
||||
MyPaintBrush *brush = mypaint_brush_new_with_buckets (64);
|
||||
const gchar *brush_data;
|
||||
|
||||
mypaint_brush_from_defaults (brush);
|
||||
@@ -445,6 +464,18 @@ gimp_mybrush_core_create_brushes (GimpMybrushCore *mybrush,
|
||||
mypaint_brush_set_base_value (brush,
|
||||
MYPAINT_BRUSH_SETTING_HARDNESS,
|
||||
options->hardness);
|
||||
mypaint_brush_set_base_value (brush,
|
||||
MYPAINT_BRUSH_SETTING_PRESSURE_GAIN_LOG,
|
||||
options->gain);
|
||||
mypaint_brush_set_base_value (brush,
|
||||
MYPAINT_BRUSH_SETTING_PAINT_MODE,
|
||||
options->pigment);
|
||||
mypaint_brush_set_base_value (brush,
|
||||
MYPAINT_BRUSH_SETTING_POSTERIZE,
|
||||
options->posterize);
|
||||
mypaint_brush_set_base_value (brush,
|
||||
MYPAINT_BRUSH_SETTING_POSTERIZE_NUM,
|
||||
options->posterize_num);
|
||||
mypaint_brush_set_base_value (brush,
|
||||
MYPAINT_BRUSH_SETTING_ERASER,
|
||||
(options->eraser &&
|
||||
|
@@ -38,9 +38,15 @@
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_VIEW_ZOOM,
|
||||
PROP_VIEW_ROTATION,
|
||||
PROP_RADIUS,
|
||||
PROP_OPAQUE,
|
||||
PROP_HARDNESS,
|
||||
PROP_GAIN,
|
||||
PROP_PIGMENT,
|
||||
PROP_POSTERIZE,
|
||||
PROP_POSTERIZE_NUM,
|
||||
PROP_ERASER,
|
||||
PROP_NO_ERASING
|
||||
};
|
||||
@@ -82,6 +88,20 @@ gimp_mybrush_options_class_init (GimpMybrushOptionsClass *klass)
|
||||
|
||||
context_class->mybrush_changed = gimp_mybrush_options_mybrush_changed;
|
||||
|
||||
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_RADIUS,
|
||||
"viewzoom",
|
||||
_("View Zoom"),
|
||||
NULL,
|
||||
0.0001, G_MAXFLOAT, 1.0,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_RADIUS,
|
||||
"viewrotation",
|
||||
_("View Rotation"),
|
||||
NULL,
|
||||
-360.0, 360.0, 0.0,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_RADIUS,
|
||||
"radius",
|
||||
_("Radius"),
|
||||
@@ -103,6 +123,31 @@ gimp_mybrush_options_class_init (GimpMybrushOptionsClass *klass)
|
||||
0.0, 1.0, 1.0,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_GAIN,
|
||||
"gain",
|
||||
_("Gain"),
|
||||
_("Adjust strength of input pressue"),
|
||||
-1.8, 1.8, 0.0,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_PIGMENT,
|
||||
"pigment",
|
||||
NULL, NULL,
|
||||
0.0, 1.0, 0.0,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_POSTERIZE,
|
||||
"posterize",
|
||||
NULL, NULL,
|
||||
0.0, 1.0, 0.0,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_POSTERIZE_NUM,
|
||||
"posterizenum",
|
||||
NULL, NULL,
|
||||
0.0, 1.28, 1.0,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ERASER,
|
||||
"eraser",
|
||||
_("Erase with this brush"),
|
||||
@@ -141,14 +186,33 @@ gimp_mybrush_options_set_property (GObject *object,
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_VIEW_ZOOM:
|
||||
options->view_zoom = g_value_get_double (value) > 0.0f ?
|
||||
g_value_get_double (value) : 0.0001f;
|
||||
break;
|
||||
case PROP_VIEW_ROTATION:
|
||||
options->view_rotation = CLAMP (g_value_get_double (value), 0.0f, 360.0f);
|
||||
break;
|
||||
case PROP_RADIUS:
|
||||
options->radius = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_OPAQUE:
|
||||
options->opaque = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_HARDNESS:
|
||||
options->hardness = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_OPAQUE:
|
||||
options->opaque = g_value_get_double (value);
|
||||
case PROP_GAIN:
|
||||
options->gain = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_PIGMENT:
|
||||
options->pigment = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_POSTERIZE:
|
||||
options->posterize = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_POSTERIZE_NUM:
|
||||
options->posterize_num = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_ERASER:
|
||||
options->eraser = g_value_get_boolean (value);
|
||||
@@ -173,6 +237,12 @@ gimp_mybrush_options_get_property (GObject *object,
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_VIEW_ZOOM:
|
||||
g_value_set_double (value, options->view_zoom);
|
||||
break;
|
||||
case PROP_VIEW_ROTATION:
|
||||
g_value_set_double (value, options->view_rotation);
|
||||
break;
|
||||
case PROP_RADIUS:
|
||||
g_value_set_double (value, options->radius);
|
||||
break;
|
||||
@@ -182,6 +252,18 @@ gimp_mybrush_options_get_property (GObject *object,
|
||||
case PROP_HARDNESS:
|
||||
g_value_set_double (value, options->hardness);
|
||||
break;
|
||||
case PROP_GAIN:
|
||||
g_value_set_double (value, options->gain);
|
||||
break;
|
||||
case PROP_PIGMENT:
|
||||
g_value_set_double (value, options->pigment);
|
||||
break;
|
||||
case PROP_POSTERIZE:
|
||||
g_value_set_double (value, options->posterize);
|
||||
break;
|
||||
case PROP_POSTERIZE_NUM:
|
||||
g_value_set_double (value, options->posterize_num);
|
||||
break;
|
||||
case PROP_ERASER:
|
||||
g_value_set_boolean (value, options->eraser);
|
||||
break;
|
||||
@@ -201,10 +283,16 @@ gimp_mybrush_options_mybrush_changed (GimpContext *context,
|
||||
{
|
||||
if (brush)
|
||||
g_object_set (context,
|
||||
"radius", gimp_mybrush_get_radius (brush),
|
||||
"opaque", gimp_mybrush_get_opaque (brush),
|
||||
"hardness", gimp_mybrush_get_hardness (brush),
|
||||
"eraser", gimp_mybrush_get_is_eraser (brush),
|
||||
"viewzoom", 1.0f,
|
||||
"viewrotation", 0.0f,
|
||||
"radius", gimp_mybrush_get_radius (brush),
|
||||
"opaque", gimp_mybrush_get_opaque (brush),
|
||||
"hardness", gimp_mybrush_get_hardness (brush),
|
||||
"gain", gimp_mybrush_get_gain (brush),
|
||||
"pigment", gimp_mybrush_get_pigment (brush),
|
||||
"posterize", gimp_mybrush_get_posterize (brush),
|
||||
"posterizenum", gimp_mybrush_get_posterize_num (brush),
|
||||
"eraser", gimp_mybrush_get_is_eraser (brush),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
@@ -36,9 +36,16 @@ struct _GimpMybrushOptions
|
||||
{
|
||||
GimpPaintOptions parent_instance;
|
||||
|
||||
gdouble view_zoom;
|
||||
gdouble view_rotation;
|
||||
|
||||
gdouble radius;
|
||||
gdouble opaque;
|
||||
gdouble hardness;
|
||||
gdouble gain;
|
||||
gdouble pigment;
|
||||
gdouble posterize;
|
||||
gdouble posterize_num;
|
||||
gboolean eraser;
|
||||
gboolean no_erasing;
|
||||
};
|
||||
|
@@ -34,7 +34,7 @@
|
||||
|
||||
struct _GimpMybrushSurface
|
||||
{
|
||||
MyPaintSurface surface;
|
||||
MyPaintSurface2 surface;
|
||||
GeglBuffer *buffer;
|
||||
GeglBuffer *paint_mask;
|
||||
gint paint_mask_x;
|
||||
@@ -232,17 +232,18 @@ calculate_dab_roi (float x,
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_mypaint_surface_get_color (MyPaintSurface *base_surface,
|
||||
float x,
|
||||
float y,
|
||||
float radius,
|
||||
float *color_r,
|
||||
float *color_g,
|
||||
float *color_b,
|
||||
float *color_a)
|
||||
gimp_mypaint_surface_get_color_2 (MyPaintSurface2 *base_surface,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat radius,
|
||||
gfloat *color_r,
|
||||
gfloat *color_g,
|
||||
gfloat *color_b,
|
||||
gfloat *color_a,
|
||||
gfloat paint)
|
||||
{
|
||||
GimpMybrushSurface *surface = (GimpMybrushSurface *)base_surface;
|
||||
GeglRectangle dabRect;
|
||||
GeglRectangle dabRect;
|
||||
|
||||
if (radius < 1.0f)
|
||||
radius = 1.0f;
|
||||
@@ -334,24 +335,41 @@ gimp_mypaint_surface_get_color (MyPaintSurface *base_surface,
|
||||
*color_a = CLAMP(sum_a, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
gimp_mypaint_surface_draw_dab (MyPaintSurface *base_surface,
|
||||
float x,
|
||||
float y,
|
||||
float radius,
|
||||
float color_r,
|
||||
float color_g,
|
||||
float color_b,
|
||||
float opaque,
|
||||
float hardness,
|
||||
float color_a,
|
||||
float aspect_ratio,
|
||||
float angle,
|
||||
float lock_alpha,
|
||||
float colorize)
|
||||
static void
|
||||
gimp_mypaint_surface_get_color_wrapper (MyPaintSurface *surface,
|
||||
float x,
|
||||
float y,
|
||||
float radius,
|
||||
float *color_r,
|
||||
float *color_g,
|
||||
float *color_b,
|
||||
float *color_a)
|
||||
{
|
||||
return gimp_mypaint_surface_get_color_2 ((MyPaintSurface2 *) surface, x, y, radius,
|
||||
color_r, color_g, color_b, color_a,
|
||||
-1.0);
|
||||
}
|
||||
|
||||
static gint
|
||||
gimp_mypaint_surface_draw_dab_2 (MyPaintSurface2 *base_surface,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat radius,
|
||||
gfloat color_r,
|
||||
gfloat color_g,
|
||||
gfloat color_b,
|
||||
gfloat opaque,
|
||||
gfloat hardness,
|
||||
gfloat color_a,
|
||||
gfloat aspect_ratio,
|
||||
gfloat angle,
|
||||
gfloat lock_alpha,
|
||||
gfloat colorize,
|
||||
gfloat posterize,
|
||||
gfloat posterize_num,
|
||||
gfloat paint)
|
||||
{
|
||||
GimpMybrushSurface *surface = (GimpMybrushSurface *)base_surface;
|
||||
GeglBufferIterator *iter;
|
||||
@@ -370,6 +388,10 @@ gimp_mypaint_surface_draw_dab (MyPaintSurface *base_surface,
|
||||
float segment2_slope;
|
||||
float r_aa_start;
|
||||
|
||||
posterize = CLAMP (posterize, 0.0f, 1.0f);
|
||||
posterize_num = CLAMP (ROUND (posterize_num * 100.0), 1, 128);
|
||||
paint = CLAMP (paint, 0.0f, 1.0f);
|
||||
|
||||
hardness = CLAMP (hardness, 0.0f, 1.0f);
|
||||
segment1_slope = -(1.0f / hardness - 1.0f);
|
||||
segment2_slope = -hardness / (1.0f - hardness);
|
||||
@@ -379,7 +401,7 @@ gimp_mypaint_surface_draw_dab (MyPaintSurface *base_surface,
|
||||
r_aa_start = MAX (r_aa_start, 0);
|
||||
r_aa_start = (r_aa_start * r_aa_start) / aspect_ratio;
|
||||
|
||||
normal_mode = opaque * (1.0f - colorize);
|
||||
normal_mode = opaque * (1.0f - colorize) * (1.0f - posterize);
|
||||
colorize = opaque * colorize;
|
||||
|
||||
/* FIXME: This should use the real matrix values to trim aspect_ratio dabs */
|
||||
@@ -481,6 +503,26 @@ gimp_mypaint_surface_draw_dab (MyPaintSurface *base_surface,
|
||||
}
|
||||
}
|
||||
|
||||
if (posterize > 0.0f && base_alpha > 0.0f)
|
||||
{
|
||||
alpha = base_alpha * posterize;
|
||||
a = alpha + dst_alpha - alpha * dst_alpha;
|
||||
if (a > 0.0f)
|
||||
{
|
||||
gfloat post_pixel[3];
|
||||
gfloat src_term = alpha / a;
|
||||
gfloat dst_term = 1.0f - src_term;
|
||||
|
||||
post_pixel[0] = ROUND (r * posterize_num) / posterize_num;
|
||||
post_pixel[1] = ROUND (g * posterize_num) / posterize_num;
|
||||
post_pixel[2] = ROUND (b * posterize_num) / posterize_num;
|
||||
|
||||
r = post_pixel[0] * src_term + r * dst_term;
|
||||
g = post_pixel[1] * src_term + g * dst_term;
|
||||
b = post_pixel[2] * src_term + b * dst_term;
|
||||
}
|
||||
}
|
||||
|
||||
if (surface->options->no_erasing)
|
||||
a = MAX (a, pixel[ALPHA]);
|
||||
|
||||
@@ -513,6 +555,33 @@ gimp_mypaint_surface_draw_dab (MyPaintSurface *base_surface,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gimp_mypaint_surface_draw_dab_wrapper (MyPaintSurface *surface,
|
||||
float x,
|
||||
float y,
|
||||
float radius,
|
||||
float color_r,
|
||||
float color_g,
|
||||
float color_b,
|
||||
float opaque,
|
||||
float hardness,
|
||||
float color_a,
|
||||
float aspect_ratio,
|
||||
float angle,
|
||||
float lock_alpha,
|
||||
float colorize)
|
||||
{
|
||||
const gfloat posterize = 0.0;
|
||||
const gfloat posterize_num = 1.0;
|
||||
const gfloat pigment = 0.0;
|
||||
|
||||
return gimp_mypaint_surface_draw_dab_2 ((MyPaintSurface2 *) surface, x, y, radius,
|
||||
color_r, color_g, color_b, opaque, hardness,
|
||||
color_a, aspect_ratio, angle, lock_alpha,
|
||||
colorize, posterize, posterize_num,
|
||||
pigment);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_mypaint_surface_begin_atomic (MyPaintSurface *base_surface)
|
||||
{
|
||||
@@ -520,22 +589,39 @@ gimp_mypaint_surface_begin_atomic (MyPaintSurface *base_surface)
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_mypaint_surface_end_atomic (MyPaintSurface *base_surface,
|
||||
MyPaintRectangle *roi)
|
||||
gimp_mypaint_surface_end_atomic_2 (MyPaintSurface2 *base_surface,
|
||||
MyPaintRectangles *rois)
|
||||
{
|
||||
GimpMybrushSurface *surface = (GimpMybrushSurface *)base_surface;
|
||||
|
||||
roi->x = surface->dirty.x;
|
||||
roi->y = surface->dirty.y;
|
||||
roi->width = surface->dirty.width;
|
||||
roi->height = surface->dirty.height;
|
||||
surface->dirty = *GEGL_RECTANGLE (0, 0, 0, 0);
|
||||
if (rois)
|
||||
{
|
||||
const gint roi_rects = rois->num_rectangles;
|
||||
|
||||
for (gint i = 0; i < roi_rects; i++)
|
||||
{
|
||||
rois->rectangles[i].x = surface->dirty.x;
|
||||
rois->rectangles[i].y = surface->dirty.y;
|
||||
rois->rectangles[i].width = surface->dirty.width;
|
||||
rois->rectangles[i].height = surface->dirty.height;
|
||||
surface->dirty = *GEGL_RECTANGLE (0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_mypaint_surface_end_atomic_wrapper (MyPaintSurface *surface,
|
||||
MyPaintRectangle *roi)
|
||||
{
|
||||
MyPaintRectangles rois = {1, roi};
|
||||
|
||||
gimp_mypaint_surface_end_atomic_2 ((MyPaintSurface2 *) surface, &rois);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_mypaint_surface_destroy (MyPaintSurface *base_surface)
|
||||
{
|
||||
GimpMybrushSurface *surface = (GimpMybrushSurface *)base_surface;
|
||||
GimpMybrushSurface *surface = (GimpMybrushSurface *) base_surface;
|
||||
|
||||
g_clear_object (&surface->buffer);
|
||||
g_clear_object (&surface->paint_mask);
|
||||
@@ -551,26 +637,34 @@ gimp_mypaint_surface_new (GeglBuffer *buffer,
|
||||
GimpMybrushOptions *options)
|
||||
{
|
||||
GimpMybrushSurface *surface = g_malloc0 (sizeof (GimpMybrushSurface));
|
||||
MyPaintSurface2 *s;
|
||||
|
||||
mypaint_surface_init ((MyPaintSurface *)surface);
|
||||
mypaint_surface_init (&surface->surface.parent);
|
||||
s = &surface->surface;
|
||||
|
||||
surface->surface.get_color = gimp_mypaint_surface_get_color;
|
||||
surface->surface.draw_dab = gimp_mypaint_surface_draw_dab;
|
||||
surface->surface.begin_atomic = gimp_mypaint_surface_begin_atomic;
|
||||
surface->surface.end_atomic = gimp_mypaint_surface_end_atomic;
|
||||
surface->surface.destroy = gimp_mypaint_surface_destroy;
|
||||
surface->component_mask = component_mask;
|
||||
surface->options = options;
|
||||
surface->buffer = g_object_ref (buffer);
|
||||
s->get_color_pigment = gimp_mypaint_surface_get_color_2;
|
||||
s->draw_dab_pigment = gimp_mypaint_surface_draw_dab_2;
|
||||
s->parent.begin_atomic = gimp_mypaint_surface_begin_atomic;
|
||||
s->end_atomic_multi = gimp_mypaint_surface_end_atomic_2;
|
||||
|
||||
s->parent.draw_dab = gimp_mypaint_surface_draw_dab_wrapper;
|
||||
s->parent.get_color = gimp_mypaint_surface_get_color_wrapper;
|
||||
s->parent.end_atomic = gimp_mypaint_surface_end_atomic_wrapper;
|
||||
|
||||
s->parent.destroy = gimp_mypaint_surface_destroy;
|
||||
|
||||
surface->component_mask = component_mask;
|
||||
surface->options = options;
|
||||
surface->buffer = g_object_ref (buffer);
|
||||
if (paint_mask)
|
||||
surface->paint_mask = g_object_ref (paint_mask);
|
||||
surface->paint_mask = g_object_ref (paint_mask);
|
||||
|
||||
surface->paint_mask_x = paint_mask_x;
|
||||
surface->paint_mask_y = paint_mask_y;
|
||||
surface->dirty = *GEGL_RECTANGLE (0, 0, 0, 0);
|
||||
surface->paint_mask_x = paint_mask_x;
|
||||
surface->paint_mask_y = paint_mask_y;
|
||||
surface->dirty = *GEGL_RECTANGLE (0, 0, 0, 0);
|
||||
|
||||
surface->off_x = 0;
|
||||
surface->off_y = 0;
|
||||
surface->off_x = 0;
|
||||
surface->off_y = 0;
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
@@ -80,6 +80,11 @@ gimp_mybrush_options_gui (GimpToolOptions *tool_options)
|
||||
0.1, 1.0, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* pressure gain */
|
||||
scale = gimp_prop_spin_scale_new (config, "gain",
|
||||
0.1, 0.0, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* erase mode */
|
||||
scale = gimp_prop_check_button_new (config, "eraser", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
|
||||
|
@@ -46,7 +46,10 @@ G_DEFINE_TYPE (GimpMybrushTool, gimp_mybrush_tool, GIMP_TYPE_PAINT_TOOL)
|
||||
|
||||
#define parent_class gimp_mybrush_tool_parent_class
|
||||
|
||||
|
||||
static void gimp_mybrush_tool_cursor_update (GimpTool *tool,
|
||||
const GimpCoords *coords,
|
||||
GdkModifierType state,
|
||||
GimpDisplay *display);
|
||||
static void gimp_mybrush_tool_options_notify (GimpTool *tool,
|
||||
GimpToolOptions *options,
|
||||
const GParamSpec *pspec);
|
||||
@@ -86,6 +89,7 @@ gimp_mybrush_tool_class_init (GimpMybrushToolClass *klass)
|
||||
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
|
||||
GimpPaintToolClass *paint_tool_class = GIMP_PAINT_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->cursor_update = gimp_mybrush_tool_cursor_update;
|
||||
tool_class->options_notify = gimp_mybrush_tool_options_notify;
|
||||
|
||||
paint_tool_class->get_outline = gimp_mybrush_tool_get_outline;
|
||||
@@ -108,6 +112,23 @@ gimp_mybrush_tool_init (GimpMybrushTool *mybrush_tool)
|
||||
GIMP_COLOR_PICK_TARGET_FOREGROUND);
|
||||
}
|
||||
|
||||
static void gimp_mybrush_tool_cursor_update (GimpTool *tool,
|
||||
const GimpCoords *coords,
|
||||
GdkModifierType state,
|
||||
GimpDisplay *display)
|
||||
{
|
||||
GimpDisplayShell *shell;
|
||||
GimpMybrushOptions *options = GIMP_MYBRUSH_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
g_return_if_fail (GIMP_IS_DISPLAY (display));
|
||||
|
||||
shell = gimp_display_get_shell (display);
|
||||
|
||||
options->view_zoom = (gimp_zoom_model_get_factor (shell->zoom) >= 0.0f) ?
|
||||
gimp_zoom_model_get_factor (shell->zoom) : 0.0001f;
|
||||
options->view_rotation = shell->rotate_angle;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_mybrush_tool_options_notify (GimpTool *tool,
|
||||
GimpToolOptions *options,
|
||||
|
@@ -324,7 +324,7 @@ bund_usr "$GIMP_PREFIX" "etc/gimp"
|
||||
|
||||
## Other features and plug-ins
|
||||
### mypaint brushes
|
||||
bund_usr "$UNIX_PREFIX" "share/mypaint-data/1.0"
|
||||
bund_usr "$UNIX_PREFIX" "share/mypaint-data/2.0"
|
||||
### Needed for 'th' word breaking in Text tool etc
|
||||
bund_usr "$UNIX_PREFIX" "share/libthai"
|
||||
conf_app LIBTHAI_DICTDIR "share/libthai"
|
||||
|
@@ -482,16 +482,12 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/mypaint/mypaint-brushes/releases/download/v1.3.1/mypaint-brushes-1.3.1.tar.xz",
|
||||
"sha256": "fef66ffc241b7c5cd29e9c518e933c739618cb51c4ed4d745bf648a1afc3fe70",
|
||||
"url": "https://github.com/mypaint/mypaint-brushes/releases/download/v2.0.2/mypaint-brushes-2.0.2.tar.xz",
|
||||
"sha256": "7984a74edef94571d872d0629b224abaa956a36f632f5c5516b33d22e49eb566",
|
||||
"x-checker-data": {
|
||||
"type": "anitya",
|
||||
"project-id": 17096,
|
||||
"stable-only": true,
|
||||
"//": "https://github.com/mypaint/libmypaint/issues/101",
|
||||
"versions": {
|
||||
"<": "2.0.0"
|
||||
},
|
||||
"url-template": "https://github.com/mypaint/mypaint-brushes/releases/download/v$version/mypaint-brushes-$version.tar.xz"
|
||||
}
|
||||
}
|
||||
|
@@ -42,7 +42,8 @@ if ("$PSCommandPath" -like "*1_build-deps-msys2.ps1*" -or "$CI_JOB_NAME" -like "
|
||||
{
|
||||
& $MSYS_ROOT\usr\bin\pacman --noconfirm -Suy
|
||||
}
|
||||
& $MSYS_ROOT\usr\bin\pacman --noconfirm -S --needed $(if ($MSYSTEM_PREFIX -ne 'mingw32') { "$(if ($MSYSTEM_PREFIX -eq 'clangarm64') { 'mingw-w64-clang-aarch64' } else { 'mingw-w64-clang-x86_64' })-perl" }) (Get-Content build/windows/all-deps-uni.txt | Where-Object { $_.Trim() -ne '' }).Replace('${MINGW_PACKAGE_PREFIX}',$(if ($MINGW_PACKAGE_PREFIX) { "$MINGW_PACKAGE_PREFIX" } elseif ($MSYSTEM_PREFIX -eq 'clangarm64') { 'mingw-w64-clang-aarch64' } else { 'mingw-w64-clang-x86_64' })).Replace(' \','')
|
||||
# TODO: When we drop 32-bit support, move an unconditional mypaint-brushes2 dependency back to all-deps-uni.txt
|
||||
& $MSYS_ROOT\usr\bin\pacman --noconfirm -S --needed $(if ($MSYSTEM_PREFIX -ne 'mingw32') { "$(if ($MSYSTEM_PREFIX -eq 'clangarm64') { 'mingw-w64-clang-aarch64' } else { 'mingw-w64-clang-x86_64' })-perl`n$(if ($MSYSTEM_PREFIX -eq 'clangarm64') { 'mingw-w64-clang-aarch64' } else { 'mingw-w64-clang-x86_64' })-mypaint-brushes2" } else { 'mingw-w64-i686-mypaint-brushes' }) (Get-Content build/windows/all-deps-uni.txt).Replace('${MINGW_PACKAGE_PREFIX}',$(if ($MINGW_PACKAGE_PREFIX) { "$MINGW_PACKAGE_PREFIX" } elseif ($MSYSTEM_PREFIX -eq 'clangarm64') { 'mingw-w64-clang-aarch64' } else { 'mingw-w64-clang-x86_64' })).Replace(' \','')
|
||||
Write-Output "$([char]27)[0Ksection_end:$(Get-Date -UFormat %s -Millisecond 0):deps_install$([char]13)$([char]27)[0K"
|
||||
|
||||
|
||||
|
@@ -14,7 +14,7 @@ if not os.getenv("MESON_BUILD_ROOT"):
|
||||
|
||||
|
||||
# Bundle deps and GIMP files
|
||||
GIMP_SOURCE = Path(os.getenv("MESON_SOURCE_ROOT")).as_posix()
|
||||
GIMP_SOURCE = Path(os.getenv("MESON_SOURCE_ROOT")).as_posix()
|
||||
|
||||
## System prefix: it is MSYSTEM_PREFIX
|
||||
with open("meson-logs/meson-log.txt") as f:
|
||||
@@ -144,7 +144,10 @@ for lang in lang_array:
|
||||
# For language list in text tool options
|
||||
bundle(MSYSTEM_PREFIX, f"share/locale/{lang}/LC_MESSAGES/iso_639_3.mo")
|
||||
### mypaint brushes
|
||||
bundle(MSYSTEM_PREFIX, "share/mypaint-data")
|
||||
if "32" not in MSYSTEM_PREFIX:
|
||||
bundle(MSYSTEM_PREFIX, "share/mypaint-data/2.0")
|
||||
else:
|
||||
bundle(MSYSTEM_PREFIX, "share/mypaint-data/1.0")
|
||||
### Needed for full CJK and Cyrillic support in file-pdf
|
||||
bundle(MSYSTEM_PREFIX, "share/poppler")
|
||||
|
||||
@@ -164,7 +167,7 @@ if (os.getenv("GIMP_UNSTABLE") or not os.getenv("GIMP_RELEASE")) and "32" not in
|
||||
#### See: https://gitlab.gnome.org/GNOME/gimp/-/issues/12119
|
||||
bundle(MSYSTEM_PREFIX, "bin/libgvplugin_dot*.dll")
|
||||
bundle(MSYSTEM_PREFIX, "bin/libgvplugin_pango*.dll")
|
||||
bundle(MSYSTEM_PREFIX, "bin/config6")
|
||||
bundle(MSYSTEM_PREFIX, "bin/config6")
|
||||
### Needed to not pollute output. See: https://gitlab.gnome.org/GNOME/gimp/-/issues/8877
|
||||
bundle(MSYSTEM_PREFIX, "bin/gdbus.exe")
|
||||
### Needed for hyperlink support etc... See: https://gitlab.gnome.org/GNOME/gimp/-/issues/12288
|
||||
@@ -173,7 +176,7 @@ bundle(MSYSTEM_PREFIX, "bin/gspawn*-console.exe")
|
||||
if not os.getenv("GIMP_UNSTABLE") and os.getenv("GIMP_RELEASE"):
|
||||
#...when running from `gimp*.exe`
|
||||
bundle(MSYSTEM_PREFIX, "bin/gspawn*-helper.exe")
|
||||
|
||||
|
||||
## Binaries for GObject Introspection support. See: https://gitlab.gnome.org/GNOME/gimp/-/issues/13170
|
||||
bundle(GIMP_PREFIX, "lib/girepository-*/*.typelib")
|
||||
bundle(MSYSTEM_PREFIX, "bin/libgirepository-*.dll")
|
||||
|
@@ -37,7 +37,6 @@ ${MINGW_PACKAGE_PREFIX}-libtiff \
|
||||
${MINGW_PACKAGE_PREFIX}-libwebp \
|
||||
${MINGW_PACKAGE_PREFIX}-libwmf \
|
||||
${MINGW_PACKAGE_PREFIX}-maxflow \
|
||||
${MINGW_PACKAGE_PREFIX}-mypaint-brushes \
|
||||
${MINGW_PACKAGE_PREFIX}-openexr \
|
||||
${MINGW_PACKAGE_PREFIX}-openjpeg2 \
|
||||
${MINGW_PACKAGE_PREFIX}-pango \
|
||||
|
@@ -444,7 +444,11 @@ lcms_minver = '2.8'
|
||||
lcms = dependency('lcms2', version: '>='+lcms_minver)
|
||||
libmypaint_minver = '1.3.0'
|
||||
libmypaint = dependency('libmypaint', version: '>='+libmypaint_minver)
|
||||
mypaint_brushes = dependency('mypaint-brushes-1.0',version: '>='+libmypaint_minver)
|
||||
mypaint_brushes_n = 'mypaint-brushes-2.0'
|
||||
if platform_windows and host_cpu_family == 'x86'
|
||||
mypaint_brushes_n = 'mypaint-brushes-1.0'
|
||||
endif
|
||||
mypaint_brushes = dependency(mypaint_brushes_n,version: '>='+libmypaint_minver)
|
||||
if not libmypaint.version().version_compare('>=1.4.0')
|
||||
libmypaint_warning='''
|
||||
|
||||
@@ -458,7 +462,7 @@ endif
|
||||
|
||||
if relocatable_bundle
|
||||
mypaint_brushes_dir = '${gimp_installation_dir}'\
|
||||
/'share'/'mypaint-data'/'1.0'/'brushes'
|
||||
/'share'/'mypaint-data'/'2.0'/'brushes'
|
||||
else
|
||||
mypaint_brushes_dir = mypaint_brushes.get_variable(pkgconfig: 'brushesdir')
|
||||
endif
|
||||
|
Reference in New Issue
Block a user