From c7403d38d0dac422a7aed6bd8d8eb2c6e1344f29 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Sat, 30 Jan 2016 19:41:02 +0000 Subject: [PATCH 1/7] Initial scaling work Keep 4:3 proportions where we can. Currently doesn't: * crop image height * middle-align the cropping * work correctly with multiple images --- src/widgets/MediaButton.vala | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/widgets/MediaButton.vala b/src/widgets/MediaButton.vala index 00970abdb..fe0118170 100644 --- a/src/widgets/MediaButton.vala +++ b/src/widgets/MediaButton.vala @@ -156,15 +156,19 @@ private class MediaButton : Gtk.Widget { return; } - width = this.get_allocated_width (); - height = this.get_allocated_height (); - double scale_x = (double)width / this._media.width; - double scale_y = (double)height / this._media.height; - - scale = double.min (double.min (scale_x, scale_y), 1.0); - - width = (int)(this._media.width * scale); - height = (int)(this._media.height * scale); + if (this._media.width > this.get_allocated_width ()) { + width = this.get_allocated_width (); + int maxHeight = (int) Math.floor((width / 4.0) * 3); + height = int.min(this._media.height, maxHeight); + scale = this.get_allocated_width () / (double) this._media.width; + stderr.printf("Scale %s: %d x %d => %d x %d (%f)\n", this._media.url,this._media.width,this._media.height,width,height, scale); + } else { + width = this._media.width; + int maxHeight = (int)Math.floor((this._media.width / 4.0) * 3); + height = int.min(this._media.height, maxHeight); + scale = 1; + stderr.printf("No scale %s: %d x %d => %d x %d (%f)\n", this._media.url,this._media.width,this._media.height,width,height, scale); + } } public override bool draw (Cairo.Context ct) { From 9189b89f6864b4639414e04b5bf8c0e8a96459d2 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Sun, 31 Jan 2016 21:01:01 +0000 Subject: [PATCH 2/7] Fix height calculation (a bit) Images that are greater than app width and portrait are cropped correctly Images narrower than app width but portrait aren't cropped correctly Images that are small enough are okay Images that are wider than app width but not 4:3 tall have spacing --- src/widgets/MediaButton.vala | 44 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/widgets/MediaButton.vala b/src/widgets/MediaButton.vala index fe0118170..6f43454b5 100644 --- a/src/widgets/MediaButton.vala +++ b/src/widgets/MediaButton.vala @@ -156,18 +156,17 @@ private class MediaButton : Gtk.Widget { return; } + int maxHeight = (int) Math.floor((this.get_allocated_width () / 4.0) * 3); + height = int.min(this._media.height, maxHeight); + if (this._media.width > this.get_allocated_width ()) { width = this.get_allocated_width (); - int maxHeight = (int) Math.floor((width / 4.0) * 3); - height = int.min(this._media.height, maxHeight); - scale = this.get_allocated_width () / (double) this._media.width; - stderr.printf("Scale %s: %d x %d => %d x %d (%f)\n", this._media.url,this._media.width,this._media.height,width,height, scale); + scale = width / (double) this._media.width; + stderr.printf("Scale %s: %d x %d => %d x %d (%f) in %d x %d\n", this._media.url,this._media.width,this._media.height,width,height, scale, this.get_allocated_width (), this.get_allocated_height ()); } else { width = this._media.width; - int maxHeight = (int)Math.floor((this._media.width / 4.0) * 3); - height = int.min(this._media.height, maxHeight); scale = 1; - stderr.printf("No scale %s: %d x %d => %d x %d (%f)\n", this._media.url,this._media.width,this._media.height,width,height, scale); + stderr.printf("No scale %s: %d x %d => %d x %d (%f) in %d x %d\n", this._media.url,this._media.width,this._media.height,width,height, scale, this.get_allocated_width (), this.get_allocated_height ()); } } @@ -269,7 +268,7 @@ private class MediaButton : Gtk.Widget { out int natural) { int media_width; int media_height; - + if (this._media == null || this._media.width == -1 || this._media.height == -1) { media_width = MIN_WIDTH; media_height = MAX_HEIGHT; @@ -278,14 +277,14 @@ private class MediaButton : Gtk.Widget { media_height = this._media.height; } - double width_ratio = (double)width / (double) media_width; - int height = int.min (media_height, (int)(media_height * width_ratio)); - if (restrict_height) { - minimum = int.min (media_height, MAX_HEIGHT); - natural = minimum; - } else { - minimum = height; - natural = height; + int maxHeight = (int) Math.floor((int.min(media_width, width) / 4.0) * 3); + int height = int.min(media_height, maxHeight); + minimum = natural = height; + if (this._media != null) { + //FIXME: The calls are height_for_width, width_for_height, height_for_width + //We need to make sure they're consistent, as currently width_for_height returns + //too wide a width! + stderr.printf("get_preferred_height_for_width(%d) for %s (%d x %d): %d\n", width, this._media.url, this._media.width, this._media.height, height); } } @@ -303,10 +302,14 @@ private class MediaButton : Gtk.Widget { media_height = this._media.height; } - double height_ratio = (double)height / (double)media_height; - int width = int.min (media_width, (int)(media_width * height_ratio)); - minimum = int.min (media_width, MIN_WIDTH); - natural = width; + //double height_ratio = (double)height / (double)media_height; + //int width = int.min (media_width, (int)(media_width * height_ratio)); + int maxWidth = (height / 3) * 4; + int width = int.min(media_height, maxWidth); + minimum = natural = width; + if (this._media != null) { + stderr.printf("get_preferred_width_for_height(%d) for %s (%d x %d): %d\n", height, this._media.url, this._media.width, this._media.height, width); + } } public override void get_preferred_width (out int minimum, @@ -320,6 +323,7 @@ private class MediaButton : Gtk.Widget { minimum = int.min (media_width, MIN_WIDTH); natural = media_width; + stderr.printf("get_preferred_width() for %s (%d x %d): %d or %d\n", this._media.url, this._media.width, this._media.height, minimum, natural); } public override void realize () { From c0a996d0ea972c2b43ffbbdc385db62337a2f0a7 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Wed, 3 Feb 2016 20:12:11 +0000 Subject: [PATCH 3/7] Fix calculations for 4:3 ratio max, including putting lines in the right place on hover --- src/widgets/MediaButton.vala | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/widgets/MediaButton.vala b/src/widgets/MediaButton.vala index 6f43454b5..cc1d08b01 100644 --- a/src/widgets/MediaButton.vala +++ b/src/widgets/MediaButton.vala @@ -156,8 +156,10 @@ private class MediaButton : Gtk.Widget { return; } - int maxHeight = (int) Math.floor((this.get_allocated_width () / 4.0) * 3); - height = int.min(this._media.height, maxHeight); + int maxHeightAllocated = (int) Math.floor((this.get_allocated_width () / 4.0) * 3); + int maxHeightFromWidth = (int) Math.floor((this._media.width / 4.0) * 3); + height = int.min(this._media.height, maxHeightAllocated); + height = int.min (height, maxHeightFromWidth); if (this._media.width > this.get_allocated_width ()) { width = this.get_allocated_width (); @@ -278,13 +280,12 @@ private class MediaButton : Gtk.Widget { } int maxHeight = (int) Math.floor((int.min(media_width, width) / 4.0) * 3); - int height = int.min(media_height, maxHeight); + double width_scale = width / (double) media_width; + int scaled_height = (int) Math.floor(media_height * width_scale); + int height = int.min(int.min(media_height, maxHeight), scaled_height); minimum = natural = height; if (this._media != null) { - //FIXME: The calls are height_for_width, width_for_height, height_for_width - //We need to make sure they're consistent, as currently width_for_height returns - //too wide a width! - stderr.printf("get_preferred_height_for_width(%d) for %s (%d x %d): %d\n", width, this._media.url, this._media.width, this._media.height, height); + stderr.printf("get_preferred_height_for_width(%d) for %s (%d x %d): %d (max %d)\n", width, this._media.url, this._media.width, this._media.height, height, maxHeight); } } @@ -304,11 +305,11 @@ private class MediaButton : Gtk.Widget { //double height_ratio = (double)height / (double)media_height; //int width = int.min (media_width, (int)(media_width * height_ratio)); - int maxWidth = (height / 3) * 4; + int maxWidth = (int) Math.floor((height / 3.0) * 4); int width = int.min(media_height, maxWidth); minimum = natural = width; if (this._media != null) { - stderr.printf("get_preferred_width_for_height(%d) for %s (%d x %d): %d\n", height, this._media.url, this._media.width, this._media.height, width); + stderr.printf("get_preferred_width_for_height(%d) for %s (%d x %d): %d (max %d)\n", height, this._media.url, this._media.width, this._media.height, width, maxWidth); } } From 7e08070fc63664f915147cabd93000fcc97670a5 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Sun, 7 Feb 2016 21:06:11 +0000 Subject: [PATCH 4/7] Simplify scaling and fix vertical alignment We now show the middle of the image Height is max 4:3 proportions of the widget --- src/widgets/MediaButton.vala | 46 +++++++++++++++--------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/src/widgets/MediaButton.vala b/src/widgets/MediaButton.vala index cc1d08b01..08f3e6d01 100644 --- a/src/widgets/MediaButton.vala +++ b/src/widgets/MediaButton.vala @@ -156,19 +156,14 @@ private class MediaButton : Gtk.Widget { return; } - int maxHeightAllocated = (int) Math.floor((this.get_allocated_width () / 4.0) * 3); - int maxHeightFromWidth = (int) Math.floor((this._media.width / 4.0) * 3); - height = int.min(this._media.height, maxHeightAllocated); - height = int.min (height, maxHeightFromWidth); - - if (this._media.width > this.get_allocated_width ()) { - width = this.get_allocated_width (); - scale = width / (double) this._media.width; - stderr.printf("Scale %s: %d x %d => %d x %d (%f) in %d x %d\n", this._media.url,this._media.width,this._media.height,width,height, scale, this.get_allocated_width (), this.get_allocated_height ()); - } else { - width = this._media.width; + width = int.min (this._media.width, this.get_allocated_width ()); + scale = this.get_allocated_width () / (double) this._media.width; + + if (scale > 1) { + height = int.min (this._media.height, (int) Math.floor((this.get_allocated_width () / 4.0) * 3)); scale = 1; - stderr.printf("No scale %s: %d x %d => %d x %d (%f) in %d x %d\n", this._media.url,this._media.width,this._media.height,width,height, scale, this.get_allocated_width (), this.get_allocated_height ()); + } else { + height = (int) Math.floor (double.min (this._media.height * scale, (this._media.width * scale / 4.0) * 3)); } } @@ -190,7 +185,7 @@ private class MediaButton : Gtk.Widget { ct.save (); ct.rectangle (0, 0, widget_width, widget_height); ct.scale (scale, scale); - ct.set_source_surface (media.surface, draw_x / scale, 0); + ct.set_source_surface (media.surface, draw_x / scale, -(((media.height * scale) - draw_height) / 2) / scale); ct.paint_with_alpha (this.media_alpha); ct.restore (); ct.new_path (); @@ -279,14 +274,17 @@ private class MediaButton : Gtk.Widget { media_height = this._media.height; } - int maxHeight = (int) Math.floor((int.min(media_width, width) / 4.0) * 3); - double width_scale = width / (double) media_width; - int scaled_height = (int) Math.floor(media_height * width_scale); - int height = int.min(int.min(media_height, maxHeight), scaled_height); - minimum = natural = height; - if (this._media != null) { - stderr.printf("get_preferred_height_for_width(%d) for %s (%d x %d): %d (max %d)\n", width, this._media.url, this._media.width, this._media.height, height, maxHeight); + double scale = width / (double) media_width; + + int height = 0; + + if (scale > 1) { + height = int.min (media_height, (int) Math.floor((width / 4.0) * 3)); + } else { + height = (int) Math.floor (double.min (media_height * scale, (media_width * scale / 4.0) * 3)); } + + minimum = natural = height; } public override void get_preferred_width_for_height (int height, @@ -303,14 +301,9 @@ private class MediaButton : Gtk.Widget { media_height = this._media.height; } - //double height_ratio = (double)height / (double)media_height; - //int width = int.min (media_width, (int)(media_width * height_ratio)); int maxWidth = (int) Math.floor((height / 3.0) * 4); - int width = int.min(media_height, maxWidth); + int width = int.min(media_width, maxWidth); minimum = natural = width; - if (this._media != null) { - stderr.printf("get_preferred_width_for_height(%d) for %s (%d x %d): %d (max %d)\n", height, this._media.url, this._media.width, this._media.height, width, maxWidth); - } } public override void get_preferred_width (out int minimum, @@ -324,7 +317,6 @@ private class MediaButton : Gtk.Widget { minimum = int.min (media_width, MIN_WIDTH); natural = media_width; - stderr.printf("get_preferred_width() for %s (%d x %d): %d or %d\n", this._media.url, this._media.width, this._media.height, minimum, natural); } public override void realize () { From 9a73b04d8f8a0b86bc8052c39d7a4a9982ab062f Mon Sep 17 00:00:00 2001 From: IBBoard Date: Mon, 8 Feb 2016 20:01:54 +0000 Subject: [PATCH 5/7] Tidy up code before pull request * Fix code formatting * Improve readability by extracting variable * Match change in 2b7d76 --- src/widgets/MediaButton.vala | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/widgets/MediaButton.vala b/src/widgets/MediaButton.vala index 08f3e6d01..5845ae709 100644 --- a/src/widgets/MediaButton.vala +++ b/src/widgets/MediaButton.vala @@ -160,7 +160,7 @@ private class MediaButton : Gtk.Widget { scale = this.get_allocated_width () / (double) this._media.width; if (scale > 1) { - height = int.min (this._media.height, (int) Math.floor((this.get_allocated_width () / 4.0) * 3)); + height = int.min (this._media.height, (int) Math.floor ((this.get_allocated_width () / 4.0) * 3)); scale = 1; } else { height = (int) Math.floor (double.min (this._media.height * scale, (this._media.width * scale / 4.0) * 3)); @@ -185,7 +185,8 @@ private class MediaButton : Gtk.Widget { ct.save (); ct.rectangle (0, 0, widget_width, widget_height); ct.scale (scale, scale); - ct.set_source_surface (media.surface, draw_x / scale, -(((media.height * scale) - draw_height) / 2) / scale); + double draw_y = -(((media.height * scale) - draw_height) / 2); + ct.set_source_surface (media.surface, draw_x / scale, draw_y / scale); ct.paint_with_alpha (this.media_alpha); ct.restore (); ct.new_path (); @@ -279,7 +280,7 @@ private class MediaButton : Gtk.Widget { int height = 0; if (scale > 1) { - height = int.min (media_height, (int) Math.floor((width / 4.0) * 3)); + height = int.min (media_height, (int) Math.floor ((width / 4.0) * 3)); } else { height = (int) Math.floor (double.min (media_height * scale, (media_width * scale / 4.0) * 3)); } @@ -301,9 +302,10 @@ private class MediaButton : Gtk.Widget { media_height = this._media.height; } - int maxWidth = (int) Math.floor((height / 3.0) * 4); - int width = int.min(media_width, maxWidth); - minimum = natural = width; + int max_width = (int) Math.floor ((height / 3.0) * 4); + int width = int.min (media_width, max_width); + minimum = int.min (media_width, MIN_WIDTH); + natural = width; } public override void get_preferred_width (out int minimum, From 03e2c46e40ef42eaa26fa2d9121bf0d11d9ad614 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Sat, 13 Aug 2016 19:51:51 +0100 Subject: [PATCH 6/7] Fix overflow in compose dialog This isn't perfect, but it is a best-compromise for GTK's size allocation --- src/widgets/MediaButton.vala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/MediaButton.vala b/src/widgets/MediaButton.vala index 5845ae709..f0e8c4ae1 100644 --- a/src/widgets/MediaButton.vala +++ b/src/widgets/MediaButton.vala @@ -279,7 +279,9 @@ private class MediaButton : Gtk.Widget { int height = 0; - if (scale > 1) { + if (restrict_height) { + height = int.min (media_height, MAX_HEIGHT); + } else if (scale > 1) { height = int.min (media_height, (int) Math.floor ((width / 4.0) * 3)); } else { height = (int) Math.floor (double.min (media_height * scale, (media_width * scale / 4.0) * 3)); From 0c215bf51b918df309c9cc4b3061b8f060de54d4 Mon Sep 17 00:00:00 2001 From: IBBoard Date: Thu, 25 Jul 2019 20:27:40 +0100 Subject: [PATCH 7/7] Add overlay to indicate when images have been cropped This only happens for VERY tall images (limits are large enough to allow vertical smartphone photos uncropped) --- src/widgets/MediaButton.vala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/widgets/MediaButton.vala b/src/widgets/MediaButton.vala index f0e8c4ae1..ed05af632 100644 --- a/src/widgets/MediaButton.vala +++ b/src/widgets/MediaButton.vala @@ -191,6 +191,21 @@ private class MediaButton : Gtk.Widget { ct.restore (); ct.new_path (); + /* + * If image got moved off the top, we cropped it. Indicate that. + * Currently trying a gradient overlay top and bottom + */ + if (draw_y < 0) { + Cairo.Pattern pattern = new Cairo.Pattern.linear (0.0, 0.0, 0, widget_height); + pattern.add_color_stop_rgba (0.01, 0.3, 0.3, 0.3, 1); + pattern.add_color_stop_rgba (0.1, 0.7, 0.7, 0.7, 0); + pattern.add_color_stop_rgba (0.9, 0.7, 0.7, 0.7, 0); + pattern.add_color_stop_rgba (0.99, 0.3, 0.3, 0.3, 1); + ct.rectangle (0, 0, widget_width, widget_height); + ct.set_source (pattern); + ct.fill (); + } + /* Draw play indicator */ if (_media.is_video ()) { int x = (widget_width / 2) - (PLAY_ICON_SIZE / 2);