gimp/app/core/gimpprojection.c

770 lines
24 KiB
C
Raw Normal View History

/* GIMP - The GNU Image Manipulation Program
1997-11-25 06:05:25 +08:00
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software: you can redistribute it and/or modify
1997-11-25 06:05:25 +08:00
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
1997-11-25 06:05:25 +08:00
* (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/>.
1997-11-25 06:05:25 +08:00
*/
app/appenv.h New file. Includes <math.h>. Move G_PI, RINT(), ROUND() etc 1999-09-01 Tor Lillqvist <tml@iki.fi> * app/appenv.h * libgimp/gimpmath.h: New file. Includes <math.h>. Move G_PI, RINT(), ROUND() etc from app/appenv.h here, so plug-ins can use them, too. Remove some commented-out old stuff in appenv.h. * libgimp/gimp.h: Include gimpmath.h. * libgimp/gimp.c (gimp_main): Win32: Don't install signal handlers, we can't do anything useful in the handler ourselves anyway (it would be nice to print out a backtrace, but that seems pretty hard to do, even if not impossible). Let Windows inform the user about the crash. If the plug-in was compiled with MSVC, and the user also has it, she is offered a chance to start the debugger automatically anyway. * app/*several*.c: Include gimpmath.h for G_PI etc. Don't include <math.h>, as gimpmath.h includes it. * plug-ins/*/*many*.c: Include config.h. Don't include <math.h>. Remove all the duplicated definitions of G_PI and rint(). Use RINT() instead of rint(). * app/app_procs.[ch]: app_exit() takes a gboolean. * app/batch.c * app/commands.c * app/interface.c: Call app_exit() with FALSE or TRUE. * app/main.c (on_error): Call gimp_fatal_error. (main): Don't install any signal handler on Win32 here, either. * app/errors.c (gimp_fatal_error, gimp_terminate): Win32: Format the message and call MessageBox with it. g_on_error_query doesn't do anything useful on Win32, and printf'ing a message to stdout or stderr doesn't do anything, either, in a windowing application.
1999-09-02 04:30:56 +08:00
#include "config.h"
Cleanup weekend... 2001-10-29 Michael Natterer <mitch@gimp.org> Cleanup weekend... * app/app_procs.c: pass "no_interface" to gimp_new(). * app/core/gimp.[ch]: added "gboolean no_interface" and the load_procs and save_procs GSLists. * app/core/gimptoolinfo.[ch]: added a "Gimp" pointer to the GimpToolInfo object so more functions find their context without accessing the global "the_gimp" variable. * app/display/display-types.h: removed the GDisplay -> GimpDisplay typedef. * app/display/gimpdisplay.c: look at gimp->no_interface, don't include "appenv.h". * app/file/file-open.[ch] * app/file/file-save.[ch]: don't use "the_gimp" any more. Instead, pass around lots of "Gimp" pointers. Removed the global load_procs and save_procs variables here. Use access() to find out whether a file is readable/writable, removed the manual voodoo and it's Win32 wrappers. Added an optional (can be NULL) "PlunInProcDef" parameter to file_save(), removed file_save_with_proc(). * app/gui/menus.c: Use the unused "gpointer data" parameter of the GtkItemFactory callbacks to pass a "Gimp" pointer to all of them. This reduces the usage of the global "the_gimp" hack to zero in app/gui/... yeah. * app/gui/channels-commands.c * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/image-commands.c * app/gui/layers-commands.c * app/gui/palettes-commands.c * app/gui/select-commands.c * app/gui/test-commands.c * app/gui/tools-commands.c * app/gui/view-commands.c: use the passed "Gimp" pointer. * app/gui/color-area.[ch] * app/gui/convert-dialog.c * app/gui/dialogs-constructors.c * app/gui/file-new-dialog.[ch] * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.[ch] * app/gui/gui.c * app/gui/info-window.[ch] * app/gui/module-browser.[ch] * app/gui/palette-editor.c * app/gui/palette-import-dialog.[ch] * app/gui/paths-dialog.c * app/gui/preferences-dialog.[ch] * app/gui/resize-dialog.[ch] * app/gui/tool-options-dialog.[ch] * app/gui/toolbox.c: pass around lots more "Gimp" and "GimpContext" pointers and don't use "the_gimp" any more. * app/tools/gimptool.h: added a pointer to the corresponding GimpToolInfo object (which in turn has a pointer to a Gimp). * app/tools/tool_manager.[ch]: set the pointer after creating the tool object. Removed tool_manager_get_info_by_tool() as there is a tool->tool_info pointer now. * app/tools/gimpbezierselecttool.c * app/tools/gimpblendtool.c * app/tools/gimpbrightnesscontrasttool.c * app/tools/gimpclonetool.c * app/tools/gimpcolorbalancetool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpconvolvetool.c * app/tools/gimpcroptool.c * app/tools/gimpcurvestool.c * app/tools/gimpdodgeburntool.c * app/tools/gimpdrawtool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpellipseselecttool.c * app/tools/gimperasertool.c * app/tools/gimpfliptool.c * app/tools/gimphistogramtool.c * app/tools/gimphuesaturationtool.c * app/tools/gimpinktool.c * app/tools/gimplevelstool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimppainttool.c * app/tools/gimppathtool.c * app/tools/gimpperspectivetool.c * app/tools/gimpposterizetool.c * app/tools/gimprectselecttool.c * app/tools/gimprotatetool.c * app/tools/gimpscaletool.c * app/tools/gimpsheartool.c * app/tools/gimptexttool.c * app/tools/gimpthresholdtool.c * app/tools/path_tool.c * app/tools/xinput_airbrush.c: s/GDisplay/GimpDisplay/g. Use tool->tool_info and tool_info->gimp in some places to get rid of using "the_gimp". Removing the remaining ones involves changing the tool options system and is scheduled next... * app/widgets/gimpdnd.c * app/widgets/gimpdocumentview.c: pass a "Gimp" pointer to all file_open_*() functions. * app/gdisplay_color.[ch] * app/gdisplay_color_ui.[ch] * app/image_map.[ch] * app/nav_window.[ch] * app/path.c * app/path_bezier.c * app/path_transform.h * app/qmask.[ch]: s/GDisplay/GimpDisplay/g * tools/pdbgen/pdb/fileops.pdb: load_procs and save_procs are members of the "Gimp" object now. * tools/pdbgen/pdb/plug_in.pdb: use gimp->no_interface, don't include "appenv.h". * app/pdb/fileops_cmds.c * app/pdb/plug_in_cmds.c: regenerated.
2001-10-29 19:47:11 +08:00
#include <cairo.h>
#include <gegl.h>
2004-07-14 00:36:29 +08:00
#include "core-types.h"
devel-docs/Makefile.am new file documenting the core's include policy. 2002-05-03 Michael Natterer <mitch@gimp.org> * devel-docs/Makefile.am * devel-docs/includes.txt: new file documenting the core's include policy. * HACKING: mention it here. * libgimptool/gimptooltypes.h: removed GimpToolOptions here. * app/core/core-types.h: and added it here. This is a temp hack needed because GimpToolInfo needs to know the GimpToolOptions type. * libgimpproxy/gimpproxytypes.h: regenerated. * libgimptool/gimptoolmodule.h: don't include gimptooltypes.h here... * libgimptool/gimptoolmodule.c: ...but here. * app/config/gimpconfig-params.c: include "libgimpbase/gimpbase.h" entirely, not single files from it. * app/core/gimp.c * app/core/gimpcontext.c * app/core/gimpcoreconfig.c * app/core/gimpdatafactory.c * app/core/gimpdocuments.c * app/core/gimpdrawable-blend.c * app/core/gimpdrawable-bucket-fill.c * app/core/gimpdrawable-offset.c * app/core/gimpdrawable-transform.c * app/core/gimpdrawable.c * app/core/gimpedit.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-guides.c * app/core/gimpimage-mask.c * app/core/gimpimage-merge.c * app/core/gimpimage-new.c * app/core/gimpimage-projection.c * app/core/gimpimage-qmask.c * app/core/gimpimage-resize.c * app/core/gimpimage-scale.c * app/core/gimpimage.c * app/core/gimpitem.c * app/core/gimpmodules.c * app/core/gimppaintinfo.c * app/core/gimpparasite.c * app/core/gimppreviewcache.c * app/core/gimptoolinfo.c * app/core/gimpunit.c: include "core-types.h" and no other types file. * app/display/gimpdisplay.c * app/display/gimpdisplayshell-callbacks.c * app/display/gimpdisplayshell.c: include "tools/tools-types.h" instead of "libgimptool/gimptooltypes.h", warn about inclusion on "gui/gui-types.h" * app/file/file-open.c * app/file/file-save.c: don't include "libgimptool/gimptooltypes.h". * app/gui/about-dialog.c * app/gui/brush-select.c * app/gui/brushes-commands.c * app/gui/color-select.c * app/gui/data-commands.c * app/gui/device-status-dialog.c * app/gui/dialogs.c * app/gui/gradients-commands.c * app/gui/help-commands.c * app/gui/info-window.c * app/gui/palettes-commands.c * app/gui/patterns-commands.c * app/gui/resize-dialog.c * app/gui/tips-dialog.c * app/gui/tool-options-dialog.c: include "gui-types.h" and no other types file. * app/paint/gimpairbrush.c * app/paint/gimpclone.c * app/paint/gimpconvolve.c * app/paint/gimpdodgeburn.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/paint/gimppaintcore-stroke.c * app/paint/gimppaintcore.c * app/paint/gimppaintoptions.c * app/paint/gimppencil.c * app/paint/gimpsmudge.c * app/paint/paint.c: include "paint-types.h" and no other types file. * app/pdb/pdb-types.h: don't include "libgimptool/gimptooltypes.h". * app/plug-in/plug-in-progress.c: warn about inclusion of "display/display-types.h" * app/tools/tools-types.h: include "libgimptool/gimptooltypes.h". * app/tools/gimpairbrushtool.c * app/tools/gimpbezierselecttool.c * app/tools/gimpblendtool.c * app/tools/gimpbrightnesscontrasttool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpclonetool.c * app/tools/gimpcolorbalancetool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpconvolvetool.c * app/tools/gimpcroptool.c * app/tools/gimpcurvestool.c * app/tools/gimpdodgeburntool.c * app/tools/gimpdrawtool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpellipseselecttool.c * app/tools/gimperasertool.c * app/tools/gimpfliptool.c * app/tools/gimpfreeselecttool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimphistogramtool.c * app/tools/gimphuesaturationtool.c * app/tools/gimpinktool.c * app/tools/gimplevelstool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimppaintbrushtool.c * app/tools/gimppainttool.c * app/tools/gimppathtool.c * app/tools/gimppenciltool.c * app/tools/gimpperspectivetool.c * app/tools/gimpposterizetool.c * app/tools/gimprectselecttool.c * app/tools/gimprotatetool.c * app/tools/gimpscaletool.c * app/tools/gimpselectiontool.c * app/tools/gimpsheartool.c * app/tools/gimpsmudgetool.c * app/tools/gimptexttool.c * app/tools/gimpthresholdtool.c * app/tools/gimptoolcontrol.c * app/tools/gimptoolcontrol.h * app/tools/gimptransformtool.c * app/tools/gimpvectortool.c * app/tools/tools.c: include "tools-types.h" and no other types file, warn about inclusion of "gui/gui-types.h". * app/widgets/gimpcolorpanel.c * app/widgets/gimptoolbox-color-area.c: warn about inclusion of "gui/gui-types.h". * app/xcf/xcf-load.c * app/xcf/xcf.c: don't include "libgimptool/gimptooltypes.h". Split tool-safe-mode up in two files, one including libgimpproxy, one libgimp. * plug-ins/tools/Makefile.am * plug-ins/tools/tool-safe-mode-plug-in.[ch]: new files including libgimp/ stuff only. * plug-ins/tools/tool-safe-mode.[ch]: include libgimpproxy/ and libgimptool/ but don't include libgimp/ because of conflicting declarations. Unrelated: * app/tools/gimpclonetool.c: create the clone core so we don't crash. * app/gui/file-open-dialog.c: changed the way we create previews so that only out-of-date previews are created on a click in the preview area. Unconditional creation can still be forced by <Ctrl>+click. Changed the tooltip to document this.
2002-05-03 20:45:22 +08:00
#include "gegl/gimp-babl.h"
2012-03-15 04:16:58 +08:00
#include "gegl/gimp-gegl-utils.h"
#include "gegl/gimptilehandlerprojection.h"
2012-03-15 04:16:58 +08:00
2004-07-14 00:36:29 +08:00
#include "gimp.h"
#include "gimp-utils.h"
2004-07-14 00:36:29 +08:00
#include "gimparea.h"
#include "gimpimage.h"
#include "gimpmarshal.h"
#include "gimppickable.h"
#include "gimpprojectable.h"
2004-07-14 00:36:29 +08:00
#include "gimpprojection.h"
#include "gimp-log.h"
/* just a bit less than GDK_PRIORITY_REDRAW */
#define GIMP_PROJECTION_IDLE_PRIORITY (G_PRIORITY_HIGH_IDLE + 20 + 1)
/* chunk size for one iteration of the chunk renderer */
#define GIMP_PROJECTION_CHUNK_WIDTH 256
#define GIMP_PROJECTION_CHUNK_HEIGHT 128
/* how much time, in seconds, do we allow chunk rendering to take */
#define GIMP_PROJECTION_CHUNK_TIME 0.01
added a read-only property for the display's image, so it can be retreived 2002-05-10 Michael Natterer <mitch@gimp.org> * app/display/gimpdisplay.c: added a read-only property for the display's image, so it can be retreived by the core, which treats displays as simple GimpObjects. * app/core/gimpcontext.c: made context->display an object property, not just gpointer. Connect to the "remove" signal of gimp->displays to get notified of disappearing displays. Removed the EEKWrapper and get the display's gimage with g_object_get(). * app/widgets/gimpimagedock.[ch]: added image_dock->display_container and require it being passed in the constructor. Do voodoo things in the "image_changed" and "display_changed" callbacks to ensure that the dock doesn't end up with no display even if the active image has one. Added a style property for the image menu's preview size. * app/gui/dialogs-commands.c (dialogs_menu_update): set the "View as List" and "View as Grid" items insensitive if the other view type doesn't exist. Hide them if the view cannot be classified as "list" or "grid" at all. Also hide the "Preview Size" submenu if it's pointless for the view. * app/gui/dialogs-constructors.c: added a special tab for the navigation dialog. Will propbaby add dockable->stock_id to generalize this kind of tab. Pass gimp->displays to gimp_image_dock_new(). * app/gui/menus.c: reordered the "<Dialogs>" factory entries, added more stock icons, cleanup. * etc/gtkrc_user * themes/Default/gtkrc: document usage of GimpImageDock's "menu_preview_height" property.
2002-05-10 21:09:19 +08:00
enum
{
2004-07-14 00:36:29 +08:00
UPDATE,
LAST_SIGNAL
added a read-only property for the display's image, so it can be retreived 2002-05-10 Michael Natterer <mitch@gimp.org> * app/display/gimpdisplay.c: added a read-only property for the display's image, so it can be retreived by the core, which treats displays as simple GimpObjects. * app/core/gimpcontext.c: made context->display an object property, not just gpointer. Connect to the "remove" signal of gimp->displays to get notified of disappearing displays. Removed the EEKWrapper and get the display's gimage with g_object_get(). * app/widgets/gimpimagedock.[ch]: added image_dock->display_container and require it being passed in the constructor. Do voodoo things in the "image_changed" and "display_changed" callbacks to ensure that the dock doesn't end up with no display even if the active image has one. Added a style property for the image menu's preview size. * app/gui/dialogs-commands.c (dialogs_menu_update): set the "View as List" and "View as Grid" items insensitive if the other view type doesn't exist. Hide them if the view cannot be classified as "list" or "grid" at all. Also hide the "Preview Size" submenu if it's pointless for the view. * app/gui/dialogs-constructors.c: added a special tab for the navigation dialog. Will propbaby add dockable->stock_id to generalize this kind of tab. Pass gimp->displays to gimp_image_dock_new(). * app/gui/menus.c: reordered the "<Dialogs>" factory entries, added more stock icons, cleanup. * etc/gtkrc_user * themes/Default/gtkrc: document usage of GimpImageDock's "menu_preview_height" property.
2002-05-10 21:09:19 +08:00
};
2001-11-01 05:20:09 +08:00
/* local function prototypes */
static void gimp_projection_pickable_iface_init (GimpPickableInterface *iface);
static void gimp_projection_finalize (GObject *object);
static gint64 gimp_projection_get_memsize (GimpObject *object,
gint64 *gui_size);
static void gimp_projection_pickable_flush (GimpPickable *pickable);
static GimpImage * gimp_projection_get_image (GimpPickable *pickable);
static const Babl * gimp_projection_get_format (GimpPickable *pickable);
static GeglBuffer * gimp_projection_get_buffer (GimpPickable *pickable);
static gboolean gimp_projection_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
const Babl *format,
gpointer pixel);
static gdouble gimp_projection_get_opacity_at (GimpPickable *pickable,
gint x,
gint y);
static void gimp_projection_free_buffer (GimpProjection *proj);
static void gimp_projection_add_update_area (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h);
static void gimp_projection_flush_whenever (GimpProjection *proj,
gboolean now);
static void gimp_projection_chunk_render_start (GimpProjection *proj);
static void gimp_projection_chunk_render_stop (GimpProjection *proj);
static gboolean gimp_projection_chunk_render_callback (gpointer data);
static void gimp_projection_chunk_render_init (GimpProjection *proj);
static gboolean gimp_projection_chunk_render_iteration(GimpProjection *proj);
static gboolean gimp_projection_chunk_render_next_area(GimpProjection *proj);
static void gimp_projection_paint_area (GimpProjection *proj,
gboolean now,
gint x,
gint y,
gint w,
gint h);
static void gimp_projection_projectable_invalidate(GimpProjectable *projectable,
gint x,
gint y,
gint w,
gint h,
GimpProjection *proj);
static void gimp_projection_projectable_flush (GimpProjectable *projectable,
gboolean invalidate_preview,
GimpProjection *proj);
static void gimp_projection_projectable_changed (GimpProjectable *projectable,
GimpProjection *proj);
2004-07-14 00:36:29 +08:00
G_DEFINE_TYPE_WITH_CODE (GimpProjection, gimp_projection, GIMP_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
gimp_projection_pickable_iface_init))
#define parent_class gimp_projection_parent_class
static guint projection_signals[LAST_SIGNAL] = { 0 };
static void
2004-07-14 00:36:29 +08:00
gimp_projection_class_init (GimpProjectionClass *klass)
1997-11-25 06:05:25 +08:00
{
2004-07-14 00:36:29 +08:00
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
1997-11-25 06:05:25 +08:00
2004-07-14 00:36:29 +08:00
projection_signals[UPDATE] =
g_signal_new ("update",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpProjectionClass, update),
NULL, NULL,
gimp_marshal_VOID__BOOLEAN_INT_INT_INT_INT,
G_TYPE_NONE, 5,
2004-07-14 00:36:29 +08:00
G_TYPE_BOOLEAN,
G_TYPE_INT,
G_TYPE_INT,
G_TYPE_INT,
G_TYPE_INT);
2004-07-14 00:36:29 +08:00
object_class->finalize = gimp_projection_finalize;
gimp_object_class->get_memsize = gimp_projection_get_memsize;
}
static void
2004-07-14 00:36:29 +08:00
gimp_projection_init (GimpProjection *proj)
{
}
static void
gimp_projection_pickable_iface_init (GimpPickableInterface *iface)
{
iface->flush = gimp_projection_pickable_flush;
iface->get_image = gimp_projection_get_image;
iface->get_format = gimp_projection_get_format;
iface->get_format_with_alpha = gimp_projection_get_format; /* sic */
iface->get_buffer = gimp_projection_get_buffer;
iface->get_pixel_at = gimp_projection_get_pixel_at;
iface->get_opacity_at = gimp_projection_get_opacity_at;
}
added a read-only property for the display's image, so it can be retreived 2002-05-10 Michael Natterer <mitch@gimp.org> * app/display/gimpdisplay.c: added a read-only property for the display's image, so it can be retreived by the core, which treats displays as simple GimpObjects. * app/core/gimpcontext.c: made context->display an object property, not just gpointer. Connect to the "remove" signal of gimp->displays to get notified of disappearing displays. Removed the EEKWrapper and get the display's gimage with g_object_get(). * app/widgets/gimpimagedock.[ch]: added image_dock->display_container and require it being passed in the constructor. Do voodoo things in the "image_changed" and "display_changed" callbacks to ensure that the dock doesn't end up with no display even if the active image has one. Added a style property for the image menu's preview size. * app/gui/dialogs-commands.c (dialogs_menu_update): set the "View as List" and "View as Grid" items insensitive if the other view type doesn't exist. Hide them if the view cannot be classified as "list" or "grid" at all. Also hide the "Preview Size" submenu if it's pointless for the view. * app/gui/dialogs-constructors.c: added a special tab for the navigation dialog. Will propbaby add dockable->stock_id to generalize this kind of tab. Pass gimp->displays to gimp_image_dock_new(). * app/gui/menus.c: reordered the "<Dialogs>" factory entries, added more stock icons, cleanup. * etc/gtkrc_user * themes/Default/gtkrc: document usage of GimpImageDock's "menu_preview_height" property.
2002-05-10 21:09:19 +08:00
static void
2004-07-14 00:36:29 +08:00
gimp_projection_finalize (GObject *object)
added a read-only property for the display's image, so it can be retreived 2002-05-10 Michael Natterer <mitch@gimp.org> * app/display/gimpdisplay.c: added a read-only property for the display's image, so it can be retreived by the core, which treats displays as simple GimpObjects. * app/core/gimpcontext.c: made context->display an object property, not just gpointer. Connect to the "remove" signal of gimp->displays to get notified of disappearing displays. Removed the EEKWrapper and get the display's gimage with g_object_get(). * app/widgets/gimpimagedock.[ch]: added image_dock->display_container and require it being passed in the constructor. Do voodoo things in the "image_changed" and "display_changed" callbacks to ensure that the dock doesn't end up with no display even if the active image has one. Added a style property for the image menu's preview size. * app/gui/dialogs-commands.c (dialogs_menu_update): set the "View as List" and "View as Grid" items insensitive if the other view type doesn't exist. Hide them if the view cannot be classified as "list" or "grid" at all. Also hide the "Preview Size" submenu if it's pointless for the view. * app/gui/dialogs-constructors.c: added a special tab for the navigation dialog. Will propbaby add dockable->stock_id to generalize this kind of tab. Pass gimp->displays to gimp_image_dock_new(). * app/gui/menus.c: reordered the "<Dialogs>" factory entries, added more stock icons, cleanup. * etc/gtkrc_user * themes/Default/gtkrc: document usage of GimpImageDock's "menu_preview_height" property.
2002-05-10 21:09:19 +08:00
{
2004-07-14 00:36:29 +08:00
GimpProjection *proj = GIMP_PROJECTION (object);
if (proj->chunk_render.running)
gimp_projection_chunk_render_stop (proj);
added a read-only property for the display's image, so it can be retreived 2002-05-10 Michael Natterer <mitch@gimp.org> * app/display/gimpdisplay.c: added a read-only property for the display's image, so it can be retreived by the core, which treats displays as simple GimpObjects. * app/core/gimpcontext.c: made context->display an object property, not just gpointer. Connect to the "remove" signal of gimp->displays to get notified of disappearing displays. Removed the EEKWrapper and get the display's gimage with g_object_get(). * app/widgets/gimpimagedock.[ch]: added image_dock->display_container and require it being passed in the constructor. Do voodoo things in the "image_changed" and "display_changed" callbacks to ensure that the dock doesn't end up with no display even if the active image has one. Added a style property for the image menu's preview size. * app/gui/dialogs-commands.c (dialogs_menu_update): set the "View as List" and "View as Grid" items insensitive if the other view type doesn't exist. Hide them if the view cannot be classified as "list" or "grid" at all. Also hide the "Preview Size" submenu if it's pointless for the view. * app/gui/dialogs-constructors.c: added a special tab for the navigation dialog. Will propbaby add dockable->stock_id to generalize this kind of tab. Pass gimp->displays to gimp_image_dock_new(). * app/gui/menus.c: reordered the "<Dialogs>" factory entries, added more stock icons, cleanup. * etc/gtkrc_user * themes/Default/gtkrc: document usage of GimpImageDock's "menu_preview_height" property.
2002-05-10 21:09:19 +08:00
2004-07-14 00:36:29 +08:00
gimp_area_list_free (proj->update_areas);
proj->update_areas = NULL;
gimp_area_list_free (proj->chunk_render.update_areas);
proj->chunk_render.update_areas = NULL;
added a read-only property for the display's image, so it can be retreived 2002-05-10 Michael Natterer <mitch@gimp.org> * app/display/gimpdisplay.c: added a read-only property for the display's image, so it can be retreived by the core, which treats displays as simple GimpObjects. * app/core/gimpcontext.c: made context->display an object property, not just gpointer. Connect to the "remove" signal of gimp->displays to get notified of disappearing displays. Removed the EEKWrapper and get the display's gimage with g_object_get(). * app/widgets/gimpimagedock.[ch]: added image_dock->display_container and require it being passed in the constructor. Do voodoo things in the "image_changed" and "display_changed" callbacks to ensure that the dock doesn't end up with no display even if the active image has one. Added a style property for the image menu's preview size. * app/gui/dialogs-commands.c (dialogs_menu_update): set the "View as List" and "View as Grid" items insensitive if the other view type doesn't exist. Hide them if the view cannot be classified as "list" or "grid" at all. Also hide the "Preview Size" submenu if it's pointless for the view. * app/gui/dialogs-constructors.c: added a special tab for the navigation dialog. Will propbaby add dockable->stock_id to generalize this kind of tab. Pass gimp->displays to gimp_image_dock_new(). * app/gui/menus.c: reordered the "<Dialogs>" factory entries, added more stock icons, cleanup. * etc/gtkrc_user * themes/Default/gtkrc: document usage of GimpImageDock's "menu_preview_height" property.
2002-05-10 21:09:19 +08:00
gimp_projection_free_buffer (proj);
2004-07-14 00:36:29 +08:00
G_OBJECT_CLASS (parent_class)->finalize (object);
added a read-only property for the display's image, so it can be retreived 2002-05-10 Michael Natterer <mitch@gimp.org> * app/display/gimpdisplay.c: added a read-only property for the display's image, so it can be retreived by the core, which treats displays as simple GimpObjects. * app/core/gimpcontext.c: made context->display an object property, not just gpointer. Connect to the "remove" signal of gimp->displays to get notified of disappearing displays. Removed the EEKWrapper and get the display's gimage with g_object_get(). * app/widgets/gimpimagedock.[ch]: added image_dock->display_container and require it being passed in the constructor. Do voodoo things in the "image_changed" and "display_changed" callbacks to ensure that the dock doesn't end up with no display even if the active image has one. Added a style property for the image menu's preview size. * app/gui/dialogs-commands.c (dialogs_menu_update): set the "View as List" and "View as Grid" items insensitive if the other view type doesn't exist. Hide them if the view cannot be classified as "list" or "grid" at all. Also hide the "Preview Size" submenu if it's pointless for the view. * app/gui/dialogs-constructors.c: added a special tab for the navigation dialog. Will propbaby add dockable->stock_id to generalize this kind of tab. Pass gimp->displays to gimp_image_dock_new(). * app/gui/menus.c: reordered the "<Dialogs>" factory entries, added more stock icons, cleanup. * etc/gtkrc_user * themes/Default/gtkrc: document usage of GimpImageDock's "menu_preview_height" property.
2002-05-10 21:09:19 +08:00
}
2004-07-14 00:36:29 +08:00
static gint64
gimp_projection_get_memsize (GimpObject *object,
gint64 *gui_size)
{
2004-07-14 00:36:29 +08:00
GimpProjection *projection = GIMP_PROJECTION (object);
gint64 memsize = 0;
memsize += gimp_gegl_buffer_get_memsize (projection->buffer);
Cleanup weekend... 2001-10-29 Michael Natterer <mitch@gimp.org> Cleanup weekend... * app/app_procs.c: pass "no_interface" to gimp_new(). * app/core/gimp.[ch]: added "gboolean no_interface" and the load_procs and save_procs GSLists. * app/core/gimptoolinfo.[ch]: added a "Gimp" pointer to the GimpToolInfo object so more functions find their context without accessing the global "the_gimp" variable. * app/display/display-types.h: removed the GDisplay -> GimpDisplay typedef. * app/display/gimpdisplay.c: look at gimp->no_interface, don't include "appenv.h". * app/file/file-open.[ch] * app/file/file-save.[ch]: don't use "the_gimp" any more. Instead, pass around lots of "Gimp" pointers. Removed the global load_procs and save_procs variables here. Use access() to find out whether a file is readable/writable, removed the manual voodoo and it's Win32 wrappers. Added an optional (can be NULL) "PlunInProcDef" parameter to file_save(), removed file_save_with_proc(). * app/gui/menus.c: Use the unused "gpointer data" parameter of the GtkItemFactory callbacks to pass a "Gimp" pointer to all of them. This reduces the usage of the global "the_gimp" hack to zero in app/gui/... yeah. * app/gui/channels-commands.c * app/gui/edit-commands.c * app/gui/file-commands.c * app/gui/image-commands.c * app/gui/layers-commands.c * app/gui/palettes-commands.c * app/gui/select-commands.c * app/gui/test-commands.c * app/gui/tools-commands.c * app/gui/view-commands.c: use the passed "Gimp" pointer. * app/gui/color-area.[ch] * app/gui/convert-dialog.c * app/gui/dialogs-constructors.c * app/gui/file-new-dialog.[ch] * app/gui/file-open-dialog.[ch] * app/gui/file-save-dialog.[ch] * app/gui/gui.c * app/gui/info-window.[ch] * app/gui/module-browser.[ch] * app/gui/palette-editor.c * app/gui/palette-import-dialog.[ch] * app/gui/paths-dialog.c * app/gui/preferences-dialog.[ch] * app/gui/resize-dialog.[ch] * app/gui/tool-options-dialog.[ch] * app/gui/toolbox.c: pass around lots more "Gimp" and "GimpContext" pointers and don't use "the_gimp" any more. * app/tools/gimptool.h: added a pointer to the corresponding GimpToolInfo object (which in turn has a pointer to a Gimp). * app/tools/tool_manager.[ch]: set the pointer after creating the tool object. Removed tool_manager_get_info_by_tool() as there is a tool->tool_info pointer now. * app/tools/gimpbezierselecttool.c * app/tools/gimpblendtool.c * app/tools/gimpbrightnesscontrasttool.c * app/tools/gimpclonetool.c * app/tools/gimpcolorbalancetool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpconvolvetool.c * app/tools/gimpcroptool.c * app/tools/gimpcurvestool.c * app/tools/gimpdodgeburntool.c * app/tools/gimpdrawtool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpellipseselecttool.c * app/tools/gimperasertool.c * app/tools/gimpfliptool.c * app/tools/gimphistogramtool.c * app/tools/gimphuesaturationtool.c * app/tools/gimpinktool.c * app/tools/gimplevelstool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimppainttool.c * app/tools/gimppathtool.c * app/tools/gimpperspectivetool.c * app/tools/gimpposterizetool.c * app/tools/gimprectselecttool.c * app/tools/gimprotatetool.c * app/tools/gimpscaletool.c * app/tools/gimpsheartool.c * app/tools/gimptexttool.c * app/tools/gimpthresholdtool.c * app/tools/path_tool.c * app/tools/xinput_airbrush.c: s/GDisplay/GimpDisplay/g. Use tool->tool_info and tool_info->gimp in some places to get rid of using "the_gimp". Removing the remaining ones involves changing the tool options system and is scheduled next... * app/widgets/gimpdnd.c * app/widgets/gimpdocumentview.c: pass a "Gimp" pointer to all file_open_*() functions. * app/gdisplay_color.[ch] * app/gdisplay_color_ui.[ch] * app/image_map.[ch] * app/nav_window.[ch] * app/path.c * app/path_bezier.c * app/path_transform.h * app/qmask.[ch]: s/GDisplay/GimpDisplay/g * tools/pdbgen/pdb/fileops.pdb: load_procs and save_procs are members of the "Gimp" object now. * tools/pdbgen/pdb/plug_in.pdb: use gimp->no_interface, don't include "appenv.h". * app/pdb/fileops_cmds.c * app/pdb/plug_in_cmds.c: regenerated.
2001-10-29 19:47:11 +08:00
2004-07-14 00:36:29 +08:00
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
gui_size);
}
/**
* gimp_projection_estimate_memsize:
* @type: the projectable's base type
* @precision: the projectable's precision
* @width: projection width
* @height: projection height
*
* Calculates a rough estimate of the memory that is required for the
* projection of an image with the given @width and @height.
*
* Return value: a rough estimate of the memory requirements.
**/
gint64
gimp_projection_estimate_memsize (GimpImageBaseType type,
GimpPrecision precision,
gint width,
gint height)
{
const Babl *format;
gint64 bytes;
if (type == GIMP_INDEXED)
type = GIMP_RGB;
format = gimp_babl_format (type, precision, TRUE);
bytes = babl_format_get_bytes_per_pixel (format);
/* The pyramid levels constitute a geometric sum with a ratio of 1/4. */
return bytes * (gint64) width * (gint64) height * 1.33;
}
static void
gimp_projection_pickable_flush (GimpPickable *pickable)
{
GimpProjection *proj = GIMP_PROJECTION (pickable);
/* create the buffer if it doesn't exist */
gimp_projection_get_buffer (pickable);
gimp_projection_finish_draw (proj);
gimp_projection_flush_now (proj);
if (proj->invalidate_preview)
{
/* invalidate the preview here since it is constructed from
* the projection
*/
proj->invalidate_preview = FALSE;
gimp_projectable_invalidate_preview (proj->projectable);
}
}
static GimpImage *
gimp_projection_get_image (GimpPickable *pickable)
{
GimpProjection *proj = GIMP_PROJECTION (pickable);
return gimp_projectable_get_image (proj->projectable);
}
static const Babl *
gimp_projection_get_format (GimpPickable *pickable)
{
GimpProjection *proj = GIMP_PROJECTION (pickable);
return gimp_projectable_get_format (proj->projectable);
}
static GeglBuffer *
gimp_projection_get_buffer (GimpPickable *pickable)
{
GimpProjection *proj = GIMP_PROJECTION (pickable);
if (! proj->buffer)
{
GeglNode *graph;
const Babl *format;
gint width;
gint height;
graph = gimp_projectable_get_graph (proj->projectable);
format = gimp_projection_get_format (GIMP_PICKABLE (proj));
gimp_projectable_get_size (proj->projectable, &width, &height);
proj->buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height),
format);
proj->validate_handler = gimp_tile_handler_projection_new (graph,
width, height);
gegl_buffer_add_handler (proj->buffer, proj->validate_handler);
/* This used to call gimp_tile_handler_projection_invalidate()
* which forced the entire projection to be constructed in one
* go for new images, causing a potentially huge delay. Now we
* initially validate stuff the normal way, which makes the
* image appear incrementally, but it keeps everything
* responsive.
*/
gimp_projection_add_update_area (proj, 0, 0, width, height);
proj->invalidate_preview = TRUE;
gimp_projection_flush (proj);
}
return proj->buffer;
}
static gboolean
gimp_projection_get_pixel_at (GimpPickable *pickable,
gint x,
gint y,
const Babl *format,
gpointer pixel)
{
GeglBuffer *buffer = gimp_projection_get_buffer (pickable);
if (x < 0 ||
y < 0 ||
x >= gegl_buffer_get_width (buffer) ||
y >= gegl_buffer_get_height (buffer))
return FALSE;
gegl_buffer_sample (buffer, x, y, NULL, pixel, format,
2012-03-26 08:17:24 +08:00
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
return TRUE;
}
static gdouble
gimp_projection_get_opacity_at (GimpPickable *pickable,
gint x,
gint y)
{
return GIMP_OPACITY_OPAQUE;
}
2004-07-14 00:36:29 +08:00
GimpProjection *
gimp_projection_new (GimpProjectable *projectable)
2004-07-14 00:36:29 +08:00
{
GimpProjection *proj;
g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), NULL);
1997-11-25 06:05:25 +08:00
2004-07-14 00:36:29 +08:00
proj = g_object_new (GIMP_TYPE_PROJECTION, NULL);
1997-11-25 06:05:25 +08:00
proj->projectable = projectable;
1997-11-25 06:05:25 +08:00
g_signal_connect_object (projectable, "invalidate",
G_CALLBACK (gimp_projection_projectable_invalidate),
proj, 0);
g_signal_connect_object (projectable, "flush",
G_CALLBACK (gimp_projection_projectable_flush),
2004-07-14 00:36:29 +08:00
proj, 0);
g_signal_connect_object (projectable, "structure-changed",
G_CALLBACK (gimp_projection_projectable_changed),
2004-07-14 00:36:29 +08:00
proj, 0);
2001-11-10 00:54:56 +08:00
2004-07-14 00:36:29 +08:00
return proj;
1997-11-25 06:05:25 +08:00
}
void
2004-07-14 00:36:29 +08:00
gimp_projection_flush (GimpProjection *proj)
{
2004-07-14 00:36:29 +08:00
g_return_if_fail (GIMP_IS_PROJECTION (proj));
/* Construct in chunks */
2004-07-14 00:36:29 +08:00
gimp_projection_flush_whenever (proj, FALSE);
}
void
2004-07-14 00:36:29 +08:00
gimp_projection_flush_now (GimpProjection *proj)
{
2004-07-14 00:36:29 +08:00
g_return_if_fail (GIMP_IS_PROJECTION (proj));
2004-07-14 00:36:29 +08:00
/* Construct NOW */
gimp_projection_flush_whenever (proj, TRUE);
2001-11-01 05:20:09 +08:00
}
void
gimp_projection_finish_draw (GimpProjection *proj)
{
g_return_if_fail (GIMP_IS_PROJECTION (proj));
if (proj->chunk_render.running)
{
gimp_projection_chunk_render_stop (proj);
while (gimp_projection_chunk_render_iteration (proj));
}
}
2004-07-14 00:36:29 +08:00
/* private functions */
static void
gimp_projection_free_buffer (GimpProjection *proj)
{
if (proj->buffer)
{
if (proj->validate_handler)
gegl_buffer_remove_handler (proj->buffer, proj->validate_handler);
g_object_unref (proj->buffer);
proj->buffer = NULL;
}
if (proj->validate_handler)
{
g_object_unref (proj->validate_handler);
proj->validate_handler = NULL;
}
}
static void
gimp_projection_add_update_area (GimpProjection *proj,
gint x,
gint y,
gint w,
gint h)
{
GimpArea *area;
gint off_x, off_y;
gint width, height;
gimp_projectable_get_offset (proj->projectable, &off_x, &off_y);
gimp_projectable_get_size (proj->projectable, &width, &height);
/* subtract the projectable's offsets because the list of update
* areas is in tile-pyramid coordinates, but our external API is
* always in terms of image coordinates.
*/
x -= off_x;
y -= off_y;
area = gimp_area_new (CLAMP (x, 0, width),
CLAMP (y, 0, height),
CLAMP (x + w, 0, width),
CLAMP (y + h, 0, height));
proj->update_areas = gimp_area_list_process (proj->update_areas, area);
}
static void
2004-07-14 00:36:29 +08:00
gimp_projection_flush_whenever (GimpProjection *proj,
gboolean now)
major cleanup. After being finished, I decided that it needs to be 2001-06-18 Michael Natterer <mitch@gimp.org> * app/nav_window.[ch]: major cleanup. After being finished, I decided that it needs to be factored out to a widget (see below), so like 90% of this file will go away soon. * app/apptypes.h: added opaque NavigationDialog typedef. * app/gdisplay.[ch]: Added gdisplay_selection_visibility() which is called from gdisplays_selection_visibility(). Capitalized the SelectionControl enum values. Cleaned up the GDisplay struct and it's initialisation while i was on it. * app/gimage.c: gimage_size_changed_handler(): removed stuff which is now done by GimpImage itself. * app/scale.c * app/scroll.c: also update the navigation popup, not only the dialog. * app/selection.[ch]: major indentation & cleanup attack. Maybe found the "Selection vanishes" bug (the timeout id was assinged to a gint, not a _guint_). * app/undo.c: s/gimp_image_size_changed/gimp_viweable_size_changed/ * app/core/gimpdrawable.c: invalidate the image's preview from our "invalidate_preview" implementation. This means that the image's preview is invalidated way too often currently, which cries for some general freeze/thaw mechanism on the GimpViewable level. (Note that previews are rendered in the idle loop, so this is not really a major performance impact, it's just ugly). * app/core/gimpimage.[ch]: removed the "size_changed" signal... * app/core/gimpviewable.[ch]: ...and added it here. * app/core/gimplayer.c: invalidate_preview(): always chain up, also if it's a floating selection. * app/gui/info-dialog.[ch] * app/gui/info-window.c: minor cleanups. * app/gui/preferences-dialog.c: no need to invalidate the image after we have invalidated all it's layers. * app/core/gimpimage-mask.c * app/gui/commands.c * app/tools/gimpeditselectiontool.c * app/tools/gimpinktool.c * app/tools/gimpmovetool.c * app/tools/gimppainttool.c: capitalized the SelectionCommand enum values. * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpnavigationpreview.[ch]: new widget. * app/widgets/gimppreview.[ch]: added a non-working non-dot-for-dot mode. Added xres/yres params to the gimp_preview_calc_size() helper function. Cache the "size" value which was passed to the simple function variants (gimp_preview_new() and gimp_preview_set_size()) so we can re-calculate the preview's extents on the underlying viewable's "size_changed" signal and on gimp_preview_set_viewable(). * app/widgets/gimpdrawablepreview.c * app/widgets/gimpimagepreview.c: changed accordingly.
2001-06-18 21:10:03 +08:00
{
/* First the updates... */
2004-07-14 00:36:29 +08:00
if (proj->update_areas)
major cleanup. After being finished, I decided that it needs to be 2001-06-18 Michael Natterer <mitch@gimp.org> * app/nav_window.[ch]: major cleanup. After being finished, I decided that it needs to be factored out to a widget (see below), so like 90% of this file will go away soon. * app/apptypes.h: added opaque NavigationDialog typedef. * app/gdisplay.[ch]: Added gdisplay_selection_visibility() which is called from gdisplays_selection_visibility(). Capitalized the SelectionControl enum values. Cleaned up the GDisplay struct and it's initialisation while i was on it. * app/gimage.c: gimage_size_changed_handler(): removed stuff which is now done by GimpImage itself. * app/scale.c * app/scroll.c: also update the navigation popup, not only the dialog. * app/selection.[ch]: major indentation & cleanup attack. Maybe found the "Selection vanishes" bug (the timeout id was assinged to a gint, not a _guint_). * app/undo.c: s/gimp_image_size_changed/gimp_viweable_size_changed/ * app/core/gimpdrawable.c: invalidate the image's preview from our "invalidate_preview" implementation. This means that the image's preview is invalidated way too often currently, which cries for some general freeze/thaw mechanism on the GimpViewable level. (Note that previews are rendered in the idle loop, so this is not really a major performance impact, it's just ugly). * app/core/gimpimage.[ch]: removed the "size_changed" signal... * app/core/gimpviewable.[ch]: ...and added it here. * app/core/gimplayer.c: invalidate_preview(): always chain up, also if it's a floating selection. * app/gui/info-dialog.[ch] * app/gui/info-window.c: minor cleanups. * app/gui/preferences-dialog.c: no need to invalidate the image after we have invalidated all it's layers. * app/core/gimpimage-mask.c * app/gui/commands.c * app/tools/gimpeditselectiontool.c * app/tools/gimpinktool.c * app/tools/gimpmovetool.c * app/tools/gimppainttool.c: capitalized the SelectionCommand enum values. * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpnavigationpreview.[ch]: new widget. * app/widgets/gimppreview.[ch]: added a non-working non-dot-for-dot mode. Added xres/yres params to the gimp_preview_calc_size() helper function. Cache the "size" value which was passed to the simple function variants (gimp_preview_new() and gimp_preview_set_size()) so we can re-calculate the preview's extents on the underlying viewable's "size_changed" signal and on gimp_preview_set_viewable(). * app/widgets/gimpdrawablepreview.c * app/widgets/gimpimagepreview.c: changed accordingly.
2001-06-18 21:10:03 +08:00
{
if (now) /* Synchronous */
{
GSList *list;
2004-07-14 00:36:29 +08:00
for (list = proj->update_areas; list; list = g_slist_next (list))
{
GimpArea *area = list->data;
if ((area->x1 != area->x2) && (area->y1 != area->y2))
{
2004-07-14 00:36:29 +08:00
gimp_projection_paint_area (proj,
FALSE, /* sic! */
area->x1,
area->y1,
(area->x2 - area->x1),
(area->y2 - area->y1));
}
}
}
else /* Asynchronous */
{
gimp_projection_chunk_render_init (proj);
}
/* Free the update lists */
gimp_area_list_free (proj->update_areas);
proj->update_areas = NULL;
}
else if (! now && proj->invalidate_preview)
{
/* invalidate the preview here since it is constructed from
* the projection
*/
proj->invalidate_preview = FALSE;
gimp_projectable_invalidate_preview (proj->projectable);
}
2004-07-14 00:36:29 +08:00
}
static void
gimp_projection_chunk_render_start (GimpProjection *proj)
{
g_return_if_fail (proj->chunk_render.running == FALSE);
proj->chunk_render_idle_id =
g_idle_add_full (GIMP_PROJECTION_IDLE_PRIORITY,
gimp_projection_chunk_render_callback, proj,
NULL);
proj->chunk_render.running = TRUE;
}
static void
gimp_projection_chunk_render_stop (GimpProjection *proj)
{
g_return_if_fail (proj->chunk_render.running == TRUE);
g_source_remove (proj->chunk_render_idle_id);
proj->chunk_render_idle_id = 0;
proj->chunk_render.running = FALSE;
}
static gboolean
gimp_projection_chunk_render_callback (gpointer data)
{
GimpProjection *proj = data;
GTimer *timer = g_timer_new ();
gint chunks = 0;
gboolean retval = TRUE;
do
{
if (! gimp_projection_chunk_render_iteration (proj))
{
gimp_projection_chunk_render_stop (proj);
retval = FALSE;
break;
}
chunks++;
}
while (g_timer_elapsed (timer, NULL) < GIMP_PROJECTION_CHUNK_TIME);
GIMP_LOG (PROJECTION, "%d chunks in %f seconds\n",
chunks, g_timer_elapsed (timer, NULL));
g_timer_destroy (timer);
return retval;
}
static void
gimp_projection_chunk_render_init (GimpProjection *proj)
{
GSList *list;
/* We need to merge the ChunkRender's and the GimpProjection's
* update_areas list to keep track of which of the updates have been
* flushed and hence need to be drawn.
*/
2004-07-14 00:36:29 +08:00
for (list = proj->update_areas; list; list = g_slist_next (list))
{
GimpArea *area = list->data;
proj->chunk_render.update_areas =
gimp_area_list_process (proj->chunk_render.update_areas,
gimp_area_new (area->x1, area->y1,
area->x2, area->y2));
}
/* If a chunk renderer was already running, merge the remainder of
* its unrendered area with the update_areas list, and make it start
* work on the next unrendered area in the list.
*/
if (proj->chunk_render.running)
{
GimpArea *area =
gimp_area_new (proj->chunk_render.base_x,
proj->chunk_render.y,
proj->chunk_render.base_x + proj->chunk_render.width,
proj->chunk_render.y + (proj->chunk_render.height -
(proj->chunk_render.y -
proj->chunk_render.base_y)));
proj->chunk_render.update_areas =
gimp_area_list_process (proj->chunk_render.update_areas, area);
gimp_projection_chunk_render_next_area (proj);
}
else
{
if (proj->chunk_render.update_areas == NULL)
2004-07-14 00:36:29 +08:00
{
g_warning ("%s: wanted to start chunk render with no update_areas",
G_STRFUNC);
2004-07-14 00:36:29 +08:00
return;
}
gimp_projection_chunk_render_next_area (proj);
2004-07-14 00:36:29 +08:00
gimp_projection_chunk_render_start (proj);
}
}
2004-07-14 00:36:29 +08:00
/* Unless specified otherwise, projection re-rendering is organised by
* ChunkRender, which amalgamates areas to be re-rendered and breaks
* them into bite-sized chunks which are chewed on in an idle
* function. This greatly improves responsiveness for many GIMP
* operations. -- Adam
*/
static gboolean
gimp_projection_chunk_render_iteration (GimpProjection *proj)
{
gint workx = proj->chunk_render.x;
gint worky = proj->chunk_render.y;
gint workw = GIMP_PROJECTION_CHUNK_WIDTH;
gint workh = GIMP_PROJECTION_CHUNK_HEIGHT;
if (workx + workw > proj->chunk_render.base_x + proj->chunk_render.width)
{
workw = proj->chunk_render.base_x + proj->chunk_render.width - workx;
}
if (worky + workh > proj->chunk_render.base_y + proj->chunk_render.height)
{
workh = proj->chunk_render.base_y + proj->chunk_render.height - worky;
}
gimp_projection_paint_area (proj, TRUE /* sic! */,
2004-07-14 00:36:29 +08:00
workx, worky, workw, workh);
proj->chunk_render.x += GIMP_PROJECTION_CHUNK_WIDTH;
if (proj->chunk_render.x >=
proj->chunk_render.base_x + proj->chunk_render.width)
{
proj->chunk_render.x = proj->chunk_render.base_x;
proj->chunk_render.y += GIMP_PROJECTION_CHUNK_HEIGHT;
2004-07-14 00:36:29 +08:00
if (proj->chunk_render.y >=
proj->chunk_render.base_y + proj->chunk_render.height)
2004-07-14 00:36:29 +08:00
{
if (! gimp_projection_chunk_render_next_area (proj))
2004-07-14 00:36:29 +08:00
{
if (proj->invalidate_preview)
{
/* invalidate the preview here since it is constructed from
* the projection
*/
proj->invalidate_preview = FALSE;
gimp_projectable_invalidate_preview (proj->projectable);
}
/* FINISHED */
2004-07-14 00:36:29 +08:00
return FALSE;
}
}
}
/* Still work to do. */
return TRUE;
}
static gboolean
gimp_projection_chunk_render_next_area (GimpProjection *proj)
{
GimpArea *area;
if (! proj->chunk_render.update_areas)
return FALSE;
area = proj->chunk_render.update_areas->data;
proj->chunk_render.update_areas =
g_slist_remove (proj->chunk_render.update_areas, area);
proj->chunk_render.x = proj->chunk_render.base_x = area->x1;
proj->chunk_render.y = proj->chunk_render.base_y = area->y1;
proj->chunk_render.width = area->x2 - area->x1;
proj->chunk_render.height = area->y2 - area->y1;
gimp_area_free (area);
return TRUE;
}
static void
2004-07-14 00:36:29 +08:00
gimp_projection_paint_area (GimpProjection *proj,
gboolean now,
gint x,
gint y,
gint w,
gint h)
{
gint off_x, off_y;
gint width, height;
gint x1, y1, x2, y2;
gimp_projectable_get_offset (proj->projectable, &off_x, &off_y);
gimp_projectable_get_size (proj->projectable, &width, &height);
/* Bounds check */
x1 = CLAMP (x, 0, width);
y1 = CLAMP (y, 0, height);
x2 = CLAMP (x + w, 0, width);
y2 = CLAMP (y + h, 0, height);
if (proj->validate_handler)
gimp_tile_handler_projection_invalidate (proj->validate_handler,
x1, y1, x2 - x1, y2 - y1);
if (now)
{
GeglNode *graph = gimp_projectable_get_graph (proj->projectable);
gegl_node_blit_buffer (graph, proj->buffer,
GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1));
if (proj->validate_handler)
gimp_tile_handler_projection_undo_invalidate (proj->validate_handler,
x1, y1, x2 - x1, y2 - y1);
}
/* add the projectable's offsets because the list of update areas
* is in tile-pyramid coordinates, but our external API is always
* in terms of image coordinates.
*/
2004-07-14 00:36:29 +08:00
g_signal_emit (proj, projection_signals[UPDATE], 0,
now,
x1 + off_x,
y1 + off_y,
x2 - x1,
y2 - y1);
2004-07-14 00:36:29 +08:00
}
2004-07-14 00:36:29 +08:00
/* image callbacks */
static void
gimp_projection_projectable_invalidate (GimpProjectable *projectable,
gint x,
gint y,
gint w,
gint h,
GimpProjection *proj)
2004-07-14 00:36:29 +08:00
{
gimp_projection_add_update_area (proj, x, y, w, h);
major cleanup. After being finished, I decided that it needs to be 2001-06-18 Michael Natterer <mitch@gimp.org> * app/nav_window.[ch]: major cleanup. After being finished, I decided that it needs to be factored out to a widget (see below), so like 90% of this file will go away soon. * app/apptypes.h: added opaque NavigationDialog typedef. * app/gdisplay.[ch]: Added gdisplay_selection_visibility() which is called from gdisplays_selection_visibility(). Capitalized the SelectionControl enum values. Cleaned up the GDisplay struct and it's initialisation while i was on it. * app/gimage.c: gimage_size_changed_handler(): removed stuff which is now done by GimpImage itself. * app/scale.c * app/scroll.c: also update the navigation popup, not only the dialog. * app/selection.[ch]: major indentation & cleanup attack. Maybe found the "Selection vanishes" bug (the timeout id was assinged to a gint, not a _guint_). * app/undo.c: s/gimp_image_size_changed/gimp_viweable_size_changed/ * app/core/gimpdrawable.c: invalidate the image's preview from our "invalidate_preview" implementation. This means that the image's preview is invalidated way too often currently, which cries for some general freeze/thaw mechanism on the GimpViewable level. (Note that previews are rendered in the idle loop, so this is not really a major performance impact, it's just ugly). * app/core/gimpimage.[ch]: removed the "size_changed" signal... * app/core/gimpviewable.[ch]: ...and added it here. * app/core/gimplayer.c: invalidate_preview(): always chain up, also if it's a floating selection. * app/gui/info-dialog.[ch] * app/gui/info-window.c: minor cleanups. * app/gui/preferences-dialog.c: no need to invalidate the image after we have invalidated all it's layers. * app/core/gimpimage-mask.c * app/gui/commands.c * app/tools/gimpeditselectiontool.c * app/tools/gimpinktool.c * app/tools/gimpmovetool.c * app/tools/gimppainttool.c: capitalized the SelectionCommand enum values. * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpnavigationpreview.[ch]: new widget. * app/widgets/gimppreview.[ch]: added a non-working non-dot-for-dot mode. Added xres/yres params to the gimp_preview_calc_size() helper function. Cache the "size" value which was passed to the simple function variants (gimp_preview_new() and gimp_preview_set_size()) so we can re-calculate the preview's extents on the underlying viewable's "size_changed" signal and on gimp_preview_set_viewable(). * app/widgets/gimpdrawablepreview.c * app/widgets/gimpimagepreview.c: changed accordingly.
2001-06-18 21:10:03 +08:00
}
2004-07-14 00:36:29 +08:00
static void
gimp_projection_projectable_flush (GimpProjectable *projectable,
gboolean invalidate_preview,
GimpProjection *proj)
2004-07-14 00:36:29 +08:00
{
if (invalidate_preview)
proj->invalidate_preview = TRUE;
gimp_projection_flush (proj);
2004-07-14 00:36:29 +08:00
}
static void
gimp_projection_projectable_changed (GimpProjectable *projectable,
GimpProjection *proj)
2004-07-14 00:36:29 +08:00
{
gint off_x, off_y;
gint width, height;
if (proj->chunk_render.running)
gimp_projection_chunk_render_stop (proj);
gimp_area_list_free (proj->update_areas);
proj->update_areas = NULL;
gimp_projection_free_buffer (proj);
gimp_projectable_get_offset (proj->projectable, &off_x, &off_y);
gimp_projectable_get_size (projectable, &width, &height);
gimp_projection_add_update_area (proj, off_x, off_y, width, height);
2004-07-14 00:36:29 +08:00
}