Faster paintcore
Directly access the brush and paint buffers rather than using GEGL iterators. Replicate the relevant parts of GimpApplicator using direct access.
This commit is contained in:
@ -55,6 +55,8 @@ libapppaint_a_sources = \
|
|||||||
gimpinkundo.h \
|
gimpinkundo.h \
|
||||||
gimppaintcore.c \
|
gimppaintcore.c \
|
||||||
gimppaintcore.h \
|
gimppaintcore.h \
|
||||||
|
gimppaintcore-loops.c \
|
||||||
|
gimppaintcore-loops.h \
|
||||||
gimppaintcore-stroke.c \
|
gimppaintcore-stroke.c \
|
||||||
gimppaintcore-stroke.h \
|
gimppaintcore-stroke.h \
|
||||||
gimppaintcoreundo.c \
|
gimppaintcoreundo.c \
|
||||||
|
|||||||
@ -822,10 +822,17 @@ gimp_brush_core_get_paint_buffer (GimpPaintCore *paint_core,
|
|||||||
if ((x2 - x1) && (y2 - y1))
|
if ((x2 - x1) && (y2 - y1))
|
||||||
{
|
{
|
||||||
GimpTempBuf *temp_buf;
|
GimpTempBuf *temp_buf;
|
||||||
|
const Babl *format;
|
||||||
|
|
||||||
|
if (gimp_drawable_get_linear (drawable))
|
||||||
|
format = babl_format ("RGBA float");
|
||||||
|
else
|
||||||
|
format = babl_format ("R'G'B'A float");
|
||||||
|
|
||||||
if (paint_core->paint_buffer &&
|
if (paint_core->paint_buffer &&
|
||||||
gegl_buffer_get_width (paint_core->paint_buffer) == (x2 - x1) &&
|
gegl_buffer_get_width (paint_core->paint_buffer) == (x2 - x1) &&
|
||||||
gegl_buffer_get_height (paint_core->paint_buffer) == (y2 - y1))
|
gegl_buffer_get_height (paint_core->paint_buffer) == (y2 - y1) &&
|
||||||
|
gegl_buffer_get_format (paint_core->paint_buffer) == format )
|
||||||
{
|
{
|
||||||
*paint_buffer_x = x1;
|
*paint_buffer_x = x1;
|
||||||
*paint_buffer_y = y1;
|
*paint_buffer_y = y1;
|
||||||
@ -834,7 +841,7 @@ gimp_brush_core_get_paint_buffer (GimpPaintCore *paint_core,
|
|||||||
}
|
}
|
||||||
|
|
||||||
temp_buf = gimp_temp_buf_new ((x2 - x1), (y2 - y1),
|
temp_buf = gimp_temp_buf_new ((x2 - x1), (y2 - y1),
|
||||||
babl_format ("RGBA float"));
|
format);
|
||||||
|
|
||||||
*paint_buffer_x = x1;
|
*paint_buffer_x = x1;
|
||||||
*paint_buffer_y = y1;
|
*paint_buffer_y = y1;
|
||||||
@ -939,7 +946,6 @@ gimp_brush_core_paste_canvas (GimpBrushCore *core,
|
|||||||
if (brush_mask)
|
if (brush_mask)
|
||||||
{
|
{
|
||||||
GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
|
GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
|
||||||
GeglBuffer *paint_mask;
|
|
||||||
gint x;
|
gint x;
|
||||||
gint y;
|
gint y;
|
||||||
gint off_x;
|
gint off_x;
|
||||||
@ -951,18 +957,12 @@ gimp_brush_core_paste_canvas (GimpBrushCore *core,
|
|||||||
off_x = (x < 0) ? -x : 0;
|
off_x = (x < 0) ? -x : 0;
|
||||||
off_y = (y < 0) ? -y : 0;
|
off_y = (y < 0) ? -y : 0;
|
||||||
|
|
||||||
paint_mask = gimp_temp_buf_create_buffer ((GimpTempBuf *) brush_mask);
|
gimp_paint_core_paste (paint_core, brush_mask,
|
||||||
|
off_x, off_y,
|
||||||
gimp_paint_core_paste (paint_core, paint_mask,
|
|
||||||
GEGL_RECTANGLE (off_x, off_y,
|
|
||||||
gegl_buffer_get_width (paint_core->paint_buffer),
|
|
||||||
gegl_buffer_get_height (paint_core->paint_buffer)),
|
|
||||||
drawable,
|
drawable,
|
||||||
brush_opacity,
|
brush_opacity,
|
||||||
image_opacity, paint_mode,
|
image_opacity, paint_mode,
|
||||||
mode);
|
mode);
|
||||||
|
|
||||||
g_object_unref (paint_mask);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -989,7 +989,6 @@ gimp_brush_core_replace_canvas (GimpBrushCore *core,
|
|||||||
if (brush_mask)
|
if (brush_mask)
|
||||||
{
|
{
|
||||||
GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
|
GimpPaintCore *paint_core = GIMP_PAINT_CORE (core);
|
||||||
GeglBuffer *paint_mask;
|
|
||||||
gint x;
|
gint x;
|
||||||
gint y;
|
gint y;
|
||||||
gint off_x;
|
gint off_x;
|
||||||
@ -1001,18 +1000,12 @@ gimp_brush_core_replace_canvas (GimpBrushCore *core,
|
|||||||
off_x = (x < 0) ? -x : 0;
|
off_x = (x < 0) ? -x : 0;
|
||||||
off_y = (y < 0) ? -y : 0;
|
off_y = (y < 0) ? -y : 0;
|
||||||
|
|
||||||
paint_mask = gimp_temp_buf_create_buffer ((GimpTempBuf *) brush_mask);
|
gimp_paint_core_replace (paint_core, brush_mask,
|
||||||
|
off_x, off_y,
|
||||||
gimp_paint_core_replace (paint_core, paint_mask,
|
|
||||||
GEGL_RECTANGLE (off_x, off_y,
|
|
||||||
gegl_buffer_get_width (paint_core->paint_buffer),
|
|
||||||
gegl_buffer_get_height (paint_core->paint_buffer)),
|
|
||||||
drawable,
|
drawable,
|
||||||
brush_opacity,
|
brush_opacity,
|
||||||
image_opacity,
|
image_opacity,
|
||||||
mode);
|
mode);
|
||||||
|
|
||||||
g_object_unref (paint_mask);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -220,9 +220,15 @@ gimp_ink_get_paint_buffer (GimpPaintCore *paint_core,
|
|||||||
if ((x2 - x1) && (y2 - y1))
|
if ((x2 - x1) && (y2 - y1))
|
||||||
{
|
{
|
||||||
GimpTempBuf *temp_buf;
|
GimpTempBuf *temp_buf;
|
||||||
|
const Babl *format;
|
||||||
|
|
||||||
|
if (gimp_drawable_get_linear (drawable))
|
||||||
|
format = babl_format ("RGBA float");
|
||||||
|
else
|
||||||
|
format = babl_format ("R'G'B'A float");
|
||||||
|
|
||||||
temp_buf = gimp_temp_buf_new ((x2 - x1), (y2 - y1),
|
temp_buf = gimp_temp_buf_new ((x2 - x1), (y2 - y1),
|
||||||
babl_format ("RGBA float"));
|
format);
|
||||||
|
|
||||||
*paint_buffer_x = x1;
|
*paint_buffer_x = x1;
|
||||||
*paint_buffer_y = y1;
|
*paint_buffer_y = y1;
|
||||||
@ -332,11 +338,9 @@ gimp_ink_motion (GimpPaintCore *paint_core,
|
|||||||
|
|
||||||
/* draw the paint_area using the just rendered canvas_buffer as mask */
|
/* draw the paint_area using the just rendered canvas_buffer as mask */
|
||||||
gimp_paint_core_paste (paint_core,
|
gimp_paint_core_paste (paint_core,
|
||||||
paint_core->canvas_buffer,
|
NULL,
|
||||||
GEGL_RECTANGLE (paint_core->paint_buffer_x,
|
paint_core->paint_buffer_x,
|
||||||
paint_core->paint_buffer_y,
|
paint_core->paint_buffer_y,
|
||||||
gegl_buffer_get_width (paint_core->paint_buffer),
|
|
||||||
gegl_buffer_get_height (paint_core->paint_buffer)),
|
|
||||||
drawable,
|
drawable,
|
||||||
GIMP_OPACITY_OPAQUE,
|
GIMP_OPACITY_OPAQUE,
|
||||||
gimp_context_get_opacity (context),
|
gimp_context_get_opacity (context),
|
||||||
|
|||||||
415
app/paint/gimppaintcore-loops.c
Normal file
415
app/paint/gimppaintcore-loops.c
Normal file
@ -0,0 +1,415 @@
|
|||||||
|
/* GIMP - The GNU Image Manipulation Program
|
||||||
|
* Copyright (C) 2013 Daniel Sabo
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <gegl.h>
|
||||||
|
|
||||||
|
#include "paint-types.h"
|
||||||
|
|
||||||
|
#include "core/gimptempbuf.h"
|
||||||
|
#include "gimppaintcore-loops.h"
|
||||||
|
#include "operations/gimplayermodefunctions.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask,
|
||||||
|
gint mask_x_offset,
|
||||||
|
gint mask_y_offset,
|
||||||
|
GeglBuffer *canvas_buffer,
|
||||||
|
gint x_offset,
|
||||||
|
gint y_offset,
|
||||||
|
gfloat opacity,
|
||||||
|
gboolean stipple)
|
||||||
|
{
|
||||||
|
GeglRectangle roi;
|
||||||
|
GeglBufferIterator *iter;
|
||||||
|
|
||||||
|
const gint mask_stride = gimp_temp_buf_get_width (paint_mask);
|
||||||
|
const gint mask_start_offset = mask_y_offset * mask_stride + mask_x_offset;
|
||||||
|
const Babl *mask_format = gimp_temp_buf_get_format (paint_mask);
|
||||||
|
|
||||||
|
roi.x = x_offset;
|
||||||
|
roi.y = y_offset;
|
||||||
|
roi.width = gimp_temp_buf_get_width (paint_mask) - mask_x_offset;
|
||||||
|
roi.height = gimp_temp_buf_get_height (paint_mask) - mask_y_offset;
|
||||||
|
|
||||||
|
iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0,
|
||||||
|
babl_format ("Y float"),
|
||||||
|
GEGL_BUFFER_READWRITE, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
|
if (stipple)
|
||||||
|
{
|
||||||
|
if (mask_format == babl_format ("Y u8"))
|
||||||
|
{
|
||||||
|
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
|
||||||
|
mask_data += mask_start_offset;
|
||||||
|
|
||||||
|
while (gegl_buffer_iterator_next (iter))
|
||||||
|
{
|
||||||
|
gfloat *out_pixel = (gfloat *)iter->data[0];
|
||||||
|
int iy, ix;
|
||||||
|
|
||||||
|
for (iy = 0; iy < iter->roi[0].height; iy++)
|
||||||
|
{
|
||||||
|
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
|
||||||
|
const guint8 *mask_pixel = &mask_data[mask_offset];
|
||||||
|
|
||||||
|
for (ix = 0; ix < iter->roi[0].width; ix++)
|
||||||
|
{
|
||||||
|
out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity;
|
||||||
|
|
||||||
|
mask_pixel += 1;
|
||||||
|
out_pixel += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mask_format == babl_format ("Y float"))
|
||||||
|
{
|
||||||
|
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
|
||||||
|
mask_data += mask_start_offset;
|
||||||
|
|
||||||
|
while (gegl_buffer_iterator_next (iter))
|
||||||
|
{
|
||||||
|
gfloat *out_pixel = (gfloat *)iter->data[0];
|
||||||
|
int iy, ix;
|
||||||
|
|
||||||
|
for (iy = 0; iy < iter->roi[0].height; iy++)
|
||||||
|
{
|
||||||
|
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
|
||||||
|
const gfloat *mask_pixel = &mask_data[mask_offset];
|
||||||
|
|
||||||
|
for (ix = 0; ix < iter->roi[0].width; ix++)
|
||||||
|
{
|
||||||
|
out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel) * opacity;
|
||||||
|
|
||||||
|
mask_pixel += 1;
|
||||||
|
out_pixel += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning("Mask format not supported: %s", babl_get_name (mask_format));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mask_format == babl_format ("Y u8"))
|
||||||
|
{
|
||||||
|
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
|
||||||
|
mask_data += mask_start_offset;
|
||||||
|
|
||||||
|
while (gegl_buffer_iterator_next (iter))
|
||||||
|
{
|
||||||
|
gfloat *out_pixel = (gfloat *)iter->data[0];
|
||||||
|
int iy, ix;
|
||||||
|
|
||||||
|
for (iy = 0; iy < iter->roi[0].height; iy++)
|
||||||
|
{
|
||||||
|
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
|
||||||
|
const guint8 *mask_pixel = &mask_data[mask_offset];
|
||||||
|
|
||||||
|
for (ix = 0; ix < iter->roi[0].width; ix++)
|
||||||
|
{
|
||||||
|
if (opacity > out_pixel[0])
|
||||||
|
out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity;
|
||||||
|
|
||||||
|
mask_pixel += 1;
|
||||||
|
out_pixel += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mask_format == babl_format ("Y float"))
|
||||||
|
{
|
||||||
|
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
|
||||||
|
mask_data += mask_start_offset;
|
||||||
|
|
||||||
|
while (gegl_buffer_iterator_next (iter))
|
||||||
|
{
|
||||||
|
gfloat *out_pixel = (gfloat *)iter->data[0];
|
||||||
|
int iy, ix;
|
||||||
|
|
||||||
|
for (iy = 0; iy < iter->roi[0].height; iy++)
|
||||||
|
{
|
||||||
|
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
|
||||||
|
const gfloat *mask_pixel = &mask_data[mask_offset];
|
||||||
|
|
||||||
|
for (ix = 0; ix < iter->roi[0].width; ix++)
|
||||||
|
{
|
||||||
|
if (opacity > out_pixel[0])
|
||||||
|
out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel) * opacity;
|
||||||
|
|
||||||
|
mask_pixel += 1;
|
||||||
|
out_pixel += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning("Mask format not supported: %s", babl_get_name (mask_format));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
canvas_buffer_to_paint_buf_alpha (GimpTempBuf *paint_buf,
|
||||||
|
GeglBuffer *canvas_buffer,
|
||||||
|
gint x_offset,
|
||||||
|
gint y_offset)
|
||||||
|
{
|
||||||
|
/* Copy the canvas buffer in rect to the paint buffer's alpha channel */
|
||||||
|
GeglRectangle roi;
|
||||||
|
GeglBufferIterator *iter;
|
||||||
|
|
||||||
|
const guint paint_stride = gimp_temp_buf_get_width (paint_buf);
|
||||||
|
gfloat *paint_data = (gfloat *) gimp_temp_buf_get_data (paint_buf);
|
||||||
|
|
||||||
|
roi.x = x_offset;
|
||||||
|
roi.y = y_offset;
|
||||||
|
roi.width = gimp_temp_buf_get_width (paint_buf);
|
||||||
|
roi.height = gimp_temp_buf_get_height (paint_buf);
|
||||||
|
|
||||||
|
iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0,
|
||||||
|
babl_format ("Y float"),
|
||||||
|
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
|
||||||
|
while (gegl_buffer_iterator_next (iter))
|
||||||
|
{
|
||||||
|
gfloat *canvas_pixel = (gfloat *)iter->data[0];
|
||||||
|
int iy, ix;
|
||||||
|
|
||||||
|
for (iy = 0; iy < iter->roi[0].height; iy++)
|
||||||
|
{
|
||||||
|
int paint_offset = (iy + iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - roi.x;
|
||||||
|
float *paint_pixel = &paint_data[paint_offset * 4];
|
||||||
|
|
||||||
|
for (ix = 0; ix < iter->roi[0].width; ix++)
|
||||||
|
{
|
||||||
|
paint_pixel[3] *= *canvas_pixel;
|
||||||
|
|
||||||
|
canvas_pixel += 1;
|
||||||
|
paint_pixel += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
paint_mask_to_paint_buffer (const GimpTempBuf *paint_mask,
|
||||||
|
gint mask_x_offset,
|
||||||
|
gint mask_y_offset,
|
||||||
|
GimpTempBuf *paint_buf,
|
||||||
|
gfloat paint_opacity)
|
||||||
|
{
|
||||||
|
gint width = gimp_temp_buf_get_width (paint_buf);
|
||||||
|
gint height = gimp_temp_buf_get_height (paint_buf);
|
||||||
|
|
||||||
|
const gint mask_stride = gimp_temp_buf_get_width (paint_mask);
|
||||||
|
const gint mask_start_offset = mask_y_offset * mask_stride + mask_x_offset;
|
||||||
|
const Babl *mask_format = gimp_temp_buf_get_format (paint_mask);
|
||||||
|
|
||||||
|
int iy, ix;
|
||||||
|
gfloat *paint_pixel = (gfloat *)gimp_temp_buf_get_data (paint_buf);
|
||||||
|
|
||||||
|
/* Validate that the paint buffer is withing the bounds of the paint mask */
|
||||||
|
g_return_if_fail (width <= gimp_temp_buf_get_width (paint_mask) - mask_x_offset);
|
||||||
|
g_return_if_fail (height <= gimp_temp_buf_get_height (paint_mask) - mask_y_offset);
|
||||||
|
|
||||||
|
if (mask_format == babl_format ("Y u8"))
|
||||||
|
{
|
||||||
|
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
|
||||||
|
mask_data += mask_start_offset;
|
||||||
|
|
||||||
|
for (iy = 0; iy < height; iy++)
|
||||||
|
{
|
||||||
|
int mask_offset = iy * mask_stride;
|
||||||
|
const guint8 *mask_pixel = &mask_data[mask_offset];
|
||||||
|
|
||||||
|
for (ix = 0; ix < width; ix++)
|
||||||
|
{
|
||||||
|
paint_pixel[3] *= (((gfloat)*mask_pixel) / 255.0f) * paint_opacity;
|
||||||
|
|
||||||
|
mask_pixel += 1;
|
||||||
|
paint_pixel += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mask_format == babl_format ("Y float"))
|
||||||
|
{
|
||||||
|
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
|
||||||
|
mask_data += mask_start_offset;
|
||||||
|
|
||||||
|
for (iy = 0; iy < height; iy++)
|
||||||
|
{
|
||||||
|
int mask_offset = iy * mask_stride;
|
||||||
|
const gfloat *mask_pixel = &mask_data[mask_offset];
|
||||||
|
|
||||||
|
for (ix = 0; ix < width; ix++)
|
||||||
|
{
|
||||||
|
paint_pixel[3] *= (*mask_pixel) * paint_opacity;
|
||||||
|
|
||||||
|
mask_pixel += 1;
|
||||||
|
paint_pixel += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
do_layer_blend (GeglBuffer *src_buffer,
|
||||||
|
GeglBuffer *dst_buffer,
|
||||||
|
GimpTempBuf *paint_buf,
|
||||||
|
GeglBuffer *mask_buffer,
|
||||||
|
gfloat opacity,
|
||||||
|
gint x_offset,
|
||||||
|
gint y_offset,
|
||||||
|
gint mask_x_offset,
|
||||||
|
gint mask_y_offset,
|
||||||
|
gboolean linear_mode,
|
||||||
|
GimpLayerModeEffects paint_mode)
|
||||||
|
{
|
||||||
|
GeglRectangle roi;
|
||||||
|
GeglRectangle mask_roi;
|
||||||
|
GeglRectangle process_roi;
|
||||||
|
const Babl *iterator_format;
|
||||||
|
GeglBufferIterator *iter;
|
||||||
|
|
||||||
|
const guint paint_stride = gimp_temp_buf_get_width (paint_buf);
|
||||||
|
gfloat *paint_data = (gfloat *) gimp_temp_buf_get_data (paint_buf);
|
||||||
|
|
||||||
|
GimpLayerModeFunction apply_func = get_layer_mode_function (paint_mode);
|
||||||
|
|
||||||
|
if (linear_mode)
|
||||||
|
iterator_format = babl_format ("RGBA float");
|
||||||
|
else
|
||||||
|
iterator_format = babl_format ("R'G'B'A float");
|
||||||
|
|
||||||
|
roi.x = x_offset;
|
||||||
|
roi.y = y_offset;
|
||||||
|
roi.width = gimp_temp_buf_get_width (paint_buf);
|
||||||
|
roi.height = gimp_temp_buf_get_height (paint_buf);
|
||||||
|
|
||||||
|
mask_roi.x = roi.x + mask_x_offset;
|
||||||
|
mask_roi.y = roi.y + mask_y_offset;
|
||||||
|
mask_roi.width = roi.width;
|
||||||
|
mask_roi.height = roi.height;
|
||||||
|
|
||||||
|
g_return_if_fail (gimp_temp_buf_get_format (paint_buf) == iterator_format);
|
||||||
|
|
||||||
|
iter = gegl_buffer_iterator_new (dst_buffer, &roi, 0,
|
||||||
|
iterator_format,
|
||||||
|
GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
|
gegl_buffer_iterator_add (iter, src_buffer, &roi, 0,
|
||||||
|
iterator_format,
|
||||||
|
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
|
if (mask_buffer)
|
||||||
|
{
|
||||||
|
gegl_buffer_iterator_add (iter, mask_buffer, &mask_roi, 0,
|
||||||
|
babl_format ("Y float"),
|
||||||
|
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (gegl_buffer_iterator_next(iter))
|
||||||
|
{
|
||||||
|
gfloat *out_pixel = (gfloat *)iter->data[0];
|
||||||
|
gfloat *in_pixel = (gfloat *)iter->data[1];
|
||||||
|
gfloat *mask_pixel = NULL;
|
||||||
|
gfloat *paint_pixel = paint_data + ((iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - roi.x) * 4;
|
||||||
|
int iy;
|
||||||
|
|
||||||
|
if (mask_buffer)
|
||||||
|
mask_pixel = (gfloat *)iter->data[2];
|
||||||
|
|
||||||
|
process_roi.x = iter->roi[0].x;
|
||||||
|
process_roi.width = iter->roi[0].width;
|
||||||
|
process_roi.height = 1;
|
||||||
|
|
||||||
|
for (iy = 0; iy < iter->roi[0].height; iy++)
|
||||||
|
{
|
||||||
|
process_roi.x = iter->roi[0].y + iy;
|
||||||
|
|
||||||
|
(*apply_func) (in_pixel,
|
||||||
|
paint_pixel,
|
||||||
|
mask_pixel,
|
||||||
|
out_pixel,
|
||||||
|
opacity,
|
||||||
|
iter->roi[0].width,
|
||||||
|
&process_roi,
|
||||||
|
0);
|
||||||
|
|
||||||
|
in_pixel += iter->roi[0].width * 4;
|
||||||
|
out_pixel += iter->roi[0].width * 4;
|
||||||
|
if (mask_buffer)
|
||||||
|
mask_pixel += iter->roi[0].width;
|
||||||
|
paint_pixel += paint_stride * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mask_components_onto (GeglBuffer *src_buffer,
|
||||||
|
GeglBuffer *aux_buffer,
|
||||||
|
GeglBuffer *dst_buffer,
|
||||||
|
GeglRectangle *roi,
|
||||||
|
GimpComponentMask mask,
|
||||||
|
gboolean linear_mode)
|
||||||
|
{
|
||||||
|
GeglBufferIterator *iter;
|
||||||
|
const Babl *iterator_format;
|
||||||
|
|
||||||
|
if (linear_mode)
|
||||||
|
iterator_format = babl_format ("RGBA float");
|
||||||
|
else
|
||||||
|
iterator_format = babl_format ("R'G'B'A float");
|
||||||
|
|
||||||
|
iter = gegl_buffer_iterator_new (dst_buffer, roi, 0,
|
||||||
|
iterator_format,
|
||||||
|
GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
|
gegl_buffer_iterator_add (iter, src_buffer, roi, 0,
|
||||||
|
iterator_format,
|
||||||
|
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
|
gegl_buffer_iterator_add (iter, aux_buffer, roi, 0,
|
||||||
|
iterator_format,
|
||||||
|
GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
|
||||||
|
|
||||||
|
while (gegl_buffer_iterator_next(iter))
|
||||||
|
{
|
||||||
|
gfloat *dest = (gfloat *)iter->data[0];
|
||||||
|
gfloat *src = (gfloat *)iter->data[1];
|
||||||
|
gfloat *aux = (gfloat *)iter->data[2];
|
||||||
|
glong samples = iter->length;
|
||||||
|
|
||||||
|
while (samples--)
|
||||||
|
{
|
||||||
|
dest[RED] = (mask & GIMP_COMPONENT_RED) ? aux[RED] : src[RED];
|
||||||
|
dest[GREEN] = (mask & GIMP_COMPONENT_GREEN) ? aux[GREEN] : src[GREEN];
|
||||||
|
dest[BLUE] = (mask & GIMP_COMPONENT_BLUE) ? aux[BLUE] : src[BLUE];
|
||||||
|
dest[ALPHA] = (mask & GIMP_COMPONENT_ALPHA) ? aux[ALPHA] : src[ALPHA];
|
||||||
|
|
||||||
|
src += 4;
|
||||||
|
aux += 4;
|
||||||
|
dest += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
app/paint/gimppaintcore-loops.h
Normal file
55
app/paint/gimppaintcore-loops.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* GIMP - The GNU Image Manipulation Program
|
||||||
|
* Copyright (C) 2013 Daniel Sabo
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask,
|
||||||
|
gint mask_x_offset,
|
||||||
|
gint mask_y_offset,
|
||||||
|
GeglBuffer *canvas_buffer,
|
||||||
|
gint x_offset,
|
||||||
|
gint y_offset,
|
||||||
|
gfloat opacity,
|
||||||
|
gboolean stipple);
|
||||||
|
|
||||||
|
void canvas_buffer_to_paint_buf_alpha (GimpTempBuf *paint_buf,
|
||||||
|
GeglBuffer *canvas_buffer,
|
||||||
|
gint x_offset,
|
||||||
|
gint y_offset);
|
||||||
|
|
||||||
|
void paint_mask_to_paint_buffer (const GimpTempBuf *paint_mask,
|
||||||
|
gint mask_x_offset,
|
||||||
|
gint mask_y_offset,
|
||||||
|
GimpTempBuf *paint_buf,
|
||||||
|
gfloat paint_opacity);
|
||||||
|
|
||||||
|
void do_layer_blend (GeglBuffer *src_buffer,
|
||||||
|
GeglBuffer *dst_buffer,
|
||||||
|
GimpTempBuf *paint_buf,
|
||||||
|
GeglBuffer *mask_buffer,
|
||||||
|
gfloat opacity,
|
||||||
|
gint x_offset,
|
||||||
|
gint y_offset,
|
||||||
|
gint mask_x_offset,
|
||||||
|
gint mask_y_offset,
|
||||||
|
gboolean linear_mode,
|
||||||
|
GimpLayerModeEffects paint_mode);
|
||||||
|
|
||||||
|
void mask_components_onto (GeglBuffer *src_buffer,
|
||||||
|
GeglBuffer *aux_buffer,
|
||||||
|
GeglBuffer *dst_buffer,
|
||||||
|
GeglRectangle *roi,
|
||||||
|
GimpComponentMask mask,
|
||||||
|
gboolean linear_mode);
|
||||||
@ -1,5 +1,6 @@
|
|||||||
/* GIMP - The GNU Image Manipulation Program
|
/* GIMP - The GNU Image Manipulation Program
|
||||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||||
|
* Copyright (C) 2013 Daniel Sabo
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -26,10 +27,8 @@
|
|||||||
|
|
||||||
#include "paint-types.h"
|
#include "paint-types.h"
|
||||||
|
|
||||||
#include "gegl/gimp-gegl-loops.h"
|
|
||||||
#include "gegl/gimp-gegl-nodes.h"
|
#include "gegl/gimp-gegl-nodes.h"
|
||||||
#include "gegl/gimp-gegl-utils.h"
|
#include "gegl/gimp-gegl-utils.h"
|
||||||
#include "gegl/gimpapplicator.h"
|
|
||||||
|
|
||||||
#include "core/gimp.h"
|
#include "core/gimp.h"
|
||||||
#include "core/gimp-utils.h"
|
#include "core/gimp-utils.h"
|
||||||
@ -42,6 +41,7 @@
|
|||||||
|
|
||||||
#include "gimppaintcore.h"
|
#include "gimppaintcore.h"
|
||||||
#include "gimppaintcoreundo.h"
|
#include "gimppaintcoreundo.h"
|
||||||
|
#include "gimppaintcore-loops.h"
|
||||||
#include "gimppaintoptions.h"
|
#include "gimppaintoptions.h"
|
||||||
|
|
||||||
#include "gimpairbrush.h"
|
#include "gimpairbrush.h"
|
||||||
@ -405,9 +405,6 @@ gimp_paint_core_start (GimpPaintCore *core,
|
|||||||
if (GIMP_DRAWABLE (mask) == drawable || gimp_channel_is_empty (mask))
|
if (GIMP_DRAWABLE (mask) == drawable || gimp_channel_is_empty (mask))
|
||||||
mask = NULL;
|
mask = NULL;
|
||||||
|
|
||||||
core->applicator = gimp_applicator_new (NULL,
|
|
||||||
gimp_drawable_get_linear (drawable));
|
|
||||||
|
|
||||||
if (mask)
|
if (mask)
|
||||||
{
|
{
|
||||||
GeglBuffer *mask_buffer;
|
GeglBuffer *mask_buffer;
|
||||||
@ -417,15 +414,42 @@ gimp_paint_core_start (GimpPaintCore *core,
|
|||||||
mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
|
mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
|
||||||
gimp_item_get_offset (item, &offset_x, &offset_y);
|
gimp_item_get_offset (item, &offset_x, &offset_y);
|
||||||
|
|
||||||
gimp_applicator_set_mask_buffer (core->applicator, mask_buffer);
|
g_object_ref (mask_buffer);
|
||||||
gimp_applicator_set_mask_offset (core->applicator,
|
core->mask_buffer = mask_buffer;
|
||||||
-offset_x, -offset_y);
|
core->mask_x_offset = -offset_x;
|
||||||
|
core->mask_y_offset = -offset_y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core->mask_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gimp_applicator_set_affect (core->applicator,
|
core->linear_mode = gimp_drawable_get_linear (drawable);
|
||||||
gimp_drawable_get_active_mask (drawable));
|
|
||||||
gimp_applicator_set_dest_buffer (core->applicator,
|
/* Allocate the scratch buffer if there's a component mask */
|
||||||
gimp_drawable_get_buffer (drawable));
|
if (gimp_drawable_get_active_mask (drawable) != GIMP_COMPONENT_ALL)
|
||||||
|
{
|
||||||
|
if (core->linear_mode)
|
||||||
|
{
|
||||||
|
core->comp_buffer =
|
||||||
|
gegl_buffer_new (GEGL_RECTANGLE (0, 0,
|
||||||
|
gimp_item_get_width (item),
|
||||||
|
gimp_item_get_height (item)),
|
||||||
|
babl_format ("RGBA float"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core->comp_buffer =
|
||||||
|
gegl_buffer_new (GEGL_RECTANGLE (0, 0,
|
||||||
|
gimp_item_get_width (item),
|
||||||
|
gimp_item_get_height (item)),
|
||||||
|
babl_format ("R'G'B'A float"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core->comp_buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Freeze the drawable preview so that it isn't constantly updated. */
|
/* Freeze the drawable preview so that it isn't constantly updated. */
|
||||||
gimp_viewable_preview_freeze (GIMP_VIEWABLE (drawable));
|
gimp_viewable_preview_freeze (GIMP_VIEWABLE (drawable));
|
||||||
@ -444,18 +468,24 @@ gimp_paint_core_finish (GimpPaintCore *core,
|
|||||||
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
||||||
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
||||||
|
|
||||||
if (core->applicator)
|
|
||||||
{
|
|
||||||
g_object_unref (core->applicator);
|
|
||||||
core->applicator = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (core->stroke_buffer)
|
if (core->stroke_buffer)
|
||||||
{
|
{
|
||||||
g_array_free (core->stroke_buffer, TRUE);
|
g_array_free (core->stroke_buffer, TRUE);
|
||||||
core->stroke_buffer = NULL;
|
core->stroke_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (core->mask_buffer)
|
||||||
|
{
|
||||||
|
g_object_unref (core->mask_buffer);
|
||||||
|
core->mask_buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (core->comp_buffer)
|
||||||
|
{
|
||||||
|
g_object_unref (core->comp_buffer);
|
||||||
|
core->comp_buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
image = gimp_item_get_image (GIMP_ITEM (drawable));
|
||||||
|
|
||||||
/* Determine if any part of the image has been altered--
|
/* Determine if any part of the image has been altered--
|
||||||
@ -737,75 +767,94 @@ gimp_paint_core_get_orig_proj (GimpPaintCore *core)
|
|||||||
|
|
||||||
void
|
void
|
||||||
gimp_paint_core_paste (GimpPaintCore *core,
|
gimp_paint_core_paste (GimpPaintCore *core,
|
||||||
GeglBuffer *paint_mask,
|
const GimpTempBuf *paint_mask,
|
||||||
const GeglRectangle *paint_mask_rect,
|
gint paint_mask_offset_x,
|
||||||
|
gint paint_mask_offset_y,
|
||||||
GimpDrawable *drawable,
|
GimpDrawable *drawable,
|
||||||
gdouble paint_opacity,
|
gdouble paint_opacity,
|
||||||
gdouble image_opacity,
|
gdouble image_opacity,
|
||||||
GimpLayerModeEffects paint_mode,
|
GimpLayerModeEffects paint_mode,
|
||||||
GimpPaintApplicationMode mode)
|
GimpPaintApplicationMode mode)
|
||||||
{
|
{
|
||||||
gint width = gegl_buffer_get_width (core->paint_buffer);
|
GimpTempBuf *paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer);
|
||||||
gint height = gegl_buffer_get_height (core->paint_buffer);
|
GeglBuffer *dest_buffer;
|
||||||
|
GeglBuffer *src_buffer;
|
||||||
|
|
||||||
|
gint width = gimp_temp_buf_get_width (paint_buf);
|
||||||
|
gint height = gimp_temp_buf_get_height (paint_buf);
|
||||||
|
|
||||||
|
if (!paint_buf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (core->comp_buffer)
|
||||||
|
dest_buffer = core->comp_buffer;
|
||||||
|
else
|
||||||
|
dest_buffer = gimp_drawable_get_buffer (drawable);
|
||||||
|
|
||||||
/* If the mode is CONSTANT:
|
|
||||||
* combine the canvas buf, the paint mask to the canvas buffer
|
|
||||||
*/
|
|
||||||
if (mode == GIMP_PAINT_CONSTANT)
|
if (mode == GIMP_PAINT_CONSTANT)
|
||||||
{
|
{
|
||||||
/* Some tools (ink) paint the mask to paint_core->canvas_buffer
|
/* This step is skipped by the ink tool, which writes directly to canvas_buffer */
|
||||||
* directly. Don't need to copy it in this case.
|
if (paint_mask != NULL)
|
||||||
*/
|
|
||||||
if (paint_mask != core->canvas_buffer)
|
|
||||||
{
|
{
|
||||||
gimp_gegl_combine_mask_weird (paint_mask, paint_mask_rect,
|
/* Mix paint mask and canvas_buffer */
|
||||||
core->canvas_buffer,
|
combine_paint_mask_to_canvas_mask (paint_mask,
|
||||||
GEGL_RECTANGLE (core->paint_buffer_x,
|
paint_mask_offset_x,
|
||||||
core->paint_buffer_y,
|
paint_mask_offset_y,
|
||||||
width, height),
|
core->canvas_buffer,
|
||||||
paint_opacity,
|
core->paint_buffer_x,
|
||||||
GIMP_IS_AIRBRUSH (core));
|
core->paint_buffer_y,
|
||||||
|
paint_opacity,
|
||||||
|
GIMP_IS_AIRBRUSH (core));
|
||||||
}
|
}
|
||||||
|
|
||||||
gimp_gegl_apply_mask (core->canvas_buffer,
|
/* Write canvas_buffer to paint_buf */
|
||||||
GEGL_RECTANGLE (core->paint_buffer_x,
|
canvas_buffer_to_paint_buf_alpha (paint_buf,
|
||||||
core->paint_buffer_y,
|
core->canvas_buffer,
|
||||||
width, height),
|
core->paint_buffer_x,
|
||||||
core->paint_buffer,
|
core->paint_buffer_y);
|
||||||
GEGL_RECTANGLE (0, 0, width, height),
|
|
||||||
1.0);
|
|
||||||
|
|
||||||
gimp_applicator_set_src_buffer (core->applicator,
|
/* undo buf -> paint_buf -> dest_buffer */
|
||||||
core->undo_buffer);
|
src_buffer = core->undo_buffer;
|
||||||
}
|
}
|
||||||
/* Otherwise:
|
|
||||||
* combine the canvas buf and the paint mask to the canvas buf
|
|
||||||
*/
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gimp_gegl_apply_mask (paint_mask, paint_mask_rect,
|
g_return_if_fail (paint_mask);
|
||||||
core->paint_buffer,
|
|
||||||
GEGL_RECTANGLE (0, 0, width, height),
|
|
||||||
paint_opacity);
|
|
||||||
|
|
||||||
gimp_applicator_set_src_buffer (core->applicator,
|
/* Write paint_mask to paint_buf, does not modify canvas_buffer */
|
||||||
gimp_drawable_get_buffer (drawable));
|
paint_mask_to_paint_buffer (paint_mask,
|
||||||
|
paint_mask_offset_x,
|
||||||
|
paint_mask_offset_y,
|
||||||
|
paint_buf,
|
||||||
|
paint_opacity);
|
||||||
|
|
||||||
|
/* dest_buffer -> paint_buf -> dest_buffer */
|
||||||
|
src_buffer = dest_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
gimp_applicator_set_apply_buffer (core->applicator,
|
do_layer_blend (src_buffer,
|
||||||
core->paint_buffer);
|
dest_buffer,
|
||||||
gimp_applicator_set_apply_offset (core->applicator,
|
paint_buf,
|
||||||
core->paint_buffer_x,
|
core->mask_buffer,
|
||||||
core->paint_buffer_y);
|
image_opacity,
|
||||||
|
core->paint_buffer_x,
|
||||||
|
core->paint_buffer_y,
|
||||||
|
core->mask_x_offset,
|
||||||
|
core->mask_y_offset,
|
||||||
|
core->linear_mode,
|
||||||
|
paint_mode);
|
||||||
|
|
||||||
gimp_applicator_set_mode (core->applicator,
|
if (core->comp_buffer)
|
||||||
image_opacity, paint_mode);
|
{
|
||||||
|
mask_components_onto (src_buffer,
|
||||||
/* apply the paint area to the image */
|
core->comp_buffer,
|
||||||
gimp_applicator_blit (core->applicator,
|
gimp_drawable_get_buffer (drawable),
|
||||||
GEGL_RECTANGLE (core->paint_buffer_x,
|
GEGL_RECTANGLE(core->paint_buffer_x,
|
||||||
core->paint_buffer_y,
|
core->paint_buffer_y,
|
||||||
width, height));
|
width,
|
||||||
|
height),
|
||||||
|
gimp_drawable_get_active_mask (drawable),
|
||||||
|
core->linear_mode);
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the undo extents */
|
/* Update the undo extents */
|
||||||
core->x1 = MIN (core->x1, core->paint_buffer_x);
|
core->x1 = MIN (core->x1, core->paint_buffer_x);
|
||||||
@ -830,19 +879,23 @@ gimp_paint_core_paste (GimpPaintCore *core,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gimp_paint_core_replace (GimpPaintCore *core,
|
gimp_paint_core_replace (GimpPaintCore *core,
|
||||||
GeglBuffer *paint_mask,
|
const GimpTempBuf *paint_mask,
|
||||||
const GeglRectangle *paint_mask_rect,
|
gint paint_mask_offset_x,
|
||||||
|
gint paint_mask_offset_y,
|
||||||
GimpDrawable *drawable,
|
GimpDrawable *drawable,
|
||||||
gdouble paint_opacity,
|
gdouble paint_opacity,
|
||||||
gdouble image_opacity,
|
gdouble image_opacity,
|
||||||
GimpPaintApplicationMode mode)
|
GimpPaintApplicationMode mode)
|
||||||
{
|
{
|
||||||
GeglRectangle mask_rect;
|
GeglRectangle mask_rect;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
|
GeglBuffer *paint_mask_buffer;
|
||||||
|
|
||||||
if (! gimp_drawable_has_alpha (drawable))
|
if (! gimp_drawable_has_alpha (drawable))
|
||||||
{
|
{
|
||||||
gimp_paint_core_paste (core, paint_mask, paint_mask_rect,
|
gimp_paint_core_paste (core, paint_mask,
|
||||||
|
paint_mask_offset_x,
|
||||||
|
paint_mask_offset_y,
|
||||||
drawable,
|
drawable,
|
||||||
paint_opacity,
|
paint_opacity,
|
||||||
image_opacity, GIMP_NORMAL_MODE,
|
image_opacity, GIMP_NORMAL_MODE,
|
||||||
@ -858,19 +911,22 @@ gimp_paint_core_replace (GimpPaintCore *core,
|
|||||||
/* Some tools (ink) paint the mask to paint_core->canvas_buffer
|
/* Some tools (ink) paint the mask to paint_core->canvas_buffer
|
||||||
* directly. Don't need to copy it in this case.
|
* directly. Don't need to copy it in this case.
|
||||||
*/
|
*/
|
||||||
paint_mask != core->canvas_buffer)
|
(paint_mask != NULL))
|
||||||
{
|
{
|
||||||
/* combine the paint mask and the canvas buffer */
|
/* Mix paint mask and canvas_buffer */
|
||||||
gimp_gegl_combine_mask_weird (paint_mask, paint_mask_rect,
|
combine_paint_mask_to_canvas_mask (paint_mask,
|
||||||
core->canvas_buffer,
|
paint_mask_offset_x,
|
||||||
GEGL_RECTANGLE (core->paint_buffer_x,
|
paint_mask_offset_y,
|
||||||
core->paint_buffer_y,
|
core->canvas_buffer,
|
||||||
width, height),
|
core->paint_buffer_x,
|
||||||
paint_opacity,
|
core->paint_buffer_y,
|
||||||
GIMP_IS_AIRBRUSH (core));
|
paint_opacity,
|
||||||
|
GIMP_IS_AIRBRUSH (core));
|
||||||
|
|
||||||
/* initialize the maskPR from the canvas buffer */
|
/* initialize the maskPR from the canvas buffer */
|
||||||
paint_mask = core->canvas_buffer;
|
paint_mask_buffer = core->canvas_buffer;
|
||||||
|
|
||||||
|
g_object_ref (paint_mask_buffer);
|
||||||
|
|
||||||
mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x,
|
mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x,
|
||||||
core->paint_buffer_y,
|
core->paint_buffer_y,
|
||||||
@ -878,7 +934,11 @@ gimp_paint_core_replace (GimpPaintCore *core,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mask_rect = *paint_mask_rect;
|
paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask);
|
||||||
|
|
||||||
|
mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x,
|
||||||
|
paint_mask_offset_y,
|
||||||
|
width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply the paint area to the image */
|
/* apply the paint area to the image */
|
||||||
@ -886,10 +946,12 @@ gimp_paint_core_replace (GimpPaintCore *core,
|
|||||||
GEGL_RECTANGLE (0, 0, width, height),
|
GEGL_RECTANGLE (0, 0, width, height),
|
||||||
FALSE, NULL,
|
FALSE, NULL,
|
||||||
image_opacity,
|
image_opacity,
|
||||||
paint_mask, &mask_rect,
|
paint_mask_buffer, &mask_rect,
|
||||||
core->paint_buffer_x,
|
core->paint_buffer_x,
|
||||||
core->paint_buffer_y);
|
core->paint_buffer_y);
|
||||||
|
|
||||||
|
g_object_unref (paint_mask_buffer);
|
||||||
|
|
||||||
/* Update the undo extents */
|
/* Update the undo extents */
|
||||||
core->x1 = MIN (core->x1, core->paint_buffer_x);
|
core->x1 = MIN (core->x1, core->paint_buffer_x);
|
||||||
core->y1 = MIN (core->y1, core->paint_buffer_y);
|
core->y1 = MIN (core->y1, core->paint_buffer_y);
|
||||||
|
|||||||
@ -58,14 +58,18 @@ struct _GimpPaintCore
|
|||||||
GeglBuffer *undo_buffer; /* pixels which have been modified */
|
GeglBuffer *undo_buffer; /* pixels which have been modified */
|
||||||
GeglBuffer *saved_proj_buffer; /* proj tiles which have been modified */
|
GeglBuffer *saved_proj_buffer; /* proj tiles which have been modified */
|
||||||
GeglBuffer *canvas_buffer; /* the buffer to paint the mask to */
|
GeglBuffer *canvas_buffer; /* the buffer to paint the mask to */
|
||||||
|
GeglBuffer *comp_buffer; /* scratch buffer used when masking components */
|
||||||
|
gboolean linear_mode; /* if painting to a linear surface */
|
||||||
|
|
||||||
GeglBuffer *paint_buffer; /* the buffer to paint pixels to */
|
GeglBuffer *paint_buffer; /* the buffer to paint pixels to */
|
||||||
gint paint_buffer_x;
|
gint paint_buffer_x;
|
||||||
gint paint_buffer_y;
|
gint paint_buffer_y;
|
||||||
|
|
||||||
GArray *stroke_buffer;
|
GeglBuffer *mask_buffer; /* the target drawable's mask */
|
||||||
|
gint mask_x_offset;
|
||||||
|
gint mask_y_offset;
|
||||||
|
|
||||||
GimpApplicator *applicator;
|
GArray *stroke_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GimpPaintCoreClass
|
struct _GimpPaintCoreClass
|
||||||
@ -168,16 +172,20 @@ GeglBuffer * gimp_paint_core_get_orig_image (GimpPaintCore *core);
|
|||||||
GeglBuffer * gimp_paint_core_get_orig_proj (GimpPaintCore *core);
|
GeglBuffer * gimp_paint_core_get_orig_proj (GimpPaintCore *core);
|
||||||
|
|
||||||
void gimp_paint_core_paste (GimpPaintCore *core,
|
void gimp_paint_core_paste (GimpPaintCore *core,
|
||||||
GeglBuffer *paint_mask,
|
const GimpTempBuf *paint_mask,
|
||||||
const GeglRectangle *paint_mask_rect,
|
gint paint_mask_offset_x,
|
||||||
|
gint paint_mask_offset_y,
|
||||||
GimpDrawable *drawable,
|
GimpDrawable *drawable,
|
||||||
gdouble paint_opacity,
|
gdouble paint_opacity,
|
||||||
gdouble image_opacity,
|
gdouble image_opacity,
|
||||||
GimpLayerModeEffects paint_mode,
|
GimpLayerModeEffects paint_mode,
|
||||||
GimpPaintApplicationMode mode);
|
GimpPaintApplicationMode mode);
|
||||||
|
|
||||||
|
|
||||||
void gimp_paint_core_replace (GimpPaintCore *core,
|
void gimp_paint_core_replace (GimpPaintCore *core,
|
||||||
GeglBuffer *paint_mask,
|
const GimpTempBuf *paint_mask,
|
||||||
const GeglRectangle *paint_mask_rect,
|
gint paint_mask_offset_x,
|
||||||
|
gint paint_mask_offset_y,
|
||||||
GimpDrawable *drawable,
|
GimpDrawable *drawable,
|
||||||
gdouble paint_opacity,
|
gdouble paint_opacity,
|
||||||
gdouble image_opacity,
|
gdouble image_opacity,
|
||||||
|
|||||||
Reference in New Issue
Block a user