Commit 18df82df authored by David Odin's avatar David Odin

new tools to generate screenshots for the widget gallery. added the tools

* devel-docs/tools/*: new tools to generate screenshots for the widget gallery.
* devel-docs/Makefile.am: added the tools subdir.
* configure.in: modified accordingly.
parent fe06c301
......@@ -1700,6 +1700,7 @@ devel-docs/libgimpthumb/Makefile
devel-docs/libgimpthumb/version
devel-docs/libgimpwidgets/Makefile
devel-docs/libgimpwidgets/version
devel-docs/tools/Makefile
docs/Makefile
menus/Makefile
tips/Makefile
......
2005-04-20 DindinX <dindinx@gimp.org>
* tools/*: new tools to generate screenshots for the widget gallery.
* Makefile.am: added the tools subdir.
* ../configure.in: modified accordingly.
2005-04-20 DindinX <dindinx@gimp.org>
* libgimpwidgets/images/gimp-button.png
......
......@@ -8,7 +8,8 @@ SUBDIRS = \
libgimpmodule \
libgimpthumb \
libgimpwidgets \
libgimp
libgimp \
tools
EXTRA_DIST = \
ChangeLog \
......
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
`pkg-config --cflags gdk-2.0` -I$(top_srcdir)
LDADDS = $(GTK_LIBS) $(top_builddir)/libgimp/libgimpui-2.0.la $(top_builddir)/libgimpwidgets/libgimpwidgets-2.0.la
noinst_PROGRAMS = \
doc-shooter
doc_shooter_SOURCES= \
shadow.c \
shadow.h \
shooter.c \
widgets.c \
widgets.h
doc_shooter_LDADD = $(LDADDS)
clean-local:
rm -f *.png
The doc shooter is used to take screenshots of widgets for the GTK+
reference manuals. We use these images for both the headers of the
images, and for the visual index of GNOME images. They aren't part of
the docs build. Instead, the images are taken, and then copied by hand
into gtk+/docs/reference/gtk/images/
Ideally, the images should be taken once a release, and all images
should be updated at the same time. A simple theme should be used to
take the screenshots, and in the future, we may include a gtkrc file in
this directory for the shooter to use. Currently, all shots are
constrained to the same width. Care should be taken when adding new
widgets to keep this constraint.
#include "shadow.h"
#include <math.h>
#define BLUR_RADIUS 5
#define SHADOW_OFFSET (BLUR_RADIUS * 4 / 5)
#define SHADOW_OPACITY 0.75
typedef struct {
int size;
double *data;
} ConvFilter;
static double
gaussian (double x, double y, double r)
{
return ((1 / (2 * M_PI * r)) *
exp ((- (x * x + y * y)) / (2 * r * r)));
}
static ConvFilter *
create_blur_filter (int radius)
{
ConvFilter *filter;
int x, y;
double sum;
filter = g_new0 (ConvFilter, 1);
filter->size = radius * 2 + 1;
filter->data = g_new (double, filter->size * filter->size);
sum = 0.0;
for (y = 0 ; y < filter->size; y++)
{
for (x = 0 ; x < filter->size; x++)
{
sum += filter->data[y * filter->size + x] = gaussian (x - (filter->size >> 1),
y - (filter->size >> 1),
radius);
}
}
for (y = 0; y < filter->size; y++)
{
for (x = 0; x < filter->size; x++)
{
filter->data[y * filter->size + x] /= sum;
}
}
return filter;
}
static GdkPixbuf *
create_shadow (GdkPixbuf *src)
{
int x, y, i, j;
int width, height;
GdkPixbuf *dest;
static ConvFilter *filter = NULL;
int src_rowstride, dest_rowstride;
int src_bpp, dest_bpp;
guchar *src_pixels, *dest_pixels;
if (!filter)
filter = create_blur_filter (BLUR_RADIUS);
width = gdk_pixbuf_get_width (src) + BLUR_RADIUS * 2 + SHADOW_OFFSET;
height = gdk_pixbuf_get_height (src) + BLUR_RADIUS * 2 + SHADOW_OFFSET;
dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
gdk_pixbuf_get_has_alpha (src),
gdk_pixbuf_get_bits_per_sample (src),
width, height);
gdk_pixbuf_fill (dest, 0);
src_pixels = gdk_pixbuf_get_pixels (src);
src_rowstride = gdk_pixbuf_get_rowstride (src);
src_bpp = gdk_pixbuf_get_has_alpha (src) ? 4 : 3;
dest_pixels = gdk_pixbuf_get_pixels (dest);
dest_rowstride = gdk_pixbuf_get_rowstride (dest);
dest_bpp = gdk_pixbuf_get_has_alpha (dest) ? 4 : 3;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
int sumr = 0, sumg = 0, sumb = 0, suma = 0;
for (i = 0; i < filter->size; i++)
{
for (j = 0; j < filter->size; j++)
{
int src_x, src_y;
src_y = -(BLUR_RADIUS + SHADOW_OFFSET) + y - (filter->size >> 1) + i;
src_x = -(BLUR_RADIUS + SHADOW_OFFSET) + x - (filter->size >> 1) + j;
if (src_y < 0 || src_y > gdk_pixbuf_get_height (src) ||
src_x < 0 || src_x > gdk_pixbuf_get_width (src))
continue;
sumr += src_pixels [src_y * src_rowstride +
src_x * src_bpp + 0] *
filter->data [i * filter->size + j];
sumg += src_pixels [src_y * src_rowstride +
src_x * src_bpp + 1] *
filter->data [i * filter->size + j];
sumb += src_pixels [src_y * src_rowstride +
src_x * src_bpp + 2] *
filter->data [i * filter->size + j];
if (src_bpp == 4)
suma += src_pixels [src_y * src_rowstride +
src_x * src_bpp + 3] *
filter->data [i * filter->size + j];
}
}
if (dest_bpp == 4)
dest_pixels [y * dest_rowstride +
x * dest_bpp + 3] = suma * SHADOW_OPACITY;
}
}
return dest;
}
GdkPixbuf *
create_shadowed_pixbuf (GdkPixbuf *src)
{
GdkPixbuf *dest;
dest = create_shadow (src);
gdk_pixbuf_composite (src, dest,
BLUR_RADIUS, BLUR_RADIUS,
gdk_pixbuf_get_width (src),
gdk_pixbuf_get_height (src),
BLUR_RADIUS, BLUR_RADIUS, 1.0, 1.0,
GDK_INTERP_NEAREST, 255);
return dest;
}
#ifndef __SHADOW_H__
#define __SHADOW_H__
#include <gdk-pixbuf/gdk-pixbuf.h>
GdkPixbuf *create_shadowed_pixbuf (GdkPixbuf *src);
#endif /* __SHADOW_H__ */
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <stdio.h>
#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>
#include <X11/extensions/shape.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <locale.h>
#include "widgets.h"
#include "shadow.h"
#define MAXIMUM_WM_REPARENTING_DEPTH 4
#ifndef _
#define _(x) (x)
#endif
static Window
find_toplevel_window (Window xid)
{
Window root, parent, *children;
int nchildren;
do
{
if (XQueryTree ( gdk_x11_get_default_xdisplay (), xid, &root,
&parent, &children, &nchildren) == 0)
{
g_warning ("Couldn't find window manager window");
return 0;
}
if (root == parent)
return xid;
xid = parent;
}
while (TRUE);
}
static GdkPixbuf *
add_border_to_shot (GdkPixbuf *pixbuf)
{
GdkPixbuf *retval;
retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
gdk_pixbuf_get_width (pixbuf) + 2,
gdk_pixbuf_get_height (pixbuf) + 2);
/* Fill with solid black */
gdk_pixbuf_fill (retval, 0xFF);
gdk_pixbuf_copy_area (pixbuf,
0, 0,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
retval, 1, 1);
return retval;
}
static GdkPixbuf *
remove_shaped_area (GdkPixbuf *pixbuf,
Window window)
{
GdkPixbuf *retval;
XRectangle *rectangles;
int rectangle_count, rectangle_order;
int i;
retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
gdk_pixbuf_fill (retval, 0);
rectangles = XShapeGetRectangles ( gdk_x11_get_default_xdisplay(), window,
ShapeBounding, &rectangle_count, &rectangle_order);
for (i = 0; i < rectangle_count; i++)
{
int y, x;
for (y = rectangles[i].y; y < rectangles[i].y + rectangles[i].height; y++)
{
guchar *src_pixels, *dest_pixels;
src_pixels = gdk_pixbuf_get_pixels (pixbuf) +
y * gdk_pixbuf_get_rowstride (pixbuf) +
rectangles[i].x * (gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3);
dest_pixels = gdk_pixbuf_get_pixels (retval) +
y * gdk_pixbuf_get_rowstride (retval) +
rectangles[i].x * 4;
for (x = rectangles[i].x; x < rectangles[i].x + rectangles[i].width; x++)
{
*dest_pixels++ = *src_pixels ++;
*dest_pixels++ = *src_pixels ++;
*dest_pixels++ = *src_pixels ++;
*dest_pixels++ = 255;
if (gdk_pixbuf_get_has_alpha (pixbuf))
src_pixels++;
}
}
}
return retval;
}
static GdkPixbuf *
take_window_shot (Window child,
gboolean include_decoration)
{
GdkWindow *window;
Display *disp;
Window w, xid;
gint x_orig, y_orig;
gint x = 0, y = 0;
gint width, height;
GdkPixbuf *tmp, *tmp2;
GdkPixbuf *retval;
disp = gdk_x11_get_default_xdisplay ();
w = gdk_x11_get_default_root_xwindow ();
if (include_decoration)
xid = find_toplevel_window (child);
else
xid = child;
window = gdk_window_foreign_new (xid);
gdk_drawable_get_size (window, &width, &height);
gdk_window_get_origin (window, &x_orig, &y_orig);
if (x_orig < 0)
{
x = - x_orig;
width = width + x_orig;
x_orig = 0;
}
if (y_orig < 0)
{
y = - y_orig;
height = height + y_orig;
y_orig = 0;
}
if (x_orig + width > gdk_screen_width ())
width = gdk_screen_width () - x_orig;
if (y_orig + height > gdk_screen_height ())
height = gdk_screen_height () - y_orig;
tmp = gdk_pixbuf_get_from_drawable (NULL, window, NULL,
x, y, 0, 0, width, height);
if (include_decoration)
tmp2 = remove_shaped_area (tmp, xid);
else
tmp2 = add_border_to_shot (tmp);
retval = create_shadowed_pixbuf (tmp2);
g_object_unref (tmp);
g_object_unref (tmp2);
return retval;
}
int main (int argc, char **argv)
{
GList *toplevels;
GdkPixbuf *screenshot = NULL;
GList *node;
/* If there's no DISPLAY, we silently error out. We don't want to break
* headless builds. */
if (! gtk_init_check (&argc, &argv))
return 0;
gimp_stock_init ();
toplevels = get_all_widgets ();
for (node = toplevels; node; node = g_list_next (node))
{
GdkWindow *window;
WidgetInfo *info;
XID id;
char *filename;
info = node->data;
gtk_widget_show (info->window);
window = info->window->window;
gtk_widget_show_now (info->window);
gtk_widget_draw (info->window, &(info->window->allocation));
while (gtk_events_pending ())
{
gtk_main_iteration ();
}
sleep (1);
while (gtk_events_pending ())
{
gtk_main_iteration ();
}
id = gdk_x11_drawable_get_xid (GDK_DRAWABLE (window));
screenshot = take_window_shot (id, info->include_decorations);
filename = g_strdup_printf ("./%s.png", info->name);
gdk_pixbuf_save (screenshot, filename, "png", NULL, NULL);
g_free(filename);
gtk_widget_hide (info->window);
}
return 0;
}
This diff is collapsed.
#ifndef __WIDGETS_H__
#define __WIDGETS_H__
#include <gtk/gtk.h>
typedef enum
{
SMALL,
MEDIUM,
LARGE,
ASIS
} WidgetSize;
typedef struct WidgetInfo
{
GtkWidget *window;
gchar *name;
gboolean no_focus;
gboolean include_decorations;
WidgetSize size;
} WidgetInfo;
GList *get_all_widgets (void);
#endif /* __WIDGETS_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment