static void paint_mask_to_canvas_tiles (GimpPaintCore *core, PixelRegion *paint_maskPR, gdouble paint_opacity) { PixelRegion srcPR; /* combine the paint mask and the canvas tiles */ pixel_region_init (&srcPR, core->canvas_tiles, core->canvas_buf->x, core->canvas_buf->y, core->canvas_buf->width, core->canvas_buf->height, TRUE); /* combine the mask to the canvas tiles */ combine_mask_and_region (&srcPR, paint_maskPR, paint_opacity * 255.999, GIMP_IS_AIRBRUSH (core)); }
/* This works similarly to gimp_paint_core_paste. However, instead of * combining the canvas to the paint core drawable using one of the * combination modes, it uses a "replace" mode (i.e. transparent * pixels in the canvas erase the paint core drawable). * When not drawing on alpha-enabled images, it just paints using * NORMAL mode. */ void gimp_paint_core_replace (GimpPaintCore *core, const GimpTempBuf *paint_mask, gint paint_mask_offset_x, gint paint_mask_offset_y, GimpDrawable *drawable, gdouble paint_opacity, gdouble image_opacity, GimpPaintApplicationMode mode) { GeglRectangle mask_rect; GeglBuffer *paint_mask_buffer; gint width, height; if (! gimp_drawable_has_alpha (drawable)) { gimp_paint_core_paste (core, paint_mask, paint_mask_offset_x, paint_mask_offset_y, drawable, paint_opacity, image_opacity, GIMP_NORMAL_MODE, mode); return; } width = gegl_buffer_get_width (core->paint_buffer); height = gegl_buffer_get_height (core->paint_buffer); if (mode == GIMP_PAINT_CONSTANT && /* Some tools (ink) paint the mask to paint_core->canvas_buffer * directly. Don't need to copy it in this case. */ paint_mask != NULL) { if (core->applicator) { paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); /* combine the paint mask and the canvas buffer */ gimp_gegl_combine_mask_weird (paint_mask_buffer, GEGL_RECTANGLE (paint_mask_offset_x, paint_mask_offset_y, width, height), core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height), paint_opacity, GIMP_IS_AIRBRUSH (core)); g_object_unref (paint_mask_buffer); } else { /* Mix paint mask and canvas_buffer */ combine_paint_mask_to_canvas_mask (paint_mask, paint_mask_offset_x, paint_mask_offset_y, core->canvas_buffer, core->paint_buffer_x, core->paint_buffer_y, paint_opacity, GIMP_IS_AIRBRUSH (core)); } /* initialize the maskPR from the canvas buffer */ paint_mask_buffer = g_object_ref (core->canvas_buffer); mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height); } else { 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 */ gimp_drawable_replace_buffer (drawable, core->paint_buffer, GEGL_RECTANGLE (0, 0, width, height), FALSE, NULL, image_opacity, paint_mask_buffer, &mask_rect, core->paint_buffer_x, core->paint_buffer_y); g_object_unref (paint_mask_buffer); /* Update the undo extents */ core->x1 = MIN (core->x1, core->paint_buffer_x); core->y1 = MIN (core->y1, core->paint_buffer_y); core->x2 = MAX (core->x2, core->paint_buffer_x + width); core->y2 = MAX (core->y2, core->paint_buffer_y + height); /* Update the drawable */ gimp_drawable_update (drawable, core->paint_buffer_x, core->paint_buffer_y, width, height); }
void gimp_paint_core_paste (GimpPaintCore *core, const GimpTempBuf *paint_mask, gint paint_mask_offset_x, gint paint_mask_offset_y, GimpDrawable *drawable, gdouble paint_opacity, gdouble image_opacity, GimpLayerModeEffects paint_mode, GimpPaintApplicationMode mode) { gint width = gegl_buffer_get_width (core->paint_buffer); gint height = gegl_buffer_get_height (core->paint_buffer); if (core->applicator) { /* If the mode is CONSTANT: * combine the canvas buf, the paint mask to the canvas buffer */ if (mode == GIMP_PAINT_CONSTANT) { /* Some tools (ink) paint the mask to paint_core->canvas_buffer * directly. Don't need to copy it in this case. */ if (paint_mask != NULL) { GeglBuffer *paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); gimp_gegl_combine_mask_weird (paint_mask_buffer, GEGL_RECTANGLE (paint_mask_offset_x, paint_mask_offset_y, width, height), core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height), paint_opacity, GIMP_IS_AIRBRUSH (core)); g_object_unref (paint_mask_buffer); } gimp_gegl_apply_mask (core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height), core->paint_buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0); gimp_applicator_set_src_buffer (core->applicator, core->undo_buffer); } /* Otherwise: * combine the canvas buf and the paint mask to the canvas buf */ else { GeglBuffer *paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); gimp_gegl_apply_mask (paint_mask_buffer, GEGL_RECTANGLE (paint_mask_offset_x, paint_mask_offset_y, width, height), core->paint_buffer, GEGL_RECTANGLE (0, 0, width, height), paint_opacity); g_object_unref (paint_mask_buffer); gimp_applicator_set_src_buffer (core->applicator, gimp_drawable_get_buffer (drawable)); } gimp_applicator_set_apply_buffer (core->applicator, core->paint_buffer); gimp_applicator_set_apply_offset (core->applicator, core->paint_buffer_x, core->paint_buffer_y); gimp_applicator_set_mode (core->applicator, image_opacity, paint_mode); /* apply the paint area to the image */ gimp_applicator_blit (core->applicator, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height)); } else { GimpTempBuf *paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer); GeglBuffer *dest_buffer; GeglBuffer *src_buffer; if (! paint_buf) return; if (core->comp_buffer) dest_buffer = core->comp_buffer; else dest_buffer = gimp_drawable_get_buffer (drawable); if (mode == GIMP_PAINT_CONSTANT) { /* This step is skipped by the ink tool, which writes * directly to canvas_buffer */ if (paint_mask != NULL) { /* Mix paint mask and canvas_buffer */ combine_paint_mask_to_canvas_mask (paint_mask, paint_mask_offset_x, paint_mask_offset_y, core->canvas_buffer, core->paint_buffer_x, core->paint_buffer_y, paint_opacity, GIMP_IS_AIRBRUSH (core)); } /* Write canvas_buffer to paint_buf */ canvas_buffer_to_paint_buf_alpha (paint_buf, core->canvas_buffer, core->paint_buffer_x, core->paint_buffer_y); /* undo buf -> paint_buf -> dest_buffer */ src_buffer = core->undo_buffer; } else { g_return_if_fail (paint_mask); /* Write paint_mask to paint_buf, does not modify canvas_buffer */ 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; } do_layer_blend (src_buffer, dest_buffer, paint_buf, core->mask_buffer, image_opacity, core->paint_buffer_x, core->paint_buffer_y, core->mask_x_offset, core->mask_y_offset, core->linear_mode, paint_mode); if (core->comp_buffer) { mask_components_onto (src_buffer, core->comp_buffer, gimp_drawable_get_buffer (drawable), GEGL_RECTANGLE(core->paint_buffer_x, core->paint_buffer_y, width, height), gimp_drawable_get_active_mask (drawable), core->linear_mode); } } /* Update the undo extents */ core->x1 = MIN (core->x1, core->paint_buffer_x); core->y1 = MIN (core->y1, core->paint_buffer_y); core->x2 = MAX (core->x2, core->paint_buffer_x + width); core->y2 = MAX (core->y2, core->paint_buffer_y + height); /* Update the drawable */ gimp_drawable_update (drawable, core->paint_buffer_x, core->paint_buffer_y, width, height); }
void gimp_paint_core_paste (GimpPaintCore *core, GeglBuffer *paint_mask, const GeglRectangle *paint_mask_rect, GimpDrawable *drawable, gdouble paint_opacity, gdouble image_opacity, GimpLayerModeEffects paint_mode, GimpPaintApplicationMode mode) { GeglBuffer *base_buffer = NULL; gint width = gegl_buffer_get_width (core->paint_buffer); gint height = gegl_buffer_get_height (core->paint_buffer); /* If the mode is CONSTANT: * combine the canvas buf, the paint mask to the canvas buffer */ if (mode == GIMP_PAINT_CONSTANT) { /* Some tools (ink) paint the mask to paint_core->canvas_buffer * directly. Don't need to copy it in this case. */ if (paint_mask != core->canvas_buffer) { gimp_gegl_combine_mask_weird (paint_mask, paint_mask_rect, core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height), paint_opacity, GIMP_IS_AIRBRUSH (core)); } gimp_gegl_apply_mask (core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height), core->paint_buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0); base_buffer = core->undo_buffer; } /* Otherwise: * combine the canvas buf and the paint mask to the canvas buf */ else { gimp_gegl_apply_mask (paint_mask, paint_mask_rect, core->paint_buffer, GEGL_RECTANGLE (0, 0, width, height), paint_opacity); base_buffer = gimp_drawable_get_buffer (drawable); } /* apply the paint area to the image */ gimp_applicator_apply (core->applicator, base_buffer, core->paint_buffer, core->paint_buffer_x, core->paint_buffer_y, image_opacity, paint_mode); /* Update the undo extents */ core->x1 = MIN (core->x1, core->paint_buffer_x); core->y1 = MIN (core->y1, core->paint_buffer_y); core->x2 = MAX (core->x2, core->paint_buffer_x + width); core->y2 = MAX (core->y2, core->paint_buffer_y + height); /* Update the drawable */ gimp_drawable_update (drawable, core->paint_buffer_x, core->paint_buffer_y, width, height); }