Beispiel #1
0
/**
 * cheese_avatar_widget_get_picture:
 * @widget: a #CheeseAvatarWidget dialogue
 *
 * Returns the portion of image selected through the builtin cropping tool,
 * after a picture has been captured on the webcam.
 *
 * Return value: a #GdkPixbuf object, or %NULL if no picture has been taken yet
 */
GdkPixbuf *
cheese_avatar_widget_get_picture (CheeseAvatarWidget *widget)
{
    CheeseAvatarWidgetPrivate *priv;

    g_return_val_if_fail (CHEESE_IS_AVATAR_WIDGET (widget), NULL);

    priv = cheese_avatar_widget_get_instance_private (widget);

    return um_crop_area_get_picture (UM_CROP_AREA (priv->image));
}
static void
um_photo_dialog_crop (UmPhotoDialog *um,
                      GdkPixbuf     *pixbuf)
{
        GtkWidget *dialog;
        GtkWidget *frame;

        dialog = gtk_dialog_new_with_buttons ("",
                                              GTK_WINDOW (gtk_widget_get_toplevel (um->popup_button)),
                                              0,
                                              GTK_STOCK_CANCEL,
                                              GTK_RESPONSE_REJECT,
                                              _("Select"),
                                              GTK_RESPONSE_ACCEPT,
                                              NULL);
        gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);

        gtk_window_set_icon_name (GTK_WINDOW (dialog), "system-users");

        g_signal_connect (G_OBJECT (dialog), "response",
                          G_CALLBACK (crop_dialog_response), um);

        /* Content */
        um->crop_area           = um_crop_area_new ();
        um_crop_area_set_min_size (UM_CROP_AREA (um->crop_area), 48, 48);
        um_crop_area_set_constrain_aspect (UM_CROP_AREA (um->crop_area), TRUE);
        um_crop_area_set_picture (UM_CROP_AREA (um->crop_area), pixbuf);
        frame                   = gtk_frame_new (NULL);
        gtk_container_add (GTK_CONTAINER (frame), um->crop_area);
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);

        gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
                            frame,
                            TRUE, TRUE, 8);

        gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 300);

        gtk_widget_show_all (dialog);
}
Beispiel #3
0
/*
 * take_again_button_clicked_cb:
 * @button: the #GtkButton that was clicked
 * @widget: the #CheeseAvatarWidget
 *
 * Switch the @widget back to the camera view, ready to take another photo.
 */
static void
take_again_button_clicked_cb (GtkButton           *button,
                              CheeseAvatarWidget *widget)
{
    CheeseAvatarWidgetPrivate *priv;

    priv = cheese_avatar_widget_get_instance_private (widget);

    gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), WIDGET_PAGE);

    um_crop_area_set_picture (UM_CROP_AREA (priv->image), NULL);

    g_object_notify_by_pspec (G_OBJECT (widget), properties[PROP_PIXBUF]);
}
static void
um_crop_area_finalize (GObject *object)
{
        UmCropArea *area = UM_CROP_AREA (object);

        if (area->priv->browse_pixbuf) {
                g_object_unref (area->priv->browse_pixbuf);
                area->priv->browse_pixbuf = NULL;
        }
        if (area->priv->pixbuf) {
                g_object_unref (area->priv->pixbuf);
                area->priv->pixbuf = NULL;
        }
        if (area->priv->color_shifted) {
                g_object_unref (area->priv->color_shifted);
                area->priv->color_shifted = NULL;
        }
}
Beispiel #5
0
static void
cheese_avatar_widget_get_property (GObject *object, guint prop_id,
                                   GValue *value, GParamSpec *pspec)
{
    CheeseAvatarWidgetPrivate *priv;

    priv = cheese_avatar_widget_get_instance_private (CHEESE_AVATAR_WIDGET (object));

    switch (prop_id)
    {
    case PROP_PIXBUF:
        g_value_set_object (value, um_crop_area_get_picture (UM_CROP_AREA (priv->image)));
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}
Beispiel #6
0
/*
 * cheese_widget_photo_taken_cb:
 * @camera: a #CheeseCamera
 * @pixbuf: the #GdkPixbuf of the image that was just taken
 * @choose: a #CheeseAvatarWidget
 *
 * Show the image that was just taken from the camera (as @pixbuf) in the
 * cropping tool.
 */
static void
cheese_widget_photo_taken_cb (CheeseCamera        *camera,
                              GdkPixbuf           *pixbuf,
                              CheeseAvatarWidget  *widget)
{
    CheeseAvatarWidgetPrivate *priv;
    GtkAllocation               allocation;

    priv = cheese_avatar_widget_get_instance_private (widget);
    gtk_widget_get_allocation (priv->camera, &allocation);
    gtk_widget_set_size_request (priv->image, allocation.width, allocation.height);

    um_crop_area_set_picture (UM_CROP_AREA (priv->image), pixbuf);
    gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), IMAGE_PAGE);

    gtk_widget_set_sensitive (priv->take_button, TRUE);

    g_object_notify_by_pspec (G_OBJECT (widget), properties[PROP_PIXBUF]);
}
static void
um_crop_area_finalize (GObject *object)
{
        UmCropAreaPrivate *priv = um_crop_area_get_instance_private (UM_CROP_AREA (object));

        if (priv->browse_pixbuf) {
                g_object_unref (priv->browse_pixbuf);
                priv->browse_pixbuf = NULL;
        }
        if (priv->pixbuf) {
                g_object_unref (priv->pixbuf);
                priv->pixbuf = NULL;
        }
        if (priv->color_shifted) {
                g_object_unref (priv->color_shifted);
                priv->color_shifted = NULL;
        }

        G_OBJECT_CLASS (um_crop_area_parent_class)->finalize (object);
}
static gboolean
um_crop_area_button_release_event (GtkWidget      *widget,
                                   GdkEventButton *event)
{
        UmCropArea *area = UM_CROP_AREA (widget);
        GdkRectangle crop;

        if (area->priv->browse_pixbuf == NULL)
                return FALSE;

        crop_to_widget (area, &crop);

        area->priv->last_press_x = -1;
        area->priv->last_press_y = -1;
        area->priv->active_region = OUTSIDE;

        gtk_widget_queue_draw_area (widget,
                                    crop.x - 1, crop.y - 1,
                                    crop.width + 2, crop.height + 2);

        return FALSE;
}
static gboolean
um_crop_area_button_press_event (GtkWidget      *widget,
                                 GdkEventButton *event)
{
        UmCropArea *area = UM_CROP_AREA (widget);
        GdkRectangle crop;

        if (area->priv->browse_pixbuf == NULL)
                return FALSE;

        crop_to_widget (area, &crop);

        area->priv->last_press_x = (event->x - area->priv->image.x) / area->priv->scale;
        area->priv->last_press_y = (event->y - area->priv->image.y) / area->priv->scale;
        area->priv->active_region = find_location (&crop, event->x, event->y);

        gtk_widget_queue_draw_area (widget,
                                    crop.x - 1, crop.y - 1,
                                    crop.width + 2, crop.height + 2);

        return FALSE;
}
static void
crop_dialog_response (GtkWidget     *dialog,
                      gint           response_id,
                      UmPhotoDialog *um)
{
        GdkPixbuf *pb, *pb2;

        if (response_id != GTK_RESPONSE_ACCEPT) {
                um->crop_area = NULL;
                gtk_widget_destroy (dialog);
                return;
        }

        pb = um_crop_area_get_picture (UM_CROP_AREA (um->crop_area));
        pb2 = gdk_pixbuf_scale_simple (pb, 96, 96, GDK_INTERP_BILINEAR);

        um_user_set_icon_data (um->user, pb2);

        g_object_unref (pb2);
        g_object_unref (pb);

        um->crop_area = NULL;
        gtk_widget_destroy (dialog);
}
static gboolean
um_crop_area_motion_notify_event (GtkWidget      *widget,
                                  GdkEventMotion *event)
{
        UmCropArea *area = UM_CROP_AREA (widget);
        gint x, y;
        gint delta_x, delta_y;
        gint width, height;
        gint adj_width, adj_height;
        gint pb_width, pb_height;
        GdkRectangle damage;
        gint left, right, top, bottom;
        gdouble new_width, new_height;
        gdouble center_x, center_y;
        gint min_width, min_height;

        if (area->priv->browse_pixbuf == NULL)
                return FALSE;

        update_cursor (area, event->x, event->y);

        crop_to_widget (area, &damage);
        gtk_widget_queue_draw_area (widget,
                                    damage.x - 1, damage.y - 1,
                                    damage.width + 2, damage.height + 2);

        pb_width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
        pb_height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);

        x = (event->x - area->priv->image.x) / area->priv->scale;
        y = (event->y - area->priv->image.y) / area->priv->scale;

        delta_x = x - area->priv->last_press_x;
        delta_y = y - area->priv->last_press_y;
        area->priv->last_press_x = x;
        area->priv->last_press_y = y;

        left = area->priv->crop.x;
        right = area->priv->crop.x + area->priv->crop.width - 1;
        top = area->priv->crop.y;
        bottom = area->priv->crop.y + area->priv->crop.height - 1;

        center_x = (left + right) / 2.0;
        center_y = (top + bottom) / 2.0;

        switch (area->priv->active_region) {
        case INSIDE:
                width = right - left + 1;
                height = bottom - top + 1;

                left += delta_x;
                right += delta_x;
                top += delta_y;
                bottom += delta_y;

                if (left < 0)
                        left = 0;
                if (top < 0)
                        top = 0;
                if (right > pb_width)
                        right = pb_width;
                if (bottom > pb_height)
                        bottom = pb_height;

                adj_width = right - left + 1;
                adj_height = bottom - top + 1;
                if (adj_width != width) {
                        if (delta_x < 0)
                                right = left + width - 1;
                        else
                                left = right - width + 1;
                }
                if (adj_height != height) {
                        if (delta_y < 0)
                                bottom = top + height - 1;
                        else
                                top = bottom - height + 1;
                }

                break;

        case TOP_LEFT:
                if (area->priv->aspect < 0) {
                        top = y;
                        left = x;
                }
                else if (y < eval_radial_line (center_x, center_y, left, top, x)) {
                        top = y;
                        new_width = (bottom - top) * area->priv->aspect;
                        left = right - new_width;
                }
                else {
                        left = x;
                        new_height = (right - left) / area->priv->aspect;
                        top = bottom - new_height;
                }
                break;

        case TOP:
                top = y;
                if (area->priv->aspect > 0) {
                        new_width = (bottom - top) * area->priv->aspect;
                        right = left + new_width;
                }
                break;

        case TOP_RIGHT:
                if (area->priv->aspect < 0) {
                        top = y;
                        right = x;
                }
                else if (y < eval_radial_line (center_x, center_y, right, top, x)) {
                        top = y;
                        new_width = (bottom - top) * area->priv->aspect;
                        right = left + new_width;
                }
                else {
                        right = x;
                        new_height = (right - left) / area->priv->aspect;
                        top = bottom - new_height;
                }
                break;

        case LEFT:
                left = x;
                if (area->priv->aspect > 0) {
                        new_height = (right - left) / area->priv->aspect;
                        bottom = top + new_height;
                }
                break;

        case BOTTOM_LEFT:
                if (area->priv->aspect < 0) {
                        bottom = y;
                        left = x;
                }
                else if (y < eval_radial_line (center_x, center_y, left, bottom, x)) {
                        left = x;
                        new_height = (right - left) / area->priv->aspect;
                        bottom = top + new_height;
                }
                else {
                        bottom = y;
                        new_width = (bottom - top) * area->priv->aspect;
                        left = right - new_width;
                }
                break;

        case RIGHT:
                right = x;
                if (area->priv->aspect > 0) {
                        new_height = (right - left) / area->priv->aspect;
                        bottom = top + new_height;
                }
                break;

        case BOTTOM_RIGHT:
                if (area->priv->aspect < 0) {
                        bottom = y;
                        right = x;
                }
                else if (y < eval_radial_line (center_x, center_y, right, bottom, x)) {
                        right = x;
                        new_height = (right - left) / area->priv->aspect;
                        bottom = top + new_height;
                }
                else {
                        bottom = y;
                        new_width = (bottom - top) * area->priv->aspect;
                        right = left + new_width;
                }
                break;

        case BOTTOM:
                bottom = y;
                if (area->priv->aspect > 0) {
                        new_width = (bottom - top) * area->priv->aspect;
                        right= left + new_width;
                }
                break;

        default:
                return FALSE;
        }

        min_width = area->priv->base_width / area->priv->scale;
        min_height = area->priv->base_height / area->priv->scale;

        width = right - left + 1;
        height = bottom - top + 1;
        if (area->priv->aspect < 0) {
                if (left < 0)
                        left = 0;
                if (top < 0)
                        top = 0;
                if (right > pb_width)
                        right = pb_width;
                if (bottom > pb_height)
                        bottom = pb_height;

                width = right - left + 1;
                height = bottom - top + 1;

                switch (area->priv->active_region) {
                case LEFT:
                case TOP_LEFT:
                case BOTTOM_LEFT:
                        if (width < min_width)
                                left = right - min_width;
                        break;
                case RIGHT:
                case TOP_RIGHT:
                case BOTTOM_RIGHT:
                        if (width < min_width)
                                right = left + min_width;
                        break;

                default: ;
                }

                switch (area->priv->active_region) {
                case TOP:
                case TOP_LEFT:
                case TOP_RIGHT:
                        if (height < min_height)
                                top = bottom - min_height;
                        break;
                case BOTTOM:
                case BOTTOM_LEFT:
                case BOTTOM_RIGHT:
                        if (height < min_height)
                                bottom = top + min_height;
                        break;

                default: ;
                }
        }
        else {
                if (left < 0 || top < 0 ||
                    right > pb_width || bottom > pb_height ||
                    width < min_width || height < min_height) {
                        left = area->priv->crop.x;
                        right = area->priv->crop.x + area->priv->crop.width - 1;
                        top = area->priv->crop.y;
                        bottom = area->priv->crop.y + area->priv->crop.height - 1;
                }
        }

        area->priv->crop.x = left;
        area->priv->crop.y = top;
        area->priv->crop.width = right - left + 1;
        area->priv->crop.height = bottom - top + 1;

        crop_to_widget (area, &damage);
        gtk_widget_queue_draw_area (widget,
                                    damage.x - 1, damage.y - 1,
                                    damage.width + 2, damage.height + 2);

        return FALSE;
}
static gboolean
um_crop_area_draw (GtkWidget *widget,
                   cairo_t   *cr)
{
        GdkRectangle crop;
        gint width, height;
        UmCropArea *uarea = UM_CROP_AREA (widget);

        if (uarea->priv->browse_pixbuf == NULL)
                return FALSE;

        update_pixbufs (uarea);

        width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
        height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
        crop_to_widget (uarea, &crop);

        gdk_cairo_set_source_pixbuf (cr, uarea->priv->color_shifted, 0, 0);
        cairo_rectangle (cr, 0, 0, width, crop.y);
        cairo_rectangle (cr, 0, crop.y, crop.x, crop.height);
        cairo_rectangle (cr, crop.x + crop.width, crop.y, width - crop.x - crop.width, crop.height);
        cairo_rectangle (cr, 0, crop.y + crop.height, width, height - crop.y - crop.height);
        cairo_fill (cr);

        gdk_cairo_set_source_pixbuf (cr, uarea->priv->pixbuf, 0, 0);
        cairo_rectangle (cr, crop.x, crop.y, crop.width, crop.height);
        cairo_fill (cr);

        if (uarea->priv->active_region != OUTSIDE) {
                gint x1, x2, y1, y2;
                cairo_set_source_rgb (cr, 1, 1, 1);
                cairo_set_line_width (cr, 1.0);
                x1 = crop.x + crop.width / 3.0;
                x2 = crop.x + 2 * crop.width / 3.0;
                y1 = crop.y + crop.height / 3.0;
                y2 = crop.y + 2 * crop.height / 3.0;

                cairo_move_to (cr, x1 + 0.5, crop.y);
                cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);

                cairo_move_to (cr, x2 + 0.5, crop.y);
                cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);

                cairo_move_to (cr, crop.x, y1 + 0.5);
                cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);

                cairo_move_to (cr, crop.x, y2 + 0.5);
                cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
                cairo_stroke (cr);
        }

        cairo_set_source_rgb (cr,  0, 0, 0);
        cairo_set_line_width (cr, 1.0);
        cairo_rectangle (cr,
                         crop.x + 0.5,
                         crop.y + 0.5,
                         crop.width - 1.0,
                         crop.height - 1.0);
        cairo_stroke (cr);

        cairo_set_source_rgb (cr, 1, 1, 1);
        cairo_set_line_width (cr, 2.0);
        cairo_rectangle (cr,
                         crop.x + 2.0,
                         crop.y + 2.0,
                         crop.width - 4.0,
                         crop.height - 4.0);
        cairo_stroke (cr);

        return FALSE;
}
static gboolean
um_crop_area_expose (GtkWidget      *widget,
                     GdkEventExpose *event)
{
        cairo_t *cr;
        GdkRectangle area;
        GdkRectangle crop;
        gint width, height;
        UmCropArea *uarea = UM_CROP_AREA (widget);

        if (uarea->priv->browse_pixbuf == NULL)
                return FALSE;

        update_pixbufs (uarea);

        width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
        height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
        crop_to_widget (uarea, &crop);

        area.x = 0;
        area.y = 0;
        area.width = width;
        area.height = crop.y;
        gdk_rectangle_intersect (&area, &event->area, &area);
        gdk_draw_pixbuf (widget->window,
                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                         uarea->priv->color_shifted,
                         area.x, area.y,
                         area.x, area.y,
                         area.width, area.height,
                         GDK_RGB_DITHER_NONE, 0, 0);

        area.x = 0;
        area.y = crop.y;
        area.width = crop.x;
        area.height = crop.height;
        gdk_rectangle_intersect (&area, &event->area, &area);
        gdk_draw_pixbuf (widget->window,
                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                         uarea->priv->color_shifted,
                         area.x, area.y,
                         area.x, area.y,
                         area.width, area.height,
                         GDK_RGB_DITHER_NONE, 0, 0);

        area.x = crop.x;
        area.y = crop.y;
        area.width = crop.width;
        area.height = crop.height;
        gdk_rectangle_intersect (&area, &event->area, &area);
        gdk_draw_pixbuf (widget->window,
                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                         uarea->priv->pixbuf,
                         area.x, area.y,
                         area.x, area.y,
                         area.width, area.height,
                         GDK_RGB_DITHER_NONE, 0, 0);

        area.x = crop.x + crop.width;
        area.y = crop.y;
        area.width = width - area.x;
        area.height = crop.height;
        gdk_rectangle_intersect (&area, &event->area, &area);
        gdk_draw_pixbuf (widget->window,
                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                         uarea->priv->color_shifted,
                         area.x, area.y,
                         area.x, area.y,
                         area.width, area.height,
                         GDK_RGB_DITHER_NONE, 0, 0);

        area.x = 0;
        area.y = crop.y + crop.height;
        area.width = width;
        area.height = height - area.y;
        gdk_rectangle_intersect (&area, &event->area, &area);
        gdk_draw_pixbuf (widget->window,
                         widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                         uarea->priv->color_shifted,
                         area.x, area.y,
                         area.x, area.y,
                         area.width, area.height,
                         GDK_RGB_DITHER_NONE, 0, 0);

        cr = gdk_cairo_create (widget->window);
        gdk_cairo_rectangle (cr, &event->area);
        cairo_clip (cr);

        if (uarea->priv->active_region != OUTSIDE) {
                gint x1, x2, y1, y2;
                gdk_cairo_set_source_color (cr, &widget->style->white);
                cairo_set_line_width (cr, 1.0);
                x1 = crop.x + crop.width / 3.0;
                x2 = crop.x + 2 * crop.width / 3.0;
                y1 = crop.y + crop.height / 3.0;
                y2 = crop.y + 2 * crop.height / 3.0;

                cairo_move_to (cr, x1 + 0.5, crop.y);
                cairo_line_to (cr, x1 + 0.5, crop.y + crop.height);

                cairo_move_to (cr, x2 + 0.5, crop.y);
                cairo_line_to (cr, x2 + 0.5, crop.y + crop.height);

                cairo_move_to (cr, crop.x, y1 + 0.5);
                cairo_line_to (cr, crop.x + crop.width, y1 + 0.5);

                cairo_move_to (cr, crop.x, y2 + 0.5);
                cairo_line_to (cr, crop.x + crop.width, y2 + 0.5);
                cairo_stroke (cr);
        }

        gdk_cairo_set_source_color (cr, &widget->style->black);
        cairo_set_line_width (cr, 1.0);
        cairo_rectangle (cr,
                         crop.x + 0.5,
                         crop.y + 0.5,
                         crop.width - 1.0,
                         crop.height - 1.0);
        cairo_stroke (cr);

        gdk_cairo_set_source_color (cr, &widget->style->white);
        cairo_set_line_width (cr, 2.0);
        cairo_rectangle (cr,
                         crop.x + 2.0,
                         crop.y + 2.0,
                         crop.width - 4.0,
                         crop.height - 4.0);
        cairo_stroke (cr);

        cairo_destroy (cr);

        return FALSE;
}