diff options
Diffstat (limited to 'qemu/pixman/demos/scale.c')
-rw-r--r-- | qemu/pixman/demos/scale.c | 436 |
1 files changed, 0 insertions, 436 deletions
diff --git a/qemu/pixman/demos/scale.c b/qemu/pixman/demos/scale.c deleted file mode 100644 index d00307e44..000000000 --- a/qemu/pixman/demos/scale.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright 2012, Red Hat, Inc. - * Copyright 2012, Soren Sandmann - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Author: Soren Sandmann <soren.sandmann@gmail.com> - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <math.h> -#include <gtk/gtk.h> -#include <pixman.h> -#include <stdlib.h> -#include "gtk-utils.h" - -typedef struct -{ - GtkBuilder * builder; - pixman_image_t * original; - GtkAdjustment * scale_x_adjustment; - GtkAdjustment * scale_y_adjustment; - GtkAdjustment * rotate_adjustment; - GtkAdjustment * subsample_adjustment; - int scaled_width; - int scaled_height; -} app_t; - -static GtkWidget * -get_widget (app_t *app, const char *name) -{ - GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (app->builder, name)); - - if (!widget) - g_error ("Widget %s not found\n", name); - - return widget; -} - -static double -min4 (double a, double b, double c, double d) -{ - double m1, m2; - - m1 = MIN (a, b); - m2 = MIN (c, d); - return MIN (m1, m2); -} - -static double -max4 (double a, double b, double c, double d) -{ - double m1, m2; - - m1 = MAX (a, b); - m2 = MAX (c, d); - return MAX (m1, m2); -} - -static void -compute_extents (pixman_f_transform_t *trans, double *sx, double *sy) -{ - double min_x, max_x, min_y, max_y; - pixman_f_vector_t v[4] = - { - { { 1, 1, 1 } }, - { { -1, 1, 1 } }, - { { -1, -1, 1 } }, - { { 1, -1, 1 } }, - }; - - pixman_f_transform_point (trans, &v[0]); - pixman_f_transform_point (trans, &v[1]); - pixman_f_transform_point (trans, &v[2]); - pixman_f_transform_point (trans, &v[3]); - - min_x = min4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]); - max_x = max4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]); - min_y = min4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]); - max_y = max4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]); - - *sx = (max_x - min_x) / 2.0; - *sy = (max_y - min_y) / 2.0; -} - -typedef struct -{ - char name [20]; - int value; -} named_int_t; - -static const named_int_t filters[] = -{ - { "Box", PIXMAN_KERNEL_BOX }, - { "Impulse", PIXMAN_KERNEL_IMPULSE }, - { "Linear", PIXMAN_KERNEL_LINEAR }, - { "Cubic", PIXMAN_KERNEL_CUBIC }, - { "Lanczos2", PIXMAN_KERNEL_LANCZOS2 }, - { "Lanczos3", PIXMAN_KERNEL_LANCZOS3 }, - { "Lanczos3 Stretched", PIXMAN_KERNEL_LANCZOS3_STRETCHED }, - { "Gaussian", PIXMAN_KERNEL_GAUSSIAN }, -}; - -static const named_int_t repeats[] = -{ - { "None", PIXMAN_REPEAT_NONE }, - { "Normal", PIXMAN_REPEAT_NORMAL }, - { "Reflect", PIXMAN_REPEAT_REFLECT }, - { "Pad", PIXMAN_REPEAT_PAD }, -}; - -static int -get_value (app_t *app, const named_int_t table[], const char *box_name) -{ - GtkComboBox *box = GTK_COMBO_BOX (get_widget (app, box_name)); - - return table[gtk_combo_box_get_active (box)].value; -} - -static void -copy_to_counterpart (app_t *app, GObject *object) -{ - static const char *xy_map[] = - { - "reconstruct_x_combo_box", "reconstruct_y_combo_box", - "sample_x_combo_box", "sample_y_combo_box", - "scale_x_adjustment", "scale_y_adjustment", - }; - GObject *counterpart = NULL; - int i; - - for (i = 0; i < G_N_ELEMENTS (xy_map); i += 2) - { - GObject *x = gtk_builder_get_object (app->builder, xy_map[i]); - GObject *y = gtk_builder_get_object (app->builder, xy_map[i + 1]); - - if (object == x) - counterpart = y; - if (object == y) - counterpart = x; - } - - if (!counterpart) - return; - - if (GTK_IS_COMBO_BOX (counterpart)) - { - gtk_combo_box_set_active ( - GTK_COMBO_BOX (counterpart), - gtk_combo_box_get_active ( - GTK_COMBO_BOX (object))); - } - else if (GTK_IS_ADJUSTMENT (counterpart)) - { - gtk_adjustment_set_value ( - GTK_ADJUSTMENT (counterpart), - gtk_adjustment_get_value ( - GTK_ADJUSTMENT (object))); - } -} - -static double -to_scale (double v) -{ - return pow (1.15, v); -} - -static void -rescale (GtkWidget *may_be_null, app_t *app) -{ - pixman_f_transform_t ftransform; - pixman_transform_t transform; - double new_width, new_height; - double fscale_x, fscale_y; - double rotation; - pixman_fixed_t *params; - int n_params; - double sx, sy; - - pixman_f_transform_init_identity (&ftransform); - - if (may_be_null && gtk_toggle_button_get_active ( - GTK_TOGGLE_BUTTON (get_widget (app, "lock_checkbutton")))) - { - copy_to_counterpart (app, G_OBJECT (may_be_null)); - } - - fscale_x = gtk_adjustment_get_value (app->scale_x_adjustment); - fscale_y = gtk_adjustment_get_value (app->scale_y_adjustment); - rotation = gtk_adjustment_get_value (app->rotate_adjustment); - - fscale_x = to_scale (fscale_x); - fscale_y = to_scale (fscale_y); - - new_width = pixman_image_get_width (app->original) * fscale_x; - new_height = pixman_image_get_height (app->original) * fscale_y; - - pixman_f_transform_scale (&ftransform, NULL, fscale_x, fscale_y); - - pixman_f_transform_translate (&ftransform, NULL, - new_width / 2.0, - new_height / 2.0); - - rotation = (rotation / 360.0) * 2 * M_PI; - pixman_f_transform_rotate (&ftransform, NULL, cos (rotation), sin (rotation)); - - pixman_f_transform_translate (&ftransform, NULL, new_width / 2.0, new_height / 2.0); - - pixman_f_transform_invert (&ftransform, &ftransform); - - compute_extents (&ftransform, &sx, &sy); - - pixman_transform_from_pixman_f_transform (&transform, &ftransform); - pixman_image_set_transform (app->original, &transform); - - params = pixman_filter_create_separable_convolution ( - &n_params, - sx * 65536.0 + 0.5, - sy * 65536.0 + 0.5, - get_value (app, filters, "reconstruct_x_combo_box"), - get_value (app, filters, "reconstruct_y_combo_box"), - get_value (app, filters, "sample_x_combo_box"), - get_value (app, filters, "sample_y_combo_box"), - gtk_adjustment_get_value (app->subsample_adjustment), - gtk_adjustment_get_value (app->subsample_adjustment)); - - pixman_image_set_filter (app->original, PIXMAN_FILTER_SEPARABLE_CONVOLUTION, params, n_params); - - pixman_image_set_repeat ( - app->original, get_value (app, repeats, "repeat_combo_box")); - - free (params); - - app->scaled_width = ceil (new_width); - app->scaled_height = ceil (new_height); - - gtk_widget_set_size_request ( - get_widget (app, "drawing_area"), new_width + 0.5, new_height + 0.5); - - gtk_widget_queue_draw ( - get_widget (app, "drawing_area")); -} - -static gboolean -on_expose (GtkWidget *da, GdkEvent *event, gpointer data) -{ - app_t *app = data; - GdkRectangle *area = &event->expose.area; - cairo_surface_t *surface; - pixman_image_t *tmp; - cairo_t *cr; - uint32_t *pixels; - - pixels = calloc (1, area->width * area->height * 4); - tmp = pixman_image_create_bits ( - PIXMAN_a8r8g8b8, area->width, area->height, pixels, area->width * 4); - - if (area->x < app->scaled_width && area->y < app->scaled_height) - { - pixman_image_composite ( - PIXMAN_OP_SRC, - app->original, NULL, tmp, - area->x, area->y, 0, 0, 0, 0, - app->scaled_width - area->x, app->scaled_height - area->y); - } - - surface = cairo_image_surface_create_for_data ( - (uint8_t *)pixels, CAIRO_FORMAT_ARGB32, - area->width, area->height, area->width * 4); - - cr = gdk_cairo_create (da->window); - - cairo_set_source_surface (cr, surface, area->x, area->y); - - cairo_paint (cr); - - cairo_destroy (cr); - cairo_surface_destroy (surface); - free (pixels); - pixman_image_unref (tmp); - - return TRUE; -} - -static void -set_up_combo_box (app_t *app, const char *box_name, - int n_entries, const named_int_t table[]) -{ - GtkWidget *widget = get_widget (app, box_name); - GtkListStore *model; - GtkCellRenderer *cell; - int i; - - model = gtk_list_store_new (1, G_TYPE_STRING); - - cell = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), cell, - "text", 0, - NULL); - - gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (model)); - - for (i = 0; i < n_entries; ++i) - { - const named_int_t *info = &(table[i]); - GtkTreeIter iter; - - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, 0, info->name, -1); - } - - gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); - - g_signal_connect (widget, "changed", G_CALLBACK (rescale), app); -} - -static void -set_up_filter_box (app_t *app, const char *box_name) -{ - set_up_combo_box (app, box_name, G_N_ELEMENTS (filters), filters); -} - -static char * -format_value (GtkWidget *widget, double value) -{ - return g_strdup_printf ("%.4f", to_scale (value)); -} - -static app_t * -app_new (pixman_image_t *original) -{ - GtkWidget *widget; - app_t *app = g_malloc (sizeof *app); - GError *err = NULL; - - app->builder = gtk_builder_new (); - app->original = original; - - if (!gtk_builder_add_from_file (app->builder, "scale.ui", &err)) - g_error ("Could not read file scale.ui: %s", err->message); - - app->scale_x_adjustment = - GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "scale_x_adjustment")); - app->scale_y_adjustment = - GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "scale_y_adjustment")); - app->rotate_adjustment = - GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "rotate_adjustment")); - app->subsample_adjustment = - GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "subsample_adjustment")); - - g_signal_connect (app->scale_x_adjustment, "value_changed", G_CALLBACK (rescale), app); - g_signal_connect (app->scale_y_adjustment, "value_changed", G_CALLBACK (rescale), app); - g_signal_connect (app->rotate_adjustment, "value_changed", G_CALLBACK (rescale), app); - g_signal_connect (app->subsample_adjustment, "value_changed", G_CALLBACK (rescale), app); - - widget = get_widget (app, "scale_x_scale"); - gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL); - g_signal_connect (widget, "format_value", G_CALLBACK (format_value), app); - widget = get_widget (app, "scale_y_scale"); - gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL); - g_signal_connect (widget, "format_value", G_CALLBACK (format_value), app); - widget = get_widget (app, "rotate_scale"); - gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL); - - widget = get_widget (app, "drawing_area"); - g_signal_connect (widget, "expose_event", G_CALLBACK (on_expose), app); - - set_up_filter_box (app, "reconstruct_x_combo_box"); - set_up_filter_box (app, "reconstruct_y_combo_box"); - set_up_filter_box (app, "sample_x_combo_box"); - set_up_filter_box (app, "sample_y_combo_box"); - - set_up_combo_box ( - app, "repeat_combo_box", G_N_ELEMENTS (repeats), repeats); - - g_signal_connect ( - gtk_builder_get_object (app->builder, "lock_checkbutton"), - "toggled", G_CALLBACK (rescale), app); - - rescale (NULL, app); - - return app; -} - -int -main (int argc, char **argv) -{ - GtkWidget *window; - pixman_image_t *image; - app_t *app; - - gtk_init (&argc, &argv); - - if (argc < 2) - { - printf ("%s <image file>\n", argv[0]); - return -1; - } - - if (!(image = pixman_image_from_file (argv[1], PIXMAN_a8r8g8b8))) - { - printf ("Could not load image \"%s\"\n", argv[1]); - return -1; - } - - app = app_new (image); - - window = get_widget (app, "main"); - - g_signal_connect (window, "delete_event", G_CALLBACK (gtk_main_quit), NULL); - - gtk_window_set_default_size (GTK_WINDOW (window), 1024, 768); - - gtk_widget_show_all (window); - - gtk_main (); - - return 0; -} |