diff --git a/ChangeLog b/ChangeLog index 4f252b7c1b..4e63fa38ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,17 @@ +2004-07-29 Sven Neumann + + * libgimpwidgets/gimppreviewarea.c: only invalidate the buffer + on size_allocate; allocate a new one on the next call to + gimp_preview_area_draw(). Fixed buffer offset in expose method. + + * libgimpwidgets/Makefile.am + * libgimpwidgets/test-preview-area.c: more a benchmark than a + test; quite similar to testrgb from the GTK+ source tree. + 2004-07-29 DindinX - * plug-ins/FractalExplorer/Dialogs.c: converted all the GtkPreviews to - GimpPreviewArea. + * plug-ins/FractalExplorer/Dialogs.c: converted all GtkPreview + widgets to GimpPreviewArea. 2004-07-29 Michael Natterer diff --git a/libgimpwidgets/.cvsignore b/libgimpwidgets/.cvsignore index d05c6c3bdf..709b8138f7 100644 --- a/libgimpwidgets/.cvsignore +++ b/libgimpwidgets/.cvsignore @@ -8,3 +8,4 @@ _libs *.la gimpwidgetsmarshal.h gimpwidgetsmarshal.c +test-preview-area diff --git a/libgimpwidgets/Makefile.am b/libgimpwidgets/Makefile.am index b23649bca2..612c524bd9 100644 --- a/libgimpwidgets/Makefile.am +++ b/libgimpwidgets/Makefile.am @@ -214,6 +214,25 @@ $(srcdir)/gimpwidgetsmarshal.c: $(srcdir)/gimpwidgetsmarshal.h && cp xgen-gwmc $(@F) \ && rm -f xgen-gwmc xgen-gwmc~ + +# +# test programs, not to be built by default and never installed +# + +noinst_PROGRAMS = test-preview-area + +test_preview_area_SOURCES = test-preview-area.c + +test_preview_area_DEPENDENCIES = \ + $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la \ + $(top_builddir)/libgimpwidgets/libgimpwidgets-$(GIMP_API_VERSION).la + +test_preview_area_LDADD = \ + $(GTK_LIBS) \ + $(test_preview_area_DEPENDENCIES) + + + install-data-local: install-ms-lib install-libtool-import-lib uninstall-local: uninstall-ms-lib uninstall-libtool-import-lib diff --git a/libgimpwidgets/gimppreviewarea.c b/libgimpwidgets/gimppreviewarea.c index a5611a4efa..2687b7dde1 100644 --- a/libgimpwidgets/gimppreviewarea.c +++ b/libgimpwidgets/gimppreviewarea.c @@ -135,15 +135,16 @@ gimp_preview_area_size_allocate (GtkWidget *widget, if (widget->allocation.width != area->width || widget->allocation.height != area->height) { + if (area->buf) + { + g_free (area->buf); + + area->buf = NULL; + area->rowstride = 0; + } + area->width = widget->allocation.width; area->height = widget->allocation.height; - - area->rowstride = ((area->width * 3) + 3) & ~3; - - if (area->buf) - g_free (area->buf); - - area->buf = g_new (guchar, area->rowstride * area->height); } } @@ -161,7 +162,7 @@ gimp_preview_area_expose (GtkWidget *widget, if (! area->buf || ! GTK_WIDGET_DRAWABLE (widget)) return FALSE; - buf = area->buf + event->area.x + event->area.y * area->rowstride; + buf = area->buf + event->area.x * 3 + event->area.y * area->rowstride; gdk_draw_rgb_image_dithalign (widget->window, widget->style->fg_gc[widget->state], @@ -228,9 +229,6 @@ gimp_preview_area_draw (GimpPreviewArea *area, g_return_if_fail (buf != NULL); g_return_if_fail (rowstride > 0); - if (! area->buf) - return; - if (x + width < 0 || x >= area->width) return; @@ -267,6 +265,12 @@ gimp_preview_area_draw (GimpPreviewArea *area, x = 0; } + if (! area->buf) + { + area->rowstride = ((area->width * 3) + 3) & ~3; + area->buf = g_new (guchar, area->rowstride * area->height); + } + if (x + width > area->width) width = area->width - x; @@ -459,7 +463,7 @@ gimp_preview_area_set_cmap (GimpPreviewArea *area, { g_return_if_fail (GIMP_IS_PREVIEW_AREA (area)); g_return_if_fail (cmap != NULL || num_colors == 0); - g_return_if_fail (num_colors < 0 || num_colors > 256); + g_return_if_fail (num_colors >= 0 && num_colors <= 256); if (num_colors > 0) { diff --git a/libgimpwidgets/test-preview-area.c b/libgimpwidgets/test-preview-area.c new file mode 100644 index 0000000000..8d420a661a --- /dev/null +++ b/libgimpwidgets/test-preview-area.c @@ -0,0 +1,164 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball + * + * Copyright (C) 2004 Sven Neumann + * test-preview-area.c + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* This code is based on testrgb.c from GTK+ - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + */ + +#include + +#include + +#include + +#include "gimpwidgetstypes.h" + +#include "gimppreviewarea.h" + + +#define WIDTH 256 +#define HEIGHT 256 +#define NUM_ITERS 50 + + +static void +test_run (GtkWidget *area) +{ + guchar *buf; + gint i, j; + gint offset; + guchar val; + gdouble start_time, total_time; + GTimer *timer; + GEnumClass *enum_class; + GEnumValue *enum_value; + + gtk_widget_realize (area); + + buf = g_malloc (WIDTH * HEIGHT * 8); + + val = 0; + for (j = 0; j < WIDTH * HEIGHT * 8; j++) + { + val = (val + ((val + (rand () & 0xff)) >> 1)) >> 1; + buf[j] = val; + } + + gimp_preview_area_set_cmap (GIMP_PREVIEW_AREA (area), buf, 256); + + /* Let's warm up the cache, and also wait for the window manager + to settle. */ + for (i = 0; i < NUM_ITERS; i++) + { + offset = (rand () % (WIDTH * HEIGHT * 4)) & -4; + gimp_preview_area_draw (GIMP_PREVIEW_AREA (area), + 0, 0, WIDTH, HEIGHT, + GIMP_RGB_IMAGE, + buf + offset, + WIDTH * 4); + } + + gdk_window_process_all_updates (); + + timer = g_timer_new (); + + enum_class = g_type_class_ref (GIMP_TYPE_IMAGE_TYPE); + + for (enum_value = enum_class->values; enum_value->value_name; enum_value++) + { + start_time = g_timer_elapsed (timer, NULL); + + for (i = 0; i < NUM_ITERS; i++) + { + offset = (rand () % (WIDTH * HEIGHT * 4)) & -4; + gimp_preview_area_draw (GIMP_PREVIEW_AREA (area), + 0, 0, WIDTH, HEIGHT, + enum_value->value, + buf + offset, + WIDTH * 4); + + gdk_window_process_updates (area->window, FALSE); + } + + gdk_flush (); + total_time = g_timer_elapsed (timer, NULL) - start_time; + g_print ("%-16s " + "time elapsed: %5.2fs, %8.1f fps, %8.2f megapixels/s\n", + enum_value->value_name, + total_time, + NUM_ITERS / total_time, + NUM_ITERS * (WIDTH * HEIGHT * 1e-6) / total_time); + } +} + +static void +test_preview_area (void) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *button; + GtkWidget *area; + + window = gtk_widget_new (GTK_TYPE_WINDOW, + "type", GTK_WINDOW_TOPLEVEL, + "title", "test-preview-area", + "allow_shrink", FALSE, + NULL); + + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + vbox = gtk_vbox_new (FALSE, 2); + + area = gimp_preview_area_new (); + + gtk_widget_set_size_request (area, WIDTH, HEIGHT); + gtk_box_pack_start (GTK_BOX (vbox), area, FALSE, FALSE, 0); + gtk_widget_show (area); + + button = gtk_button_new_from_stock (GTK_STOCK_CLOSE); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); + g_signal_connect_swapped (button, "clicked", + G_CALLBACK (gtk_widget_destroy), + window); + + gtk_widget_show (button); + + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_widget_show (vbox); + + gtk_widget_show (window); + + test_run (area); +} + +int +main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + + test_preview_area (); + + gtk_main (); + + return 0; +}