Commit df7ad092 authored by BST 1999 Andy Thomas's avatar BST 1999 Andy Thomas Committed by Andy Thomas

app/nav_window.c app/nav_window.h app/gimppreviewcache.h app/layer.c

Fri Aug 27 18:57:50 BST 1999 Andy Thomas <alt@gimp.org>

	* app/nav_window.c
	* app/nav_window.h
	* app/gimppreviewcache.h
	* app/layer.c
	* app/channel.c
	* app/commands.c

	Added some controls to the nav window. Yep. I know that the
	buttons are toooo biGGG.

	Preview cache changes. Now prime preview cache with a image
	so that later we have a better chance of a hit. Still
	needs to be more intelligent at doing this (needs to pick largest
	out of the cache & use its size as the size to prime with).
parent 73656bee
Fri Aug 27 18:57:50 BST 1999 Andy Thomas <alt@gimp.org>
* app/nav_window.c
* app/nav_window.h
* app/gimppreviewcache.h
* app/layer.c
* app/channel.c
* app/commands.c
Added some controls to the nav window. Yep. I know that the
buttons are toooo biGGG.
Preview cache changes. Now prime preview cache with a image
so that later we have a better chance of a hit. Still
needs to be more intelligent at doing this (needs to pick largest
out of the cache & use its size as the size to prime with).
Fri Aug 27 02:16:02 EDT 1999 Adrian Likins <alikins@redhat.com>
* app/gimpbrushpipe.c: paint_line_pixmap_mask, finally
......
......@@ -546,7 +546,7 @@ view_window_nav_cmd_callback (GtkWidget *widget,
if (! gdisp->window_nav_dialog)
gdisp->window_nav_dialog = nav_window_create ((void *) gdisp);
info_dialog_popup (gdisp->window_nav_dialog);
nav_dialog_popup (gdisp->window_nav_dialog);
}
void
......
......@@ -477,10 +477,10 @@ channel_toggle_visibility (Channel *channel)
return GIMP_DRAWABLE (channel)->visible;
}
TempBuf *
channel_preview (Channel *channel,
gint width,
gint height)
static TempBuf *
channel_preview_private (Channel *channel,
gint width,
gint height)
{
MaskBuf * preview_buf;
PixelRegion srcPR, destPR;
......@@ -530,6 +530,31 @@ channel_preview (Channel *channel,
}
}
TempBuf *
channel_preview (Channel *channel,
gint width,
gint height)
{
/* Ok prime the cache with a large preview if the cache is invalid */
if(!GIMP_DRAWABLE(channel)->preview_valid &&
width <= PREVIEW_CACHE_PRIME_WIDTH &&
height <= PREVIEW_CACHE_PRIME_HEIGHT)
{
TempBuf * tb = channel_preview_private(channel,
PREVIEW_CACHE_PRIME_WIDTH,
PREVIEW_CACHE_PRIME_HEIGHT);
/* Save the 2nd call */
if(width == PREVIEW_CACHE_PRIME_WIDTH &&
height == PREVIEW_CACHE_PRIME_HEIGHT)
return tb;
}
/* Second call - should NOT visit the tile cache...*/
return channel_preview_private(channel,width,height);
}
void
channel_invalidate_previews (GimpImage* gimage)
{
......
......@@ -546,7 +546,7 @@ view_window_nav_cmd_callback (GtkWidget *widget,
if (! gdisp->window_nav_dialog)
gdisp->window_nav_dialog = nav_window_create ((void *) gdisp);
info_dialog_popup (gdisp->window_nav_dialog);
nav_dialog_popup (gdisp->window_nav_dialog);
}
void
......
......@@ -477,10 +477,10 @@ channel_toggle_visibility (Channel *channel)
return GIMP_DRAWABLE (channel)->visible;
}
TempBuf *
channel_preview (Channel *channel,
gint width,
gint height)
static TempBuf *
channel_preview_private (Channel *channel,
gint width,
gint height)
{
MaskBuf * preview_buf;
PixelRegion srcPR, destPR;
......@@ -530,6 +530,31 @@ channel_preview (Channel *channel,
}
}
TempBuf *
channel_preview (Channel *channel,
gint width,
gint height)
{
/* Ok prime the cache with a large preview if the cache is invalid */
if(!GIMP_DRAWABLE(channel)->preview_valid &&
width <= PREVIEW_CACHE_PRIME_WIDTH &&
height <= PREVIEW_CACHE_PRIME_HEIGHT)
{
TempBuf * tb = channel_preview_private(channel,
PREVIEW_CACHE_PRIME_WIDTH,
PREVIEW_CACHE_PRIME_HEIGHT);
/* Save the 2nd call */
if(width == PREVIEW_CACHE_PRIME_WIDTH &&
height == PREVIEW_CACHE_PRIME_HEIGHT)
return tb;
}
/* Second call - should NOT visit the tile cache...*/
return channel_preview_private(channel,width,height);
}
void
channel_invalidate_previews (GimpImage* gimage)
{
......
......@@ -477,10 +477,10 @@ channel_toggle_visibility (Channel *channel)
return GIMP_DRAWABLE (channel)->visible;
}
TempBuf *
channel_preview (Channel *channel,
gint width,
gint height)
static TempBuf *
channel_preview_private (Channel *channel,
gint width,
gint height)
{
MaskBuf * preview_buf;
PixelRegion srcPR, destPR;
......@@ -530,6 +530,31 @@ channel_preview (Channel *channel,
}
}
TempBuf *
channel_preview (Channel *channel,
gint width,
gint height)
{
/* Ok prime the cache with a large preview if the cache is invalid */
if(!GIMP_DRAWABLE(channel)->preview_valid &&
width <= PREVIEW_CACHE_PRIME_WIDTH &&
height <= PREVIEW_CACHE_PRIME_HEIGHT)
{
TempBuf * tb = channel_preview_private(channel,
PREVIEW_CACHE_PRIME_WIDTH,
PREVIEW_CACHE_PRIME_HEIGHT);
/* Save the 2nd call */
if(width == PREVIEW_CACHE_PRIME_WIDTH &&
height == PREVIEW_CACHE_PRIME_HEIGHT)
return tb;
}
/* Second call - should NOT visit the tile cache...*/
return channel_preview_private(channel,width,height);
}
void
channel_invalidate_previews (GimpImage* gimage)
{
......
......@@ -1089,10 +1089,10 @@ layer_linked (Layer *layer)
return layer->linked;
}
TempBuf *
layer_preview (Layer *layer,
gint w,
gint h)
static TempBuf *
layer_preview_private (Layer *layer,
gint w,
gint h)
{
GImage *gimage;
TempBuf *preview_buf;
......@@ -1161,9 +1161,33 @@ layer_preview (Layer *layer,
}
TempBuf *
layer_mask_preview (Layer *layer,
gint w,
gint h)
layer_preview (Layer *layer,
gint w,
gint h)
{
/* Ok prime the cache with a large preview if the cache is invalid */
if(!GIMP_DRAWABLE(layer)->preview_valid &&
w <= PREVIEW_CACHE_PRIME_WIDTH &&
h <= PREVIEW_CACHE_PRIME_HEIGHT)
{
TempBuf * tb = layer_preview_private(layer,
PREVIEW_CACHE_PRIME_WIDTH,
PREVIEW_CACHE_PRIME_HEIGHT);
/* Save the 2nd call */
if(w == PREVIEW_CACHE_PRIME_WIDTH &&
h == PREVIEW_CACHE_PRIME_HEIGHT)
return tb;
}
/* Second call - should NOT visit the tile cache...*/
return layer_preview_private(layer,w,h);
}
static TempBuf *
layer_mask_preview_private (Layer *layer,
gint w,
gint h)
{
TempBuf *preview_buf;
LayerMask *mask;
......@@ -1213,6 +1237,31 @@ layer_mask_preview (Layer *layer,
}
}
TempBuf *
layer_mask_preview (Layer *layer,
gint w,
gint h)
{
/* Ok prime the cache with a large preview if the cache is invalid */
if(!GIMP_DRAWABLE(layer->mask)->preview_valid &&
w <= PREVIEW_CACHE_PRIME_WIDTH &&
h <= PREVIEW_CACHE_PRIME_HEIGHT)
{
TempBuf * tb = layer_mask_preview_private(layer,
PREVIEW_CACHE_PRIME_WIDTH,
PREVIEW_CACHE_PRIME_HEIGHT);
/* Save the 2nd call */
if(w == PREVIEW_CACHE_PRIME_WIDTH &&
h == PREVIEW_CACHE_PRIME_HEIGHT)
return tb;
}
/* Second call - should NOT visit the tile cache...*/
return layer_mask_preview_private(layer,w,h);
}
Tattoo
layer_get_tattoo (const Layer *layer)
{
......
......@@ -34,6 +34,9 @@ typedef struct _PreviewNearest {
} PreviewNearest;
#define MAX_CACHE_PREVIEWS 5
#define PREVIEW_CACHE_PRIME_WIDTH 112
#define PREVIEW_CACHE_PRIME_HEIGHT 112
TempBuf * gimp_preview_cache_get(GSList **,gint,gint);
void gimp_preview_cache_add(GSList **,TempBuf *);
void gimp_preview_cache_invalidate(GSList **);
......
......@@ -34,6 +34,9 @@
#include "libgimp/gimpintl.h"
#include "libgimp/gimpunit.h"
#include "pixmaps/zoom_in.xpm"
#include "pixmaps/zoom_out.xpm"
#define MAX_BUF 256
......@@ -47,6 +50,12 @@
#define NAV_PREVIEW_HEIGHT 112
#define BORDER_PEN_WIDTH 3
#define MAX_SCALE_BUF 20
/* Timeout before preview is updated */
#define PREVIEW_UPDATE_TIMEOUT 1100
typedef struct _NavWinData NavWinData;
struct _NavWinData
{
......@@ -57,6 +66,9 @@ struct _NavWinData
void *gdisp_ptr; /* I'm not happy 'bout this one */
GtkWidget *previewBox;
GtkWidget *previewAlign;
GtkWidget *zoom_label;
GtkWidget *zoom_scale;
GtkObject *zoom_adjustment;
gdouble ratio;
GdkGC *gc;
gint dispx; /* x pos of top left corner of display area */
......@@ -74,6 +86,7 @@ struct _NavWinData
gboolean block_window_marker; /* Block redraws of window marker */
gint nav_preview_width;
gint nav_preview_height;
gboolean block_adj_sig;
};
......@@ -95,7 +108,10 @@ nav_window_preview_resized (GtkWidget *,
#endif /* 0 */
static void
nav_window_update_preview (NavWinData *,gboolean);
nav_window_update_preview (NavWinData *);
static void
nav_window_update_preview_blank(NavWinData *iwd);
static void
destroy_preview_widget (NavWinData *);
......@@ -117,6 +133,10 @@ nav_window_draw_sqr(NavWinData *,
static void
set_size_data(NavWinData *);
static gint
nav_preview_update_do_timer(NavWinData *);
static void
nav_window_destroy_callback (GtkWidget *widget,
gpointer client_data)
......@@ -137,7 +157,7 @@ nav_window_close_callback (GtkWidget *widget,
info_win = (InfoDialog *)client_data;
iwd = (NavWinData *)info_win->user_data;
/* iwd->showingPreview = FALSE; ALT. Needs to be sorted out */
iwd->showingPreview = FALSE;
info_dialog_popdown ((InfoDialog *) client_data);
}
......@@ -177,13 +197,17 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp)
iwd->imageheight = newheight;
/* Normalise */
iwd->dispwidth = MAX(iwd->dispwidth, 2);
iwd->dispheight = MAX(iwd->dispheight, 2);
iwd->dispwidth = MIN(iwd->dispwidth, iwd->pwidth/*-BORDER_PEN_WIDTH*/);
iwd->dispheight = MIN(iwd->dispheight, iwd->pheight/*-BORDER_PEN_WIDTH*/);
if(need_update == TRUE)
{
gtk_widget_hide(iwd->previewAlign);
nav_window_update_preview(iwd,FALSE);
/* ALT nav_window_update_preview(iwd);*/
nav_window_update_preview_blank(iwd);
gtk_widget_show(iwd->preview);
gtk_widget_draw(iwd->preview, NULL);
gtk_widget_show(iwd->previewAlign);
......@@ -191,6 +215,7 @@ nav_window_disp_area(NavWinData *iwd,GDisplay *gdisp)
iwd->dispx,iwd->dispy,
iwd->dispwidth,iwd->dispheight);
gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),iwd->preview);
gtk_timeout_add(PREVIEW_UPDATE_TIMEOUT,(GtkFunction)nav_preview_update_do_timer,(gpointer)iwd);
}
}
......@@ -328,30 +353,6 @@ create_preview_widget(NavWinData *iwd)
GTK_WIDGET_SET_FLAGS (image, GTK_CAN_FOCUS);
}
#if 0
static void
info_window_page_switch (GtkWidget *widget,
GtkNotebookPage *page,
gint page_num)
{
InfoDialog *info_win;
InfoWinData *iwd;
info_win = (InfoDialog *)gtk_object_get_user_data(GTK_OBJECT (widget));
iwd = (InfoWinData *)info_win->user_data;
/* Only deal with the second page */
if(page_num != 1)
{
iwd->showingPreview = FALSE;
return;
}
iwd->showingPreview = TRUE;
}
#endif /* 0 */
static void
update_real_view(NavWinData *iwd,gint tx,gint ty)
{
......@@ -387,10 +388,7 @@ update_real_view(NavWinData *iwd,gint tx,gint ty)
iwd->block_window_marker = FALSE;
}
static void
nav_window_update_preview
(NavWinData *iwd,
gboolean invalidated)
static void nav_window_update_preview(NavWinData *iwd)
{
GDisplay *gdisp;
TempBuf * preview_buf;
......@@ -399,6 +397,8 @@ nav_window_update_preview
gint pwidth, pheight;
GimpImage *gimage;
gdouble r,g,b,a,chk;
gint xoff = 0;
gint yoff = 0;
gimp_add_busy_cursors();
......@@ -406,84 +406,103 @@ nav_window_update_preview
/* Calculate preview size */
gimage = ((GDisplay *)(iwd->gdisp_ptr))->gimage;
/* Min size is 2 */
pwidth = iwd->pwidth;
pheight = iwd->pheight;
preview_buf = gimp_image_construct_composite_preview (gimage,
MAX (pwidth, 2),
MAX (pheight, 2));
buf = g_new (gchar, iwd->nav_preview_width * 3);
src = (gchar *) temp_buf_data (preview_buf);
has_alpha = (preview_buf->bytes == 2 || preview_buf->bytes == 4);
for (y = 0; y <preview_buf->height ; y++)
for (y = 0; y <pheight ; y++)
{
dest = buf;
switch (preview_buf->bytes)
{
case 4:
for (x = 0; x < preview_buf->width; x++)
{
r = ((gdouble)(*(src++)))/255.0;
g = ((gdouble)(*(src++)))/255.0;
b = ((gdouble)(*(src++)))/255.0;
a = ((gdouble)(*(src++)))/255.0;
chk = ((gdouble)((( (x^y) & 4 ) << 4) | 128))/255.0;
if(!invalidated)
for (x = 0; x < pwidth; x++)
{
r = ((gdouble)(*(src++)))/255.0;
g = ((gdouble)(*(src++)))/255.0;
b = ((gdouble)(*(src++)))/255.0;
a = ((gdouble)(*(src++)))/255.0;
chk = ((gdouble)((( (x^y) & 4 ) << 4) | 128))/255.0;
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
*(dest++) = (guchar)((chk + (g - chk)*a)*255.0);
*(dest++) = (guchar)((chk + (b - chk)*a)*255.0);
}
else
{
chk *= 128.0;
*(dest++) = (guchar)chk;
*(dest++) = (guchar)chk;
*(dest++) = (guchar)chk;
}
}
break;
break;
case 2:
for (x = 0; x < preview_buf->width; x++)
for (x = 0; x < pwidth; x++)
{
r = ((gdouble)(*(src++)))/255.0;
a = ((gdouble)(*(src++)))/255.0;
r = ((gdouble)(*(src++)))/255.0;
a = ((gdouble)(*(src++)))/255.0;
chk = ((gdouble)((( (x^y) & 4 ) << 4) | 128))/255.0;
if(!invalidated)
{
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
}
else
{
chk *= 255.0;
*(dest++) = (guchar)chk;
*(dest++) = (guchar)chk;
*(dest++) = (guchar)chk;
}
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
}
break;
default:
g_warning("UNKNOWN TempBuf bpp in nav_window_update_preview()");
}
gtk_preview_draw_row (GTK_PREVIEW (iwd->preview),
(guchar *)buf, 0, y, preview_buf->width);
(guchar *)buf, xoff, yoff+y, preview_buf->width);
}
g_free (buf);
temp_buf_free (preview_buf);
nav_window_disp_area(iwd,gdisp);
/* nav_window_disp_area(iwd,gdisp); */
gimp_remove_busy_cursors (NULL);
}
static void nav_window_update_preview_blank(NavWinData *iwd)
{
GDisplay *gdisp;
guchar *buf, *dest;
gint x,y;
GimpImage *gimage;
gdouble chk;
gdisp = (GDisplay *) iwd->gdisp_ptr;
/* Calculate preview size */
gimage = ((GDisplay *)(iwd->gdisp_ptr))->gimage;
buf = g_new (gchar, iwd->pwidth * 3);
for (y = 0; y < iwd->pheight ; y++)
{
dest = buf;
for (x = 0; x < iwd->pwidth; x++)
{
chk = ((gdouble)((( (x^y) & 4 ) << 4) | 128))/255.0;
chk *= 128.0;
*(dest++) = (guchar)chk;
*(dest++) = (guchar)chk;
*(dest++) = (guchar)chk;
}
gtk_preview_draw_row (GTK_PREVIEW (iwd->preview),
(guchar *)buf, 0, y, iwd->pwidth);
}
g_free (buf);
gdk_flush();
/* nav_window_disp_area(iwd,gdisp);*/
}
static gint
inside_preview_square(NavWinData *iwd, gint x, gint y)
{
......@@ -496,55 +515,42 @@ inside_preview_square(NavWinData *iwd, gint x, gint y)
return FALSE;
}
#if 0
static gint
nav_window_preview_resized (GtkWidget *widget,
GtkAllocation *alloc,
gpointer *data)
static void
update_zoom_label(NavWinData *iwd)
{
NavWinData *iwd;
iwd = (NavWinData *)data;
if(!iwd || !iwd->preview)
return FALSE;
printf("Now at [x,y] = [%d,%d] [w,h] = [%d,%d]\n",
alloc->x,alloc->y,
alloc->width,alloc->height);
if(iwd->nav_preview_width == alloc->width &&
iwd->nav_preview_height == alloc->height)
return FALSE;
iwd->nav_preview_width = alloc->width;
iwd->nav_preview_height = alloc->height;
set_size_data(iwd);
gtk_preview_size(GTK_PREVIEW(iwd->preview),alloc->width,alloc->height);
nav_window_update_preview(iwd,FALSE);
nav_window_draw_sqr(iwd,FALSE,
iwd->dispx,iwd->dispy,
iwd->dispwidth,iwd->dispheight);
#if 0
destroy_preview_widget(iwd);
create_preview_widget(iwd);
nav_window_update_preview(iwd,FALSE);
gchar scale_str[MAX_SCALE_BUF];
/* Update the zoom scale string */
g_snprintf (scale_str, MAX_SCALE_BUF, "%d:%d",
SCALEDEST (((GDisplay *)iwd->gdisp_ptr)),
SCALESRC (((GDisplay *)iwd->gdisp_ptr)));
gtk_label_set_text(GTK_LABEL(iwd->zoom_label),scale_str);
}
nav_window_update_preview(iwd,FALSE);
gtk_widget_show(iwd->preview);
gtk_widget_draw(iwd->preview, NULL);
gtk_widget_show(iwd->previewAlign);
nav_window_draw_sqr(iwd,FALSE,
iwd->dispx,iwd->dispy,
iwd->dispwidth,iwd->dispheight);
static void
update_zoom_adjustment(NavWinData *iwd)
{
GtkAdjustment *adj = GTK_ADJUSTMENT(iwd->zoom_adjustment);
gdouble f = ((gdouble)SCALEDEST (((GDisplay *)iwd->gdisp_ptr)))/((gdouble)SCALESRC (((GDisplay *)iwd->gdisp_ptr)));
gdouble val;
if(f < 1.0)
{
val = -1/f;
}
else
{
val = f;
}
#endif /* 0 */
return FALSE;
if(abs((gint)adj->value) != (gint)(val - 1) && iwd->block_adj_sig != TRUE)
{
adj->value = val;
gtk_signal_emit_by_name (GTK_OBJECT (iwd->zoom_adjustment), "changed");
}
}
#endif /* 0 */
static void
move_to_point(NavWinData *iwd,
gint tx,
......@@ -616,9 +622,9 @@ nav_window_preview_events (GtkWidget *widget,
{
case GDK_EXPOSE:
break;
case GDK_MAP:
nav_window_update_preview(iwd,FALSE);
nav_window_update_preview_blank(iwd);
gtk_timeout_add(PREVIEW_UPDATE_TIMEOUT,(GtkFunction)nav_preview_update_do_timer,(gpointer)iwd);
break;
case GDK_BUTTON_PRESS:
......@@ -798,7 +804,8 @@ nav_window_expose_events (GtkWidget *widget,
static gint
nav_preview_update_do(NavWinData *iwd)
{
nav_window_update_preview(iwd,FALSE);
nav_window_update_preview(iwd);
nav_window_disp_area(iwd,iwd->gdisp_ptr);
gtk_widget_draw(iwd->preview, NULL);
iwd->installedDirtyTimer = FALSE;
return FALSE;
......@@ -826,16 +833,165 @@ nav_image_need_update (GtkObject *obj,
iwd->installedDirtyTimer = TRUE;
/* Update preview at a less busy time */
nav_window_update_preview(iwd,TRUE);
nav_window_update_preview_blank(iwd);
gtk_widget_draw(iwd->preview, NULL);
gtk_timeout_add(2000,(GtkFunction)nav_preview_update_do_timer,(gpointer)iwd);
gtk_timeout_add(PREVIEW_UPDATE_TIMEOUT,(GtkFunction)nav_preview_update_do_timer,(gpointer)iwd);
}
static void
navwindow_zoomin (GtkWidget *widget,
gpointer data)
{
NavWinData *iwd;
GDisplay *gdisp;
iwd = (NavWinData *)data;
if(!iwd)
return;
gdisp = (GDisplay *) iwd->gdisp_ptr;
change_scale(gdisp,ZOOMIN);
}
static void
navwindow_zoomout (GtkWidget *widget,
gpointer data)
{
NavWinData *iwd;
GDisplay *gdisp;
iwd = (NavWinData *)data;
if(!iwd)
return;
gdisp = (GDisplay *) iwd->gdisp_ptr;
change_scale(gdisp,ZOOMOUT);
}
static void
zoom_adj_changed (GtkAdjustment *adj,
gpointer data)
{
NavWinData *iwd;
GDisplay *gdisp;
gint scalesrc, scaledest;
iwd = (NavWinData *)data;
if(!iwd)
return;
gdisp = (GDisplay *) iwd->gdisp_ptr;
if(adj->value < 0.0)
{
scalesrc = abs((gint)adj->value-1);
scaledest = 1;
}
else
<