aac86dc668db9e47c1a9df65f34d80e99cf50de3
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index cfb34a9..afcd0d0 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -2073,6 +2073,7 @@ gtk_label_get_type G_GNUC_CONST
 gtk_label_get_use_markup
 gtk_label_get_use_underline
 gtk_label_get_width_chars
+gtk_label_get_full_size
 gtk_label_new
 gtk_label_new_with_mnemonic
 gtk_label_select_region
@@ -2095,6 +2096,7 @@ gtk_label_set_text_with_mnemonic
 gtk_label_set_use_markup
 gtk_label_set_use_underline
 gtk_label_set_width_chars
+gtk_label_set_full_size
 #endif
 #endif
 
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 09fcb85..a31cb1e 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -48,11 +48,16 @@
 
 #define GTK_LABEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_LABEL, GtkLabelPrivate))
 
+#ifndef INFINITY /* Why again don't we use C99? */
+#define INFINITY HUGE_VAL
+#endif
+
 typedef struct
 {
   gint wrap_width;
   gint width_chars;
   gint max_width_chars;
+  gboolean full_size;
 }
 GtkLabelPrivate;
 
@@ -95,7 +100,8 @@ enum {
   PROP_WIDTH_CHARS,
   PROP_SINGLE_LINE_MODE,
   PROP_ANGLE,
-  PROP_MAX_WIDTH_CHARS
+  PROP_MAX_WIDTH_CHARS,
+  PROP_FULL_SIZE
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -512,6 +518,23 @@ gtk_label_class_init (GtkLabelClass *class)
                                                      G_MAXINT,
                                                      -1,
                                                      GTK_PARAM_READWRITE));
+
+  /**
+   * GtkLabel:full-size:
+   *
+   * Use the entire space the widget got assigned for text wrapping. Overrides
+   * any #GtkLabel:width-chars, #GtkLabel:max-width-chars and screen size based
+   * constraints. Requires #GtkLabel:angle to be 0°, 90°, 180° or 270°.
+   *
+   * Since: 2.14
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FULL_SIZE,
+                                   g_param_spec_boolean ("full-size",
+							 P_("Full size"),
+							 P_("Use the entire size of the widget to wrap text"),
+                                                        FALSE,
+                                                        GTK_PARAM_READWRITE));
   /*
    * Key bindings
    */
@@ -688,6 +711,9 @@ gtk_label_set_property (GObject      *object,
     case PROP_MAX_WIDTH_CHARS:
       gtk_label_set_max_width_chars (label, g_value_get_int (value));
       break;
+    case PROP_FULL_SIZE:
+      gtk_label_set_full_size (label, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -771,6 +797,9 @@ gtk_label_get_property (GObject     *object,
     case PROP_MAX_WIDTH_CHARS:
       g_value_set_int (value, gtk_label_get_max_width_chars (label));
       break;
+    case PROP_FULL_SIZE:
+      g_value_set_int (value, gtk_label_get_full_size (label));
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -2005,14 +2034,14 @@ gtk_label_ensure_layout (GtkLabel *label)
       PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */
       gdouble angle = gtk_label_get_angle (label);
 
-      if (angle != 0.0 && !label->wrap && !label->ellipsize && !label->select_info)
+      if (angle != 0.0 && !label->select_info)
 	{
+          PangoMatrix matrix = PANGO_MATRIX_INIT;
+
 	  /* We rotate the standard singleton PangoContext for the widget,
 	   * depending on the fact that it's meant pretty much exclusively
 	   * for our use.
 	   */
-	  PangoMatrix matrix = PANGO_MATRIX_INIT;
-	  
 	  pango_matrix_rotate (&matrix, angle);
 
 	  pango_context_set_matrix (gtk_widget_get_pango_context (widget), &matrix);
@@ -2056,8 +2085,8 @@ gtk_label_ensure_layout (GtkLabel *label)
       pango_layout_set_single_paragraph_mode (label->layout, label->single_line_mode);
 
       if (label->ellipsize)
-	pango_layout_set_width (label->layout, 
-				widget->allocation.width * PANGO_SCALE);
+        pango_layout_set_width (label->layout,
+                                widget->allocation.width * PANGO_SCALE);
       else if (label->wrap)
 	{
 	  GtkWidgetAuxInfo *aux_info;
@@ -2084,14 +2113,14 @@ gtk_label_ensure_layout (GtkLabel *label)
 
 	      wrap_width = get_label_wrap_width (label);
 	      width = MIN (width, wrap_width);
-	      width = MIN (width,
+ 	      width = MIN (width,
 			   PANGO_SCALE * (gdk_screen_get_width (screen) + 1) / 2);
-	      
+
 	      pango_layout_set_width (label->layout, width);
 	      pango_layout_get_extents (label->layout, NULL, &logical_rect);
 	      width = logical_rect.width;
 	      height = logical_rect.height;
-	      
+
 	      /* Unfortunately, the above may leave us with a very unbalanced looking paragraph,
 	       * so we try short search for a narrower width that leaves us with the same height
 	       */
@@ -2138,8 +2167,8 @@ gtk_label_size_request (GtkWidget      *widget,
 {
   GtkLabel *label;
   GtkLabelPrivate *priv;
-  gint width, height;
   PangoRectangle logical_rect;
+  PangoRectangle required_rect;
   GtkWidgetAuxInfo *aux_info;
   
   g_return_if_fail (GTK_IS_LABEL (widget));
@@ -2166,39 +2195,21 @@ gtk_label_size_request (GtkWidget      *widget,
 
   gtk_label_ensure_layout (label);
 
-  width = label->misc.xpad * 2;
-  height = label->misc.ypad * 2;
-
   aux_info = _gtk_widget_get_aux_info (widget, FALSE);
 
-  if (label->have_transform)
-    {
-      PangoRectangle rect;
-      PangoContext *context = pango_layout_get_context (label->layout);
-      const PangoMatrix *matrix = pango_context_get_matrix (context);
-
-      pango_layout_get_extents (label->layout, NULL, &rect);
-      pango_matrix_transform_rectangle (matrix, &rect);
-      pango_extents_to_pixels (&rect, NULL);
-      
-      requisition->width = width + rect.width;
-      requisition->height = height + rect.height;
-
-      return;
-    }
-  else
-    pango_layout_get_extents (label->layout, NULL, &logical_rect);
+  pango_layout_get_extents (label->layout, NULL, &logical_rect);
+  required_rect.x = required_rect.y = 0;
 
   if ((label->wrap || label->ellipsize || 
        priv->width_chars > 0 || priv->max_width_chars > 0) && 
       aux_info && aux_info->width > 0)
-    width += aux_info->width;
+    required_rect.width = aux_info->width;
   else if (label->ellipsize || priv->width_chars > 0 || priv->max_width_chars > 0)
     {
-      width += PANGO_PIXELS (get_label_char_width (label));
+      required_rect.width = PANGO_PIXELS (get_label_char_width (label));
     }
   else
-    width += PANGO_PIXELS (logical_rect.width);
+    required_rect.width = PANGO_PIXELS (logical_rect.width);
 
   if (label->single_line_mode)
     {
@@ -2214,39 +2225,102 @@ gtk_label_size_request (GtkWidget      *widget,
       descent = pango_font_metrics_get_descent (metrics);
       pango_font_metrics_unref (metrics);
     
-      height += PANGO_PIXELS (ascent + descent);
+      required_rect.height = PANGO_PIXELS (ascent + descent);
     }
   else
-    height += PANGO_PIXELS (logical_rect.height);
+    required_rect.height = PANGO_PIXELS (logical_rect.height);
 
-  requisition->width = width;
-  requisition->height = height;
+  if (label->have_transform)
+    {
+      PangoContext *context = pango_layout_get_context (label->layout);
+      const PangoMatrix *matrix = pango_context_get_matrix (context);
+      pango_matrix_transform_pixel_rectangle (matrix, &required_rect);
+    }
+
+  requisition->width = required_rect.width + label->misc.xpad * 2;
+  requisition->height = required_rect.height + label->misc.ypad * 2;
 }
 
 static void
 gtk_label_size_allocate (GtkWidget     *widget,
                          GtkAllocation *allocation)
 {
-  GtkLabel *label;
-
-  label = GTK_LABEL (widget);
+  GtkLabel *label = GTK_LABEL (widget);
 
   (* GTK_WIDGET_CLASS (gtk_label_parent_class)->size_allocate) (widget, allocation);
 
-  if (label->ellipsize)
+  if (label->ellipsize || GTK_LABEL_GET_PRIVATE (label)->full_size)
     {
       if (label->layout)
 	{
-	  gint width;
 	  PangoRectangle logical;
+          PangoRectangle bounds;
 
-	  width = (allocation->width - label->misc.xpad * 2) * PANGO_SCALE;
+          bounds.x = bounds.y = 0;
+          bounds.width = allocation->width - label->misc.xpad * 2;
+          bounds.height = allocation->height - label->misc.ypad * 2;
 
 	  pango_layout_set_width (label->layout, -1);
-	  pango_layout_get_extents (label->layout, NULL, &logical);
+	  pango_layout_get_pixel_extents (label->layout, NULL, &logical);
+
+          if (label->have_transform)
+            {
+              PangoContext *context = gtk_widget_get_pango_context (widget);
+              const PangoMatrix *matrix = pango_context_get_matrix (context);
+
+              const gdouble dx = matrix->xx; /* cos (M_PI * angle / 180) */
+              const gdouble dy = matrix->xy; /* sin (M_PI * angle / 180) */
+
+              if (fabs (dy) < 0.01)
+                {
+                  if (logical.width > bounds.width)
+	            pango_layout_set_width (label->layout, bounds.width * PANGO_SCALE);
+                }
+              else if (fabs (dx) < 0.01)
+                {
+                  if (logical.width > bounds.height)
+	            pango_layout_set_width (label->layout, bounds.height * PANGO_SCALE);
+                }
+              else
+                {
+                  gdouble x0, y0, x1, y1, length;
+                  gboolean vertical;
+                  gint cy;
+
+                  x0 = bounds.width / 2;
+                  y0 = dx ? x0 * dy / dx : dy * INFINITY;
+                  vertical = fabs (y0) > bounds.height / 2;
 
-	  if (logical.width > width)
-	    pango_layout_set_width (label->layout, width);
+                  if (vertical)
+                    {
+                      y0 = bounds.height/2;
+                      x0 = dy ? y0 * dx / dy : dx * INFINITY;
+                    }
+
+                  length = 2 * sqrt (x0 * x0 + y0 * y0);
+                  pango_layout_set_width (label->layout, rint (length * PANGO_SCALE));
+                  pango_layout_get_pixel_size (label->layout, NULL, &cy);
+
+                  x1 = +dy * cy/2;
+                  y1 = -dx * cy/2;
+
+                  if (vertical)
+                    {
+                      y0 = bounds.height/2 + y1 - y0;
+                      x0 = -y0 * dx/dy;
+                    }
+                  else
+                    {
+                      x0 = bounds.width/2 + x1 - x0;
+                      y0 = -x0 * dy/dx;
+                    }
+
+                  length = length - sqrt (x0 * x0 + y0 * y0) * 2;
+                  pango_layout_set_width (label->layout, rint (length * PANGO_SCALE));
+                }
+            }
+	  else if (logical.width > bounds.width)
+	    pango_layout_set_width (label->layout, bounds.width * PANGO_SCALE);
 	}
     }
 
@@ -2327,7 +2401,9 @@ get_layout_location (GtkLabel  *label,
   GtkWidget *widget; 
   GtkLabelPrivate *priv;
   gfloat xalign;
-  gint req_width, x, y;
+  gint req_width;
+  gint req_height;
+  gint x, y;
   
   misc = GTK_MISC (label);
   widget = GTK_WIDGET (label);
@@ -2338,33 +2414,48 @@ get_layout_location (GtkLabel  *label,
   else
     xalign = 1.0 - misc->xalign;
 
-  if (label->ellipsize || priv->width_chars > 0)
+  if (label->ellipsize || priv->width_chars > 0 || GTK_LABEL_GET_PRIVATE (label)->full_size)
     {
       int width;
       PangoRectangle logical;
 
       width = pango_layout_get_width (label->layout);
-      pango_layout_get_pixel_extents (label->layout, NULL, &logical);
+      pango_layout_get_extents (label->layout, NULL, &logical);
+
+      if (label->have_transform)
+        {
+          PangoContext *context = gtk_widget_get_pango_context (widget);
+          const PangoMatrix *matrix = pango_context_get_matrix (context);
+          pango_matrix_transform_rectangle (matrix, &logical);
+        }
+
+      pango_extents_to_pixels (&logical, NULL);
 
       req_width = logical.width;
+      req_height = logical.height;
+
       if (width != -1)
 	req_width = MIN(PANGO_PIXELS (width), req_width);
+
       req_width += 2 * misc->xpad;
+      req_height += 2 * misc->ypad;
     }
   else
-    req_width = widget->requisition.width;
+    {
+      req_width = widget->requisition.width;
+      req_height = widget->requisition.height;
+    }
 
   x = floor (widget->allocation.x + (gint)misc->xpad +
-	      xalign * (widget->allocation.width - req_width));
+	     xalign * (widget->allocation.width - req_width));
 
   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
     x = MAX (x, widget->allocation.x + misc->xpad);
   else
     x = MIN (x, widget->allocation.x + widget->allocation.width - misc->xpad);
 
-  y = floor (widget->allocation.y + (gint)misc->ypad 
-             + MAX (((widget->allocation.height - widget->requisition.height) * misc->yalign),
-	     0));
+  y = floor (widget->allocation.y + (gint)misc->ypad +
+  	     misc->yalign * (widget->allocation.height - req_height));
 
   if (xp)
     *xp = x;
@@ -3676,6 +3767,32 @@ gtk_label_set_use_underline (GtkLabel *label,
     gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
 }
 
+gboolean
+gtk_label_get_full_size (GtkLabel *label)
+{
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+  return GTK_LABEL_GET_PRIVATE (label)->full_size;
+}
+
+void
+gtk_label_set_full_size (GtkLabel *label,
+			 gboolean  setting)
+{
+  GtkLabelPrivate *priv;
+
+  g_return_if_fail (GTK_IS_LABEL (label));
+  priv = GTK_LABEL_GET_PRIVATE (label);
+
+  if (priv->full_size != setting)
+    {
+      priv->full_size = setting;
+
+      g_object_notify (G_OBJECT (label), "full-size");
+      gtk_label_invalidate_wrap_width (label);
+      gtk_widget_queue_resize (GTK_WIDGET (label));
+    }
+}
+
 /**
  * gtk_label_get_use_underline:
  * @label: a #GtkLabel
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
index 5656ebb..ac90f1d 100644
--- a/gtk/gtklabel.h
+++ b/gtk/gtklabel.h
@@ -119,6 +119,9 @@ gboolean              gtk_label_get_use_markup    (GtkLabel      *label);
 void                  gtk_label_set_use_underline (GtkLabel      *label,
 						   gboolean       setting);
 gboolean              gtk_label_get_use_underline (GtkLabel      *label);
+void                  gtk_label_set_full_size     (GtkLabel      *label,
+						   gboolean       setting);
+gboolean              gtk_label_get_full_size     (GtkLabel      *label);
 
 void     gtk_label_set_markup_with_mnemonic       (GtkLabel         *label,
 						   const gchar      *str);
