gimp-edit.c 19.2 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * 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 2 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, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
17
 */
Sven Neumann's avatar
Sven Neumann committed
18 19 20

#include "config.h"

Elliot Lee's avatar
Elliot Lee committed
21
#include <stdlib.h>
Sven Neumann's avatar
Sven Neumann committed
22

23
#include <glib-object.h>
24

25
#include "core-types.h"
Sven Neumann's avatar
Sven Neumann committed
26

27
#include "base/pixel-region.h"
28
#include "base/temp-buf.h"
29
#include "base/tile-manager.h"
30
#include "base/tile-manager-crop.h"
31

32 33
#include "paint-funcs/paint-funcs.h"

34
#include "gimp.h"
35
#include "gimp-edit.h"
36
#include "gimp-utils.h"
37 38 39 40
#include "gimpbuffer.h"
#include "gimpchannel.h"
#include "gimpcontext.h"
#include "gimpimage.h"
41
#include "gimpimage-undo.h"
42
#include "gimplayer.h"
43
#include "gimplayer-floating-sel.h"
44
#include "gimplist.h"
45
#include "gimppattern.h"
46
#include "gimppickable.h"
47
#include "gimpselection.h"
48

49
#include "gimp-intl.h"
50

51

52 53
/*  local function protypes  */

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
static GimpBuffer * gimp_edit_extract         (GimpImage            *gimage,
                                               GimpDrawable         *drawable,
                                               GimpContext          *context,
                                               gboolean              cut_pixels);
static GimpBuffer * gimp_edit_extract_visible (GimpImage            *gimage,
                                               GimpContext          *context);
static GimpBuffer * gimp_edit_make_buffer     (Gimp                 *gimp,
                                               TileManager          *tiles,
                                               gboolean              mask_empty);
static gboolean     gimp_edit_fill_internal   (GimpImage            *gimage,
                                               GimpDrawable         *drawable,
                                               GimpContext          *context,
                                               GimpFillType          fill_type,
                                               gdouble               opacity,
                                               GimpLayerModeEffects  paint_mode,
                                               const gchar          *undo_desc);
70 71 72 73


/*  public functions  */

74
const GimpBuffer *
Michael Natterer's avatar
Michael Natterer committed
75
gimp_edit_cut (GimpImage    *gimage,
76 77
	       GimpDrawable *drawable,
               GimpContext  *context)
Elliot Lee's avatar
Elliot Lee committed
78
{
79 80
  GimpBuffer *buffer;

81 82
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
83
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
84
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
Elliot Lee's avatar
Elliot Lee committed
85

86 87 88 89 90 91 92 93 94 95 96
  buffer = gimp_edit_extract (gimage, drawable, context, TRUE);

  if (buffer)
    {
      gimp_set_global_buffer (gimage->gimp, buffer);
      g_object_unref (buffer);

      return gimage->gimp->global_buffer;
    }

  return NULL;
Elliot Lee's avatar
Elliot Lee committed
97 98
}

99
const GimpBuffer *
Michael Natterer's avatar
Michael Natterer committed
100
gimp_edit_copy (GimpImage    *gimage,
101 102
		GimpDrawable *drawable,
                GimpContext  *context)
Elliot Lee's avatar
Elliot Lee committed
103
{
104 105
  GimpBuffer *buffer;

106 107
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
108
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
109
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
Elliot Lee's avatar
Elliot Lee committed
110

111 112 113 114 115 116 117 118 119 120 121
  buffer = gimp_edit_extract (gimage, drawable, context, FALSE);

  if (buffer)
    {
      gimp_set_global_buffer (gimage->gimp, buffer);
      g_object_unref (buffer);

      return gimage->gimp->global_buffer;
    }

  return NULL;
Elliot Lee's avatar
Elliot Lee committed
122 123
}

124 125 126 127
const GimpBuffer *
gimp_edit_copy_visible (GimpImage   *gimage,
                        GimpContext *context)
{
128
  GimpBuffer *buffer;
129 130 131 132

  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);

133
  buffer = gimp_edit_extract_visible (gimage, context);
134

135 136 137 138
  if (buffer)
    {
      gimp_set_global_buffer (gimage->gimp, buffer);
      g_object_unref (buffer);
139

140 141
      return gimage->gimp->global_buffer;
    }
142

143
  return NULL;
144 145
}

146
GimpLayer *
Michael Natterer's avatar
Michael Natterer committed
147 148
gimp_edit_paste (GimpImage    *gimage,
		 GimpDrawable *drawable,
149
		 GimpBuffer   *paste,
150 151 152 153 154
		 gboolean      paste_into,
                 gint          viewport_x,
                 gint          viewport_y,
                 gint          viewport_width,
                 gint          viewport_height)
Elliot Lee's avatar
Elliot Lee committed
155
{
156 157
  GimpLayer     *layer;
  GimpImageType  type;
158 159
  gint           center_x;
  gint           center_y;
160 161 162 163
  gint           offset_x;
  gint           offset_y;
  gint           width;
  gint           height;
164

165
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
166
  g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), NULL);
167
  g_return_val_if_fail (drawable == NULL ||
168
                        gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
169
  g_return_val_if_fail (GIMP_IS_BUFFER (paste), NULL);
170 171 172

  /*  Make a new layer: if drawable == NULL,
   *  user is pasting into an empty image.
173 174
   */

175 176
  if (drawable)
    type = gimp_drawable_type_with_alpha (drawable);
177
  else
178 179
    type = gimp_image_base_type_with_alpha (gimage);

180
  layer = gimp_layer_new_from_tiles (paste->tiles, gimage, type,
181 182 183
                                     _("Pasted Layer"),
                                     GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE);

184 185
  if (! layer)
    return NULL;
Elliot Lee's avatar
Elliot Lee committed
186

187
  if (drawable)
188
    {
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
      /*  if pasting to a drawable  */

      gint     off_x, off_y;
      gint     x1, y1, x2, y2;
      gint     paste_x, paste_y;
      gint     paste_width, paste_height;
      gboolean have_mask;

      gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y);
      have_mask = gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);

      if (! have_mask         &&
          viewport_width  > 0 &&
          viewport_height > 0 &&
          gimp_rectangle_intersect (viewport_x, viewport_y,
                                    viewport_width, viewport_height,
                                    off_x, off_y,
                                    x2 - x1, y2 - y1,
                                    &paste_x, &paste_y,
                                    &paste_width, &paste_height))
        {
          center_x = paste_x + paste_width  / 2;
          center_y = paste_y + paste_height / 2;
        }
      else
        {
          center_x = off_x + (x1 + x2) / 2;
          center_y = off_y + (y1 + y2) / 2;
        }
    }
  else if (viewport_width > 0 && viewport_height > 0)
    {
      /*  if we got a viewport set the offsets to the center of the viewport  */

      center_x = viewport_x + viewport_width  / 2;
      center_y = viewport_y + viewport_height / 2;
225 226 227
    }
  else
    {
228 229 230 231
      /*  otherwise the offsets to the center of the image  */

      center_x = gimage->width  / 2;
      center_y = gimage->height / 2;
232
    }
Elliot Lee's avatar
Elliot Lee committed
233

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
  width  = gimp_item_width  (GIMP_ITEM (layer));
  height = gimp_item_height (GIMP_ITEM (layer));

  offset_x = center_x - width  / 2;
  offset_y = center_y - height / 2;

  /*  Ensure that the pasted layer is always within the image, if it
   *  fits and aligned at top left if it doesn't. (See bug #142944).
   */
  offset_x = MIN (offset_x, gimage->width  - width);
  offset_y = MIN (offset_y, gimage->height - height);
  offset_x = MAX (offset_x, 0);
  offset_y = MAX (offset_y, 0);

  GIMP_ITEM (layer)->offset_x = offset_x;
  GIMP_ITEM (layer)->offset_y = offset_y;
250

251 252 253 254
  /*  Start a group undo  */
  gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_EDIT_PASTE,
                               _("Paste"));

255 256 257 258
  /*  If there is a selection mask clear it--
   *  this might not always be desired, but in general,
   *  it seems like the correct behavior.
   */
259
  if (! gimp_channel_is_empty (gimp_image_get_mask (gimage)) && ! paste_into)
260
    gimp_channel_clear (gimp_image_get_mask (gimage), NULL, TRUE);
Elliot Lee's avatar
Elliot Lee committed
261

262
  /*  if there's a drawable, add a new floating selection  */
263 264
  if (drawable)
    floating_sel_attach (layer, drawable);
265
  else
266
    gimp_image_add_layer (gimage, layer, 0);
267

268
  /*  end the group undo  */
269
  gimp_image_undo_group_end (gimage);
270 271

  return layer;
Elliot Lee's avatar
Elliot Lee committed
272
}
273

274
GimpImage *
275 276 277
gimp_edit_paste_as_new (Gimp       *gimp,
			GimpImage  *invoke,
			GimpBuffer *paste)
278
{
279 280 281
  GimpImage     *gimage;
  GimpLayer     *layer;
  GimpImageType  type;
282

283 284 285 286
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
  g_return_val_if_fail (invoke == NULL || GIMP_IS_IMAGE (invoke), NULL);
  g_return_val_if_fail (GIMP_IS_BUFFER (paste), NULL);

287 288 289 290 291 292 293 294 295 296 297
  switch (tile_manager_bpp (paste->tiles))
    {
    case 1: type = GIMP_GRAY_IMAGE;  break;
    case 2: type = GIMP_GRAYA_IMAGE; break;
    case 3: type = GIMP_RGB_IMAGE;   break;
    case 4: type = GIMP_RGBA_IMAGE;  break;
    default:
      g_return_val_if_reached (NULL);
      break;
    }

298
  /*  create a new image  (always of type GIMP_RGB)  */
299
  gimage = gimp_create_image (gimp,
300 301
			      gimp_buffer_get_width (paste),
                              gimp_buffer_get_height (paste),
302
			      GIMP_IMAGE_TYPE_BASE_TYPE (type),
303
			      TRUE);
304
  gimp_image_undo_disable (gimage);
305 306 307 308 309

  if (invoke)
    {
      gimp_image_set_resolution (gimage,
				 invoke->xresolution, invoke->yresolution);
310 311
      gimp_image_set_unit (gimage,
                           gimp_image_get_unit (invoke));
312
    }
313

314
  layer = gimp_layer_new_from_tiles (paste->tiles, gimage, type,
315
				     _("Pasted Layer"),
316
				     GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE);
317

318
  if (! layer)
319
    {
320 321 322
      g_object_unref (gimage);
      return NULL;
    }
323

324
  gimp_image_add_layer (gimage, layer, 0);
325

326
  gimp_image_undo_enable (gimage);
327

328
  return gimage;
329
}
Elliot Lee's avatar
Elliot Lee committed
330

331 332 333 334 335 336
const gchar *
gimp_edit_named_cut (GimpImage    *gimage,
                     const gchar  *name,
                     GimpDrawable *drawable,
                     GimpContext  *context)
{
337
  GimpBuffer *buffer;
338 339 340 341 342 343 344

  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);

345
  buffer = gimp_edit_extract (gimage, drawable, context, TRUE);
346 347 348

  if (buffer)
    {
349 350 351
      gimp_object_set_name (GIMP_OBJECT (buffer), name);
      gimp_container_add (gimage->gimp->named_buffers, GIMP_OBJECT (buffer));
      g_object_unref (buffer);
352

353
      return gimp_object_get_name (GIMP_OBJECT (buffer));
354 355 356 357 358 359 360 361 362 363 364
    }

  return NULL;
}

const gchar *
gimp_edit_named_copy (GimpImage    *gimage,
                      const gchar  *name,
                      GimpDrawable *drawable,
                      GimpContext  *context)
{
365
  GimpBuffer *buffer;
366 367 368 369 370 371 372

  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);

373
  buffer = gimp_edit_extract (gimage, drawable, context, FALSE);
374 375 376

  if (buffer)
    {
377 378 379
      gimp_object_set_name (GIMP_OBJECT (buffer), name);
      gimp_container_add (gimage->gimp->named_buffers, GIMP_OBJECT (buffer));
      g_object_unref (buffer);
380

381
      return gimp_object_get_name (GIMP_OBJECT (buffer));
382 383 384 385 386 387 388 389 390 391
    }

  return NULL;
}

const gchar *
gimp_edit_named_copy_visible (GimpImage   *gimage,
                              const gchar *name,
                              GimpContext *context)
{
392
  GimpBuffer *buffer;
393 394 395 396 397

  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
  g_return_val_if_fail (name != NULL, NULL);
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);

398
  buffer = gimp_edit_extract_visible (gimage, context);
399 400 401

  if (buffer)
    {
402 403 404
      gimp_object_set_name (GIMP_OBJECT (buffer), name);
      gimp_container_add (gimage->gimp->named_buffers, GIMP_OBJECT (buffer));
      g_object_unref (buffer);
405

406
      return gimp_object_get_name (GIMP_OBJECT (buffer));
407 408 409 410 411
    }

  return NULL;
}

412
gboolean
Michael Natterer's avatar
Michael Natterer committed
413
gimp_edit_clear (GimpImage    *gimage,
414 415
		 GimpDrawable *drawable,
                 GimpContext  *context)
Elliot Lee's avatar
Elliot Lee committed
416
{
417 418
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
419
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
420
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE);
Elliot Lee's avatar
Elliot Lee committed
421

422
  return gimp_edit_fill_internal (gimage, drawable, context,
423
                                  GIMP_TRANSPARENT_FILL,
424
                                  GIMP_OPACITY_OPAQUE, GIMP_ERASE_MODE,
425
                                  _("Clear"));
Elliot Lee's avatar
Elliot Lee committed
426 427
}

428
gboolean
Michael Natterer's avatar
Michael Natterer committed
429 430
gimp_edit_fill (GimpImage    *gimage,
		GimpDrawable *drawable,
431
                GimpContext  *context,
Michael Natterer's avatar
Michael Natterer committed
432
		GimpFillType  fill_type)
Elliot Lee's avatar
Elliot Lee committed
433
{
434
  const gchar *undo_desc;
Elliot Lee's avatar
Elliot Lee committed
435

436 437
  g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE);
  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
438
  g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE);
439
  g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE);
Elliot Lee's avatar
Elliot Lee committed
440

441 442
  switch (fill_type)
    {
443
    case GIMP_FOREGROUND_FILL:
444
      undo_desc = _("Fill with FG Color");
445 446
      break;

447
    case GIMP_BACKGROUND_FILL:
448
      undo_desc = _("Fill with BG Color");
449 450
      break;

451
    case GIMP_WHITE_FILL:
452
      undo_desc = _("Fill with White");
453 454
      break;

455
    case GIMP_TRANSPARENT_FILL:
456
      undo_desc = _("Fill with Transparency");
457 458
      break;

459 460 461 462
    case GIMP_PATTERN_FILL:
      undo_desc = _("Fill with Pattern");
      break;

463
    case GIMP_NO_FILL:
464 465 466
      return TRUE;  /*  nothing to do, but the fill succeded  */

    default:
467
      g_warning ("%s: unknown fill type", G_STRFUNC);
468
      fill_type = GIMP_BACKGROUND_FILL;
469
      undo_desc = _("Fill with BG Color");
470 471 472
      break;
    }

473
  return gimp_edit_fill_internal (gimage, drawable, context,
474 475 476
                                  fill_type,
                                  GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE,
                                  undo_desc);
477 478 479 480 481
}


/*  private functions  */

482
static GimpBuffer *
483 484
gimp_edit_extract (GimpImage    *gimage,
                   GimpDrawable *drawable,
485
                   GimpContext  *context,
486 487 488 489 490 491 492 493 494 495 496 497 498
                   gboolean      cut_pixels)
{
  TileManager *tiles;
  gboolean     empty;

  /*  See if the gimage mask is empty  */
  empty = gimp_channel_is_empty (gimp_image_get_mask (gimage));

  if (cut_pixels)
    gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_EDIT_CUT, _("Cut"));

  /*  Cut/copy the mask portion from the gimage  */
  tiles = gimp_selection_extract (gimp_image_get_mask (gimage),
499
                                  drawable, context, cut_pixels, FALSE, FALSE);
500 501 502 503

  if (cut_pixels)
    gimp_image_undo_group_end (gimage);

504
  return gimp_edit_make_buffer (gimage->gimp, tiles, empty);
505 506
}

507 508 509 510
static GimpBuffer *
gimp_edit_extract_visible (GimpImage   *gimage,
                           GimpContext *context)
{
511 512 513 514 515
  GimpPickable *pickable;
  TileManager  *tiles;
  PixelRegion   srcPR, destPR;
  gboolean      non_empty;
  gint          x1, y1, x2, y2;
516 517 518 519 520 521 522 523 524 525

  non_empty = gimp_channel_bounds (gimp_image_get_mask (gimage),
                                   &x1, &y1, &x2, &y2);
  if ((x1 == x2) || (y1 == y2))
    {
      g_message (_("Unable to cut or copy because the "
		   "selected region is empty."));
      return NULL;
    }

526 527 528 529
  pickable = GIMP_PICKABLE (gimage->projection);

  gimp_pickable_flush (pickable);

530
  tiles = tile_manager_new (x2 - x1, y2 - y1,
531
                            gimp_pickable_get_bytes (pickable));
532 533
  tile_manager_set_offsets (tiles, x1, y1);

534
  pixel_region_init (&srcPR, gimp_pickable_get_tiles (pickable),
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
		     x1, y1,
                     x2 - x1, y2 - y1,
                     FALSE);
  pixel_region_init (&destPR, tiles,
                     0, 0,
                     x2 - x1, y2 - y1,
                     TRUE);

  /*  use EEKy no-COW copying because sharing tiles with the projection
   *  is buggy as hell, probably because tile_invalidate() doesn't
   *  do what it should  --mitch
   */
  copy_region_nocow (&srcPR, &destPR);

  return gimp_edit_make_buffer (gimage->gimp, tiles, ! non_empty);
}

static GimpBuffer *
gimp_edit_make_buffer (Gimp        *gimp,
                       TileManager *tiles,
                       gboolean     mask_empty)
556
{
557
  /*  Only crop if the gimage mask wasn't empty  */
558
  if (tiles && ! mask_empty)
559
    {
560
      TileManager *crop = tile_manager_crop (tiles, 0);
561

562
      if (crop != tiles)
563
        {
564 565
          tile_manager_unref (tiles);
          tiles = crop;
566
        }
567 568 569
    }

  if (tiles)
570
    return gimp_buffer_new (tiles, _("Global Buffer"), FALSE);
571 572 573 574

  return NULL;
}

575
static gboolean
576 577 578 579 580 581 582
gimp_edit_fill_internal (GimpImage            *gimage,
                         GimpDrawable         *drawable,
                         GimpContext          *context,
                         GimpFillType          fill_type,
                         gdouble               opacity,
                         GimpLayerModeEffects  paint_mode,
                         const gchar          *undo_desc)
583 584 585
{
  TileManager *buf_tiles;
  PixelRegion  bufPR;
586
  gint         x, y, width, height;
587
  gint         tiles_bytes;
588
  guchar       col[MAX_CHANNELS];
589 590 591
  TempBuf     *pat_buf = NULL;
  gboolean     new_buf;

592
  if (! gimp_drawable_mask_intersect (drawable, &x, &y, &width, &height))
593 594 595
    return TRUE;  /*  nothing to do, but the fill succeded  */

  tiles_bytes = gimp_drawable_bytes (drawable);
596 597 598 599

  switch (fill_type)
    {
    case GIMP_FOREGROUND_FILL:
600
      gimp_image_get_foreground (gimage, drawable, context, col);
601 602 603 604
      break;

    case GIMP_BACKGROUND_FILL:
    case GIMP_TRANSPARENT_FILL:
605
      gimp_image_get_background (gimage, drawable, context, col);
606 607 608
      break;

    case GIMP_WHITE_FILL:
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
      {
        guchar tmp_col[MAX_CHANNELS];

        tmp_col[RED_PIX]   = 255;
        tmp_col[GREEN_PIX] = 255;
        tmp_col[BLUE_PIX]  = 255;
        gimp_image_transform_color (gimage, drawable, col, GIMP_RGB, tmp_col);
      }
      break;

    case GIMP_PATTERN_FILL:
      {
        GimpPattern *pattern = gimp_context_get_pattern (context);

        pat_buf = gimp_image_transform_temp_buf (gimage, drawable,
                                                 pattern->mask, &new_buf);

        if (! gimp_drawable_has_alpha (drawable) &&
            (pat_buf->bytes == 2 || pat_buf->bytes == 4))
          tiles_bytes++;
      }
630 631 632 633 634 635
      break;

    case GIMP_NO_FILL:
      return TRUE;  /*  nothing to do, but the fill succeded  */
    }

636
  buf_tiles = tile_manager_new (width, height, tiles_bytes);
637

638
  pixel_region_init (&bufPR, buf_tiles, 0, 0, width, height, TRUE);
Elliot Lee's avatar
Elliot Lee committed
639

640 641 642
  if (pat_buf)
    {
      pattern_region (&bufPR, NULL, pat_buf, 0, 0);
643

644 645 646 647 648 649 650
      if (new_buf)
        temp_buf_free (pat_buf);
    }
  else
    {
      if (gimp_drawable_has_alpha (drawable))
        col[gimp_drawable_bytes (drawable) - 1] = OPAQUE_OPACITY;
651

652 653
      color_region (&bufPR, col);
    }
Elliot Lee's avatar
Elliot Lee committed
654

655
  pixel_region_init (&bufPR, buf_tiles, 0, 0, width, height, FALSE);
656 657
  gimp_drawable_apply_region (drawable, &bufPR,
                              TRUE, undo_desc,
658
                              opacity, paint_mode,
659
                              NULL, x, y);
Elliot Lee's avatar
Elliot Lee committed
660

661
  tile_manager_unref (buf_tiles);
Elliot Lee's avatar
Elliot Lee committed
662

663
  gimp_drawable_update (drawable, x, y, width, height);
664

Elliot Lee's avatar
Elliot Lee committed
665 666
  return TRUE;
}