15
15
* You should have received a copy of the GNU General Public License
16
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
* Written by: Matthias Clasen <mclasen@redhat.com>
140
141
gtk_widget_get_allocation (widget, &allocation);
141
142
context = gtk_widget_get_style_context (widget);
143
if (area->priv->pixbuf == NULL ||
144
gdk_pixbuf_get_width (area->priv->pixbuf) != allocation.width ||
145
gdk_pixbuf_get_height (area->priv->pixbuf) != allocation.height) {
146
if (area->priv->pixbuf != NULL)
147
g_object_unref (area->priv->pixbuf);
148
area->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
149
gdk_pixbuf_get_has_alpha (area->priv->browse_pixbuf),
144
if (priv->pixbuf == NULL ||
145
gdk_pixbuf_get_width (priv->pixbuf) != allocation.width ||
146
gdk_pixbuf_get_height (priv->pixbuf) != allocation.height) {
147
if (priv->pixbuf != NULL)
148
g_object_unref (priv->pixbuf);
149
priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
150
gdk_pixbuf_get_has_alpha (priv->browse_pixbuf),
151
152
allocation.width, allocation.height);
154
155
pixel = (((gint)(color.red * 1.0)) << 16) |
155
156
(((gint)(color.green * 1.0)) << 8) |
156
157
((gint)(color.blue * 1.0));
157
gdk_pixbuf_fill (area->priv->pixbuf, pixel);
158
gdk_pixbuf_fill (priv->pixbuf, pixel);
159
width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
160
height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
160
width = gdk_pixbuf_get_width (priv->browse_pixbuf);
161
height = gdk_pixbuf_get_height (priv->browse_pixbuf);
162
163
scale = allocation.height / (gdouble)height;
163
164
if (scale * width > allocation.width)
168
169
dest_x = (allocation.width - dest_width) / 2;
169
170
dest_y = (allocation.height - dest_height) / 2,
171
gdk_pixbuf_scale (area->priv->browse_pixbuf,
172
gdk_pixbuf_scale (priv->browse_pixbuf,
174
175
dest_width, dest_height,
177
178
GDK_INTERP_BILINEAR);
179
if (area->priv->color_shifted)
180
g_object_unref (area->priv->color_shifted);
181
area->priv->color_shifted = gdk_pixbuf_copy (area->priv->pixbuf);
182
shift_colors (area->priv->color_shifted, -32, -32, -32, 0);
184
if (area->priv->scale == 0.0) {
185
area->priv->crop.width = 2 * area->priv->base_width / scale;
186
area->priv->crop.height = 2 * area->priv->base_height / scale;
187
area->priv->crop.x = (gdk_pixbuf_get_width (area->priv->browse_pixbuf) - area->priv->crop.width) / 2;
188
area->priv->crop.y = (gdk_pixbuf_get_height (area->priv->browse_pixbuf) - area->priv->crop.height) / 2;
180
if (priv->color_shifted)
181
g_object_unref (priv->color_shifted);
182
priv->color_shifted = gdk_pixbuf_copy (priv->pixbuf);
183
shift_colors (priv->color_shifted, -32, -32, -32, 0);
185
if (priv->scale == 0.0) {
188
crop_scale = MIN (gdk_pixbuf_get_width (priv->pixbuf) / priv->base_width * 0.8,
189
gdk_pixbuf_get_height (priv->pixbuf) / priv->base_height * 0.8);
190
priv->crop.width = crop_scale * priv->base_width / scale;
191
priv->crop.height = crop_scale * priv->base_height / scale;
192
priv->crop.x = (gdk_pixbuf_get_width (priv->browse_pixbuf) - priv->crop.width) / 2;
193
priv->crop.y = (gdk_pixbuf_get_height (priv->browse_pixbuf) - priv->crop.height) / 2;
191
area->priv->scale = scale;
192
area->priv->image.x = dest_x;
193
area->priv->image.y = dest_y;
194
area->priv->image.width = dest_width;
195
area->priv->image.height = dest_height;
197
priv->image.x = dest_x;
198
priv->image.y = dest_y;
199
priv->image.width = dest_width;
200
priv->image.height = dest_height;
207
212
crop_to_widget (UmCropArea *area,
208
213
GdkRectangle *crop)
210
crop->x = area->priv->image.x + area->priv->crop.x * area->priv->scale;
211
crop->y = area->priv->image.y + area->priv->crop.y * area->priv->scale;
212
crop->width = area->priv->crop.width * area->priv->scale;
213
crop->height = area->priv->crop.height * area->priv->scale;
215
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (area);
217
crop->x = priv->image.x + priv->crop.x * priv->scale;
218
crop->y = priv->image.y + priv->crop.y * priv->scale;
219
crop->width = priv->crop.width * priv->scale;
220
crop->height = priv->crop.height * priv->scale;
254
261
um_crop_area_draw (GtkWidget *widget,
264
UmCropArea *area = UM_CROP_AREA (widget);
265
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (area);
257
266
GdkRectangle crop;
258
267
gint width, height;
259
UmCropArea *uarea = UM_CROP_AREA (widget);
261
if (uarea->priv->browse_pixbuf == NULL)
269
if (priv->browse_pixbuf == NULL)
264
update_pixbufs (uarea);
266
width = gdk_pixbuf_get_width (uarea->priv->pixbuf);
267
height = gdk_pixbuf_get_height (uarea->priv->pixbuf);
268
crop_to_widget (uarea, &crop);
270
gdk_cairo_set_source_pixbuf (cr, uarea->priv->color_shifted, 0, 0);
272
update_pixbufs (area);
274
width = gdk_pixbuf_get_width (priv->pixbuf);
275
height = gdk_pixbuf_get_height (priv->pixbuf);
276
crop_to_widget (area, &crop);
278
gdk_cairo_set_source_pixbuf (cr, priv->color_shifted, 0, 0);
271
279
cairo_rectangle (cr, 0, 0, width, crop.y);
272
280
cairo_rectangle (cr, 0, crop.y, crop.x, crop.height);
273
281
cairo_rectangle (cr, crop.x + crop.width, crop.y, width - crop.x - crop.width, crop.height);
274
282
cairo_rectangle (cr, 0, crop.y + crop.height, width, height - crop.y - crop.height);
277
gdk_cairo_set_source_pixbuf (cr, uarea->priv->pixbuf, 0, 0);
285
gdk_cairo_set_source_pixbuf (cr, priv->pixbuf, 0, 0);
278
286
cairo_rectangle (cr, crop.x, crop.y, crop.width, crop.height);
281
if (uarea->priv->active_region != OUTSIDE) {
289
if (priv->active_region != OUTSIDE) {
282
290
gint x1, x2, y1, y2;
283
291
cairo_set_source_rgb (cr, 1, 1, 1);
284
292
cairo_set_line_width (cr, 1.0);
539
549
damage.x - 1, damage.y - 1,
540
550
damage.width + 2, damage.height + 2);
542
pb_width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
543
pb_height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
545
x = (event->x - area->priv->image.x) / area->priv->scale;
546
y = (event->y - area->priv->image.y) / area->priv->scale;
548
delta_x = x - area->priv->last_press_x;
549
delta_y = y - area->priv->last_press_y;
550
area->priv->last_press_x = x;
551
area->priv->last_press_y = y;
553
left = area->priv->crop.x;
554
right = area->priv->crop.x + area->priv->crop.width - 1;
555
top = area->priv->crop.y;
556
bottom = area->priv->crop.y + area->priv->crop.height - 1;
552
pb_width = gdk_pixbuf_get_width (priv->browse_pixbuf);
553
pb_height = gdk_pixbuf_get_height (priv->browse_pixbuf);
555
x = (event->x - priv->image.x) / priv->scale;
556
y = (event->y - priv->image.y) / priv->scale;
558
delta_x = x - priv->last_press_x;
559
delta_y = y - priv->last_press_y;
560
priv->last_press_x = x;
561
priv->last_press_y = y;
564
right = priv->crop.x + priv->crop.width - 1;
566
bottom = priv->crop.y + priv->crop.height - 1;
558
568
center_x = (left + right) / 2.0;
559
569
center_y = (top + bottom) / 2.0;
561
switch (area->priv->active_region) {
571
switch (priv->active_region) {
563
573
width = right - left + 1;
564
574
height = bottom - top + 1;
598
if (area->priv->aspect < 0) {
608
if (priv->aspect < 0) {
602
612
else if (y < eval_radial_line (center_x, center_y, left, top, x)) {
604
new_width = (bottom - top) * area->priv->aspect;
614
new_width = (bottom - top) * priv->aspect;
605
615
left = right - new_width;
609
new_height = (right - left) / area->priv->aspect;
619
new_height = (right - left) / priv->aspect;
610
620
top = bottom - new_height;
616
if (area->priv->aspect > 0) {
617
new_width = (bottom - top) * area->priv->aspect;
626
if (priv->aspect > 0) {
627
new_width = (bottom - top) * priv->aspect;
618
628
right = left + new_width;
623
if (area->priv->aspect < 0) {
633
if (priv->aspect < 0) {
627
637
else if (y < eval_radial_line (center_x, center_y, right, top, x)) {
629
new_width = (bottom - top) * area->priv->aspect;
639
new_width = (bottom - top) * priv->aspect;
630
640
right = left + new_width;
634
new_height = (right - left) / area->priv->aspect;
644
new_height = (right - left) / priv->aspect;
635
645
top = bottom - new_height;
641
if (area->priv->aspect > 0) {
642
new_height = (right - left) / area->priv->aspect;
651
if (priv->aspect > 0) {
652
new_height = (right - left) / priv->aspect;
643
653
bottom = top + new_height;
647
657
case BOTTOM_LEFT:
648
if (area->priv->aspect < 0) {
658
if (priv->aspect < 0) {
652
662
else if (y < eval_radial_line (center_x, center_y, left, bottom, x)) {
654
new_height = (right - left) / area->priv->aspect;
664
new_height = (right - left) / priv->aspect;
655
665
bottom = top + new_height;
659
new_width = (bottom - top) * area->priv->aspect;
669
new_width = (bottom - top) * priv->aspect;
660
670
left = right - new_width;
666
if (area->priv->aspect > 0) {
667
new_height = (right - left) / area->priv->aspect;
676
if (priv->aspect > 0) {
677
new_height = (right - left) / priv->aspect;
668
678
bottom = top + new_height;
672
682
case BOTTOM_RIGHT:
673
if (area->priv->aspect < 0) {
683
if (priv->aspect < 0) {
677
687
else if (y < eval_radial_line (center_x, center_y, right, bottom, x)) {
679
new_height = (right - left) / area->priv->aspect;
689
new_height = (right - left) / priv->aspect;
680
690
bottom = top + new_height;
684
new_width = (bottom - top) * area->priv->aspect;
694
new_width = (bottom - top) * priv->aspect;
685
695
right = left + new_width;
691
if (area->priv->aspect > 0) {
692
new_width = (bottom - top) * area->priv->aspect;
701
if (priv->aspect > 0) {
702
new_width = (bottom - top) * priv->aspect;
693
703
right= left + new_width;
754
764
if (left < 0 || top < 0 ||
755
765
right > pb_width || bottom > pb_height ||
756
766
width < min_width || height < min_height) {
757
left = area->priv->crop.x;
758
right = area->priv->crop.x + area->priv->crop.width - 1;
759
top = area->priv->crop.y;
760
bottom = area->priv->crop.y + area->priv->crop.height - 1;
768
right = priv->crop.x + priv->crop.width - 1;
770
bottom = priv->crop.y + priv->crop.height - 1;
764
area->priv->crop.x = left;
765
area->priv->crop.y = top;
766
area->priv->crop.width = right - left + 1;
767
area->priv->crop.height = bottom - top + 1;
776
priv->crop.width = right - left + 1;
777
priv->crop.height = bottom - top + 1;
769
779
crop_to_widget (area, &damage);
770
780
gtk_widget_queue_draw_area (widget,
789
799
GdkEventButton *event)
791
801
UmCropArea *area = UM_CROP_AREA (widget);
802
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (area);
792
803
GdkRectangle crop;
794
if (area->priv->browse_pixbuf == NULL)
805
if (priv->browse_pixbuf == NULL)
797
808
crop_to_widget (area, &crop);
799
area->priv->last_press_x = (event->x - area->priv->image.x) / area->priv->scale;
800
area->priv->last_press_y = (event->y - area->priv->image.y) / area->priv->scale;
801
area->priv->active_region = find_location (&crop, event->x, event->y);
810
priv->last_press_x = (event->x - priv->image.x) / priv->scale;
811
priv->last_press_y = (event->y - priv->image.y) / priv->scale;
812
priv->active_region = find_location (&crop, event->x, event->y);
803
814
gtk_widget_queue_draw_area (widget,
804
815
crop.x - 1, crop.y - 1,
822
833
GdkEventButton *event)
824
835
UmCropArea *area = UM_CROP_AREA (widget);
836
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (area);
825
837
GdkRectangle crop;
827
if (area->priv->browse_pixbuf == NULL)
839
if (priv->browse_pixbuf == NULL)
830
842
crop_to_widget (area, &crop);
832
area->priv->last_press_x = -1;
833
area->priv->last_press_y = -1;
834
area->priv->active_region = OUTSIDE;
844
priv->last_press_x = -1;
845
priv->last_press_y = -1;
846
priv->active_region = OUTSIDE;
836
848
gtk_widget_queue_draw_area (widget,
837
849
crop.x - 1, crop.y - 1,
844
856
um_crop_area_finalize (GObject *object)
846
UmCropArea *area = UM_CROP_AREA (object);
848
if (area->priv->browse_pixbuf) {
849
g_object_unref (area->priv->browse_pixbuf);
850
area->priv->browse_pixbuf = NULL;
852
if (area->priv->pixbuf) {
853
g_object_unref (area->priv->pixbuf);
854
area->priv->pixbuf = NULL;
856
if (area->priv->color_shifted) {
857
g_object_unref (area->priv->color_shifted);
858
area->priv->color_shifted = NULL;
858
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (UM_CROP_AREA (object));
860
if (priv->browse_pixbuf) {
861
g_object_unref (priv->browse_pixbuf);
862
priv->browse_pixbuf = NULL;
865
g_object_unref (priv->pixbuf);
868
if (priv->color_shifted) {
869
g_object_unref (priv->color_shifted);
870
priv->color_shifted = NULL;
873
G_OBJECT_CLASS (um_crop_area_parent_class)->finalize (object);
870
884
widget_class->button_press_event = um_crop_area_button_press_event;
871
885
widget_class->button_release_event = um_crop_area_button_release_event;
872
886
widget_class->motion_notify_event = um_crop_area_motion_notify_event;
874
g_type_class_add_private (klass, sizeof (UmCropAreaPrivate));
878
890
um_crop_area_init (UmCropArea *area)
880
area->priv = (G_TYPE_INSTANCE_GET_PRIVATE ((area), UM_TYPE_CROP_AREA,
892
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (area);
883
894
gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_MASK |
884
895
GDK_BUTTON_PRESS_MASK |
885
896
GDK_BUTTON_RELEASE_MASK);
887
area->priv->scale = 0.0;
888
area->priv->image.x = 0;
889
area->priv->image.y = 0;
890
area->priv->image.width = 0;
891
area->priv->image.height = 0;
892
area->priv->active_region = OUTSIDE;
893
area->priv->base_width = 48;
894
area->priv->base_height = 48;
895
area->priv->aspect = 1;
901
priv->image.width = 0;
902
priv->image.height = 0;
903
priv->active_region = OUTSIDE;
904
priv->base_width = 48;
905
priv->base_height = 48;
921
932
um_crop_area_get_picture (UmCropArea *area)
934
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (area);
923
935
gint width, height;
925
width = gdk_pixbuf_get_width (area->priv->browse_pixbuf);
926
height = gdk_pixbuf_get_height (area->priv->browse_pixbuf);
927
width = MIN (area->priv->crop.width, width - area->priv->crop.x);
928
height = MIN (area->priv->crop.height, height - area->priv->crop.y);
930
return gdk_pixbuf_new_subpixbuf (area->priv->browse_pixbuf,
937
if (priv->browse_pixbuf == NULL)
940
width = gdk_pixbuf_get_width (priv->browse_pixbuf);
941
height = gdk_pixbuf_get_height (priv->browse_pixbuf);
942
width = MIN (priv->crop.width, width - priv->crop.x);
943
height = MIN (priv->crop.height, height - priv->crop.y);
945
return gdk_pixbuf_new_subpixbuf (priv->browse_pixbuf,
945
960
um_crop_area_set_picture (UmCropArea *area,
946
961
GdkPixbuf *pixbuf)
963
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (area);
951
if (area->priv->browse_pixbuf) {
952
g_object_unref (area->priv->browse_pixbuf);
953
area->priv->browse_pixbuf = NULL;
967
if (priv->browse_pixbuf) {
968
g_object_unref (priv->browse_pixbuf);
969
priv->browse_pixbuf = NULL;
956
area->priv->browse_pixbuf = g_object_ref (pixbuf);
972
priv->browse_pixbuf = g_object_ref (pixbuf);
957
973
width = gdk_pixbuf_get_width (pixbuf);
958
974
height = gdk_pixbuf_get_height (pixbuf);
964
area->priv->crop.width = 2 * area->priv->base_width;
965
area->priv->crop.height = 2 * area->priv->base_height;
966
area->priv->crop.x = (width - area->priv->crop.width) / 2;
967
area->priv->crop.y = (height - area->priv->crop.height) / 2;
980
priv->crop.width = 2 * priv->base_width;
981
priv->crop.height = 2 * priv->base_height;
982
priv->crop.x = (width - priv->crop.width) / 2;
983
priv->crop.y = (height - priv->crop.height) / 2;
969
area->priv->scale = 0.0;
970
area->priv->image.x = 0;
971
area->priv->image.y = 0;
972
area->priv->image.width = 0;
973
area->priv->image.height = 0;
988
priv->image.width = 0;
989
priv->image.height = 0;
975
991
gtk_widget_queue_draw (GTK_WIDGET (area));
991
area->priv->base_width = width;
992
area->priv->base_height = height;
1007
UmCropAreaPrivate *priv = um_crop_area_get_instance_private (area);
1008
priv->base_width = width;
1009
priv->base_height = height;
994
if (area->priv->aspect > 0) {
995
area->priv->aspect = area->priv->base_width / (gdouble)area->priv->base_height;
1011
if (priv->aspect > 0) {
1012
priv->aspect = priv->base_width / (gdouble)priv->base_height;