]> git.sur5r.net Git - glabels/blobdiff - src/label-text.c
Updated French doc translation
[glabels] / src / label-text.c
index aef20b8c565b641e7e5941b7020fafaf8ea4c4aa..d9146c420aaa35c413ccd1c0dd5c01884a2ebc2b 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "label-text.h"
 
+#include <glib/gi18n.h>
 #include <glib.h>
 #include <pango/pango.h>
 #include <math.h>
 
 #define FONT_SCALE (72.0/96.0)
 
+#define HANDLE_OUTLINE_RGBA_ARGS   0.5,   0.5,   0.5,   0.75
+#define HANDLE_OUTLINE_WIDTH_PIXELS   2.0
+
+#define SELECTION_SLOP_PIXELS 4.0
+
 
 /*========================================================*/
 /* Private types.                                         */
 /*========================================================*/
 
 struct _glLabelTextPrivate {
-       GtkTextTagTable *tag_table;
-       GtkTextBuffer   *buffer;
+
+        GtkTextTagTable *tag_table;
+        GtkTextBuffer   *buffer;
 
        gchar           *font_family;
        gdouble          font_size;
@@ -60,6 +67,8 @@ struct _glLabelTextPrivate {
         gboolean         size_changed;
         gdouble          w;
         gdouble          h;
+
+        gboolean         checkpoint_flag;
 };
 
 
@@ -77,6 +86,9 @@ static void gl_label_text_finalize      (GObject          *object);
 static void copy                        (glLabelObject    *dst_object,
                                         glLabelObject    *src_object);
 
+static void buffer_begin_user_action_cb (GtkTextBuffer    *textbuffer,
+                                         glLabelText      *ltext);
+
 static void buffer_changed_cb           (GtkTextBuffer    *textbuffer,
                                         glLabelText      *ltext);
 
@@ -85,25 +97,32 @@ static void get_size                    (glLabelObject    *object,
                                         gdouble          *h);
 
 static void set_font_family             (glLabelObject    *object,
-                                        const gchar      *font_family);
+                                        const gchar      *font_family,
+                                         gboolean          checkpoint);
 
 static void set_font_size               (glLabelObject    *object,
-                                        gdouble           font_size);
+                                        gdouble           font_size,
+                                         gboolean          checkpoint);
 
 static void set_font_weight             (glLabelObject    *object,
-                                        PangoWeight       font_weight);
+                                        PangoWeight       font_weight,
+                                         gboolean          checkpoint);
 
 static void set_font_italic_flag        (glLabelObject    *object,
-                                        gboolean          font_italic_flag);
+                                        gboolean          font_italic_flag,
+                                         gboolean          checkpoint);
 
 static void set_text_alignment          (glLabelObject    *object,
-                                        PangoAlignment    text_alignment);
+                                        PangoAlignment    text_alignment,
+                                         gboolean          checkpoint);
 
 static void set_text_line_spacing       (glLabelObject    *object,
-                                        gdouble           text_line_spacing);
+                                        gdouble           text_line_spacing,
+                                         gboolean          checkpoint);
 
 static void set_text_color              (glLabelObject    *object,
-                                        glColorNode      *text_color_node);
+                                        glColorNode      *text_color_node,
+                                         gboolean          checkpoint);
 
 static gchar          *get_font_family             (glLabelObject    *object);
 
@@ -119,6 +138,11 @@ static gdouble         get_text_line_spacing       (glLabelObject    *object);
 
 static glColorNode*    get_text_color              (glLabelObject    *object);
 
+static void            set_text_path               (glLabelText      *this,
+                                                    cairo_t          *cr,
+                                                    gboolean          screen_flag,
+                                                    glMergeRecord    *record);
+
 static void            draw_object                 (glLabelObject    *object,
                                                     cairo_t          *cr,
                                                     gboolean          screen_flag,
@@ -148,11 +172,14 @@ static gboolean        object_at                   (glLabelObject    *object,
                                                     gdouble           x_pixels,
                                                     gdouble           y_pixels);
 
+static void            draw_handles                (glLabelObject    *object,
+                                                    cairo_t          *cr);
+
 
 /*****************************************************************************/
 /* Object infrastructure.                                                    */
 /*****************************************************************************/
-G_DEFINE_TYPE (glLabelText, gl_label_text, GL_TYPE_LABEL_OBJECT);
+G_DEFINE_TYPE (glLabelText, gl_label_text, GL_TYPE_LABEL_OBJECT)
 
 
 /*****************************************************************************/
@@ -187,6 +214,7 @@ gl_label_text_class_init (glLabelTextClass *class)
         label_object_class->draw_object           = draw_object;
         label_object_class->draw_shadow           = draw_shadow;
         label_object_class->object_at             = object_at;
+        label_object_class->draw_handles          = draw_handles;
 
        object_class->finalize = gl_label_text_finalize;
 }
@@ -205,6 +233,10 @@ gl_label_text_init (glLabelText *ltext)
 
         ltext->priv->size_changed      = TRUE;
 
+        ltext->priv->checkpoint_flag   = TRUE;
+
+       g_signal_connect (G_OBJECT(ltext->priv->buffer), "begin-user-action",
+                         G_CALLBACK(buffer_begin_user_action_cb), ltext);
        g_signal_connect (G_OBJECT(ltext->priv->buffer), "changed",
                          G_CALLBACK(buffer_changed_cb), ltext);
 }
@@ -234,7 +266,8 @@ gl_label_text_finalize (GObject *object)
 /** New Object Generator.                                                    */
 /*****************************************************************************/
 GObject *
-gl_label_text_new (glLabel *label)
+gl_label_text_new (glLabel *label,
+                   gboolean checkpoint)
 {
        glLabelText   *ltext;
         glColorNode   *color_node;
@@ -243,7 +276,10 @@ gl_label_text_new (glLabel *label)
 
         if (label != NULL)
         {
-                gl_label_object_set_parent (GL_LABEL_OBJECT(ltext), label);
+                if ( checkpoint )
+                {
+                        gl_label_checkpoint (label, _("Create text object"));
+                }
 
                 color_node = gl_color_node_new_default ();
 
@@ -256,6 +292,9 @@ gl_label_text_new (glLabel *label)
                 ltext->priv->align            = gl_label_get_default_text_alignment (label);
                ltext->priv->color_node       = color_node;       
                 ltext->priv->line_spacing     = gl_label_get_default_text_line_spacing (label);
+
+                gl_label_add_object (label, GL_LABEL_OBJECT (ltext));
+                gl_label_object_set_parent (GL_LABEL_OBJECT (ltext), label);
         }
 
        return G_OBJECT (ltext);
@@ -281,13 +320,13 @@ copy (glLabelObject *dst_object,
 
        lines = gl_label_text_get_lines (ltext);
        text_color_node = get_text_color (src_object);
-       gl_label_text_set_lines (new_ltext, lines);
+       gl_label_text_set_lines (new_ltext, lines, FALSE);
 
        new_ltext->priv->font_family      = g_strdup (ltext->priv->font_family);
        new_ltext->priv->font_size        = ltext->priv->font_size;
        new_ltext->priv->font_weight      = ltext->priv->font_weight;
        new_ltext->priv->font_italic_flag = ltext->priv->font_italic_flag;
-       set_text_color (dst_object, text_color_node);
+       set_text_color (dst_object, text_color_node, FALSE);
        new_ltext->priv->align            = ltext->priv->align;
        new_ltext->priv->line_spacing     = ltext->priv->line_spacing;
        new_ltext->priv->auto_shrink      = ltext->priv->auto_shrink;
@@ -308,7 +347,8 @@ copy (glLabelObject *dst_object,
 /*****************************************************************************/
 void
 gl_label_text_set_lines (glLabelText *ltext,
-                        GList       *lines)
+                        GList       *lines,
+                         gboolean     checkpoint)
 {
        gchar *text;
 
@@ -316,28 +356,37 @@ gl_label_text_set_lines (glLabelText *ltext,
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
+        ltext->priv->checkpoint_flag = checkpoint;
+
        text = gl_text_node_lines_expand (lines, NULL);
        gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
        g_free (text);
 
         ltext->priv->size_changed = TRUE;
 
+        ltext->priv->checkpoint_flag = TRUE;
+
        gl_debug (DEBUG_LABEL, "END");
 }
 
 
 void
 gl_label_text_set_text (glLabelText *ltext,
-                        const gchar *text)
+                        const gchar *text,
+                        gboolean     checkpoint)
 {
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
+        ltext->priv->checkpoint_flag = checkpoint;
+
        gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
 
         ltext->priv->size_changed = TRUE;
 
+        ltext->priv->checkpoint_flag = TRUE;
+
        gl_debug (DEBUG_LABEL, "END");
 }
 
@@ -389,6 +438,23 @@ gl_label_text_get_text (glLabelText      *ltext)
 }
 
 
+/*****************************************************************************/
+/* Text buffer "changed" callback.                                           */
+/*****************************************************************************/
+static void
+buffer_begin_user_action_cb (GtkTextBuffer *textbuffer,
+                             glLabelText   *ltext)
+{
+        glLabel *label;
+
+        if ( ltext->priv->checkpoint_flag )
+        {
+                label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                gl_label_checkpoint (label, _("Typing"));
+        }
+}
+
+
 /*****************************************************************************/
 /* Text buffer "changed" callback.                                           */
 /*****************************************************************************/
@@ -491,10 +557,12 @@ get_size (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_font_family (glLabelObject *object,
-                const gchar   *font_family)
+                const gchar   *font_family,
+                 gboolean       checkpoint)
 {
        glLabelText    *ltext = (glLabelText *)object;
        gchar          *good_font_family;
+        glLabel        *label;
 
        gl_debug (DEBUG_LABEL, "START");
 
@@ -511,6 +579,13 @@ set_font_family (glLabelObject *object,
                }
                g_free (ltext->priv->font_family);
        }
+
+        if ( checkpoint )
+        {
+                label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                gl_label_checkpoint (label, _("Font family"));
+        }
+
        ltext->priv->font_family = g_strdup (good_font_family);
        g_free (good_font_family);
 
@@ -531,21 +606,28 @@ set_font_family (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_font_size (glLabelObject *object,
-              gdouble        font_size)
+              gdouble        font_size,
+               gboolean       checkpoint)
 {
        glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-       if (ltext->priv->font_size != font_size) {
+       if (ltext->priv->font_size != font_size)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Font size"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
                ltext->priv->font_size = font_size;
                gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -557,21 +639,28 @@ set_font_size (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_font_weight (glLabelObject   *object,
-                PangoWeight      font_weight)
+                PangoWeight      font_weight,
+                 gboolean         checkpoint)
 {
        glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-       if (ltext->priv->font_weight != font_weight) {
+       if (ltext->priv->font_weight != font_weight)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Font weight"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
                ltext->priv->font_weight = font_weight;
                gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -583,21 +672,28 @@ set_font_weight (glLabelObject   *object,
 /*****************************************************************************/
 static void
 set_font_italic_flag (glLabelObject *object,
-                     gboolean       font_italic_flag)
+                     gboolean       font_italic_flag,
+                      gboolean       checkpoint)
 {
        glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-       if (ltext->priv->font_italic_flag != font_italic_flag) {
+       if (ltext->priv->font_italic_flag != font_italic_flag)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Italic"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
                ltext->priv->font_italic_flag = font_italic_flag;
                gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -609,21 +705,28 @@ set_font_italic_flag (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_text_alignment (glLabelObject    *object,
-                   PangoAlignment    text_alignment)
+                   PangoAlignment    text_alignment,
+                    gboolean          checkpoint)
 {
        glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-       if (ltext->priv->align != text_alignment) {
+       if (ltext->priv->align != text_alignment)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Align text"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
                ltext->priv->align = text_alignment;
                gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -635,21 +738,28 @@ set_text_alignment (glLabelObject    *object,
 /*****************************************************************************/
 static void
 set_text_line_spacing (glLabelObject *object,
-                      gdouble        line_spacing)
+                      gdouble        line_spacing,
+                       gboolean       checkpoint)
 {
        glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-       if (ltext->priv->line_spacing != line_spacing) {
+       if (ltext->priv->line_spacing != line_spacing)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Line spacing"));
+                }
 
                 ltext->priv->size_changed = TRUE;
 
                ltext->priv->line_spacing = line_spacing;
                gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -661,21 +771,28 @@ set_text_line_spacing (glLabelObject *object,
 /*****************************************************************************/
 static void
 set_text_color (glLabelObject *object,
-               glColorNode   *text_color_node)
+               glColorNode   *text_color_node,
+                gboolean       checkpoint)
 {
        glLabelText    *ltext = (glLabelText *)object;
+        glLabel        *label;
 
        gl_debug (DEBUG_LABEL, "START");
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-       if (!gl_color_node_equal (ltext->priv->color_node, text_color_node)) {
+       if (!gl_color_node_equal (ltext->priv->color_node, text_color_node))
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Text color"));
+                }
 
                gl_color_node_free (&(ltext->priv->color_node));
                ltext->priv->color_node = gl_color_node_dup (text_color_node);
                
                gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -799,17 +916,25 @@ get_text_color (glLabelObject *object)
 /*****************************************************************************/
 void
 gl_label_text_set_auto_shrink (glLabelText      *ltext,
-                              gboolean          auto_shrink)
+                              gboolean          auto_shrink,
+                               gboolean          checkpoint)
 {
+        glLabel *label;
+
        gl_debug (DEBUG_LABEL, "BEGIN");
 
        g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
 
-       if (ltext->priv->auto_shrink != auto_shrink) {
+       if (ltext->priv->auto_shrink != auto_shrink)
+        {
+                if ( checkpoint )
+                {
+                        label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
+                        gl_label_checkpoint (label, _("Auto shrink"));
+                }
 
                ltext->priv->auto_shrink = auto_shrink;
                gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
-
        }
 
        gl_debug (DEBUG_LABEL, "END");
@@ -831,146 +956,114 @@ gl_label_text_get_auto_shrink (glLabelText      *ltext)
 
 
 /*****************************************************************************/
-/* Draw object method.                                                       */
+/* Automatically shrink text size to fit within horizontal width.            */
 /*****************************************************************************/
-static void
-draw_object (glLabelObject *object,
-             cairo_t       *cr,
-             gboolean       screen_flag,
-             glMergeRecord *record)
+static gdouble
+auto_shrink_font_size (cairo_t     *cr,
+                       gchar       *family,
+                       gdouble      size,
+                       PangoWeight  weight,
+                       PangoStyle   style,
+                       gchar       *text,
+                       gdouble      width)
 {
-       glColorNode     *color_node;
-       guint            color;
+        PangoLayout          *layout;
+        PangoFontDescription *desc;
+        gint                  iw, ih;
+        gdouble               layout_width;
+        gdouble               new_size;
 
-       gl_debug (DEBUG_LABEL, "START");
+        layout = pango_cairo_create_layout (cr);
 
-       color_node = gl_label_object_get_text_color (object);
-       color = gl_color_node_expand (color_node, record);
-        if (color_node->field_flag && screen_flag)
-        {
-                color = GL_COLOR_MERGE_DEFAULT;
-        }
-       gl_color_node_free (&color_node);
-       
-        draw_text_real (object, cr, screen_flag, record, color);
+        desc = pango_font_description_new ();
+        pango_font_description_set_family (desc, family);
+        pango_font_description_set_weight (desc, weight);
+        pango_font_description_set_style  (desc, style);
+        pango_font_description_set_size   (desc, size * PANGO_SCALE);
 
-       gl_debug (DEBUG_LABEL, "END");
-}
+        pango_layout_set_font_description (layout, desc);
+        pango_font_description_free       (desc);
 
+        pango_layout_set_text (layout, text, -1);
+        pango_layout_set_width (layout, -1);
+        pango_layout_get_size (layout, &iw, &ih);
+        layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
 
-/*****************************************************************************/
-/* Draw shadow method.                                                       */
-/*****************************************************************************/
-static void
-draw_shadow (glLabelObject *object,
-             cairo_t       *cr,
-             gboolean       screen_flag,
-             glMergeRecord *record)
-{
-       glColorNode     *color_node;
-       guint            color;
-       glColorNode     *shadow_color_node;
-       gdouble          shadow_opacity;
-       guint            shadow_color;
+        g_object_unref (layout);
 
-       gl_debug (DEBUG_LABEL, "START");
+        g_print ("Object w = %g, layout w = %g\n", width, layout_width);
 
-       color_node = gl_label_object_get_text_color (object);
-       color = gl_color_node_expand (color_node, record);
-        if (color_node->field_flag && screen_flag)
+        if ( layout_width > width )
         {
-                color = GL_COLOR_MERGE_DEFAULT;
-        }
-       gl_color_node_free (&color_node);
-       
-       shadow_color_node = gl_label_object_get_shadow_color (object);
-       if (shadow_color_node->field_flag)
-       {
-               shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
-       }
-       shadow_opacity = gl_label_object_get_shadow_opacity (object);
-       shadow_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, color);
-       gl_color_node_free (&shadow_color_node);
+                /* Scale down. */
+                new_size = size * (width-2*GL_LABEL_TEXT_MARGIN)/layout_width;
 
-        draw_text_real (object, cr, screen_flag, record, shadow_color);
+                /* Round down to nearest 1/2 point */
+                new_size = (int)(new_size*2.0) / 2.0;
 
-       gl_debug (DEBUG_LABEL, "END");
+                /* don't get ridiculously small. */
+                if (new_size < 1.0)
+                {
+                        new_size = 1.0;
+                }
+        }
+        else
+        {
+                new_size = size;
+        }
+
+        return new_size;
 }
 
 
 /*****************************************************************************/
-/* Draw text.                                                                */
+/* Update pango layout.                                                      */
 /*****************************************************************************/
 static void
-draw_text_real (glLabelObject *object,
-                cairo_t       *cr,
-                gboolean       screen_flag,
-                glMergeRecord *record,
-                guint          color)
+set_text_path (glLabelText      *this,
+               cairo_t          *cr,
+               gboolean          screen_flag,
+               glMergeRecord    *record)
 {
-       gdouble          object_w, object_h;
-       gdouble          raw_w, raw_h;
-       gchar           *text;
-       GList           *lines;
-       gchar           *font_family;
-       gdouble          font_size;
-       PangoWeight      font_weight;
-       gboolean         font_italic_flag;
-        gboolean         auto_shrink;
-       gdouble          text_line_spacing;
-        PangoAlignment   alignment;
-        PangoStyle       style;
-        PangoLayout     *layout;
+        gdouble               object_w, object_h;
+        gdouble               raw_w, raw_h;
+        gchar                *text;
+        GList                *lines;
+        gdouble               font_size;
+        gboolean              auto_shrink;
+        PangoLayout          *layout;
+        PangoStyle            style;
         PangoFontDescription *desc;
-        gdouble          scale_x, scale_y;
         cairo_font_options_t *font_options;
         PangoContext         *context;
 
 
-       gl_debug (DEBUG_LABEL, "START");
+        gl_debug (DEBUG_LABEL, "START");
 
-       gl_label_object_get_size (object, &object_w, &object_h);
-       gl_label_object_get_raw_size (object, &raw_w, &raw_h);
-       lines = gl_label_text_get_lines (GL_LABEL_TEXT (object));
-       font_family = gl_label_object_get_font_family (object);
-       font_size = gl_label_object_get_font_size (object) * FONT_SCALE;
-       font_weight = gl_label_object_get_font_weight (object);
-       font_italic_flag = gl_label_object_get_font_italic_flag (object);
-
-       alignment = gl_label_object_get_text_alignment (object);
-       text_line_spacing =
-               gl_label_object_get_text_line_spacing (object);
-        auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
+        cairo_save (cr);
 
-       text = gl_text_node_lines_expand (lines, record);
+        gl_label_object_get_size (GL_LABEL_OBJECT (this), &object_w, &object_h);
+        gl_label_object_get_raw_size (GL_LABEL_OBJECT (this), &raw_w, &raw_h);
 
-        style = font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
+        lines = gl_label_text_get_lines (this);
+        text = gl_text_node_lines_expand (lines, record);
 
+        style = this->priv->font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
 
+        font_size   = this->priv->font_size;
+        auto_shrink = gl_label_text_get_auto_shrink (this);
         if (!screen_flag && record && auto_shrink && (raw_w != 0.0))
         {
                 font_size = auto_shrink_font_size (cr,
-                                                   font_family,
-                                                   font_size,
-                                                   font_weight,
+                                                   this->priv->font_family,
+                                                   this->priv->font_size * FONT_SCALE,
+                                                   this->priv->font_weight,
                                                    style,
                                                    text,
                                                    object_w);
         }
 
 
-        /*
-         * Workaround for pango Bug#341481.
-         * Render font at device scale and scale font size accordingly.
-         */
-        scale_x = 1.0;
-        scale_y = 1.0;
-        cairo_device_to_user_distance (cr, &scale_x, &scale_y);
-        scale_x = fabs (scale_x);
-        scale_y = fabs (scale_y);
-        cairo_save (cr);
-        cairo_scale (cr, scale_x, scale_y);
-
         layout = pango_cairo_create_layout (cr);
 
         font_options = cairo_font_options_create ();
@@ -980,101 +1073,125 @@ draw_text_real (glLabelObject *object,
         cairo_font_options_destroy (font_options);
 
         desc = pango_font_description_new ();
-        pango_font_description_set_family (desc, font_family);
-        pango_font_description_set_weight (desc, font_weight);
+        pango_font_description_set_family (desc, this->priv->font_family);
+        pango_font_description_set_weight (desc, this->priv->font_weight);
+        pango_font_description_set_size   (desc, font_size * FONT_SCALE * PANGO_SCALE);
         pango_font_description_set_style  (desc, style);
-        pango_font_description_set_size   (desc, font_size * PANGO_SCALE / scale_x);
         pango_layout_set_font_description (layout, desc);
         pango_font_description_free       (desc);
 
         pango_layout_set_text (layout, text, -1);
-        pango_layout_set_spacing (layout, font_size * (text_line_spacing-1) * PANGO_SCALE / scale_x);
+        pango_layout_set_spacing (layout, font_size * (this->priv->line_spacing-1) * PANGO_SCALE);
         if (raw_w == 0.0)
         {
                 pango_layout_set_width (layout, -1);
         }
         else
         {
-                pango_layout_set_width (layout, object_w * PANGO_SCALE / scale_x);
+                pango_layout_set_width (layout, object_w * PANGO_SCALE);
         }
-        pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
-        pango_layout_set_alignment (layout, alignment);
-
+        pango_layout_set_wrap (layout, PANGO_WRAP_WORD);
+        pango_layout_set_alignment (layout, this->priv->align);
 
-        cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
-        cairo_move_to (cr, GL_LABEL_TEXT_MARGIN/scale_x, 0);
-        pango_cairo_show_layout (cr, layout);
 
-        cairo_restore (cr);
+        cairo_move_to (cr, GL_LABEL_TEXT_MARGIN, 0);
+        pango_cairo_layout_path (cr, layout);
 
         g_object_unref (layout);
+        gl_text_node_lines_free (&lines);
 
+        cairo_restore (cr);
 
-       gl_text_node_lines_free (&lines);
-       g_free (font_family);
-
-       gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 }
 
 
 /*****************************************************************************/
-/* Automatically shrink text size to fit within horizontal width.            */
+/* Draw object method.                                                       */
 /*****************************************************************************/
-static gdouble
-auto_shrink_font_size (cairo_t     *cr,
-                       gchar       *family,
-                       gdouble      size,
-                       PangoWeight  weight,
-                       PangoStyle   style,
-                       gchar       *text,
-                       gdouble      width)
+static void
+draw_object (glLabelObject *object,
+             cairo_t       *cr,
+             gboolean       screen_flag,
+             glMergeRecord *record)
 {
-        PangoLayout          *layout;
-        PangoFontDescription *desc;
-        gint                  iw, ih;
-        gdouble               layout_width;
-        gdouble               new_size;
+        glColorNode     *color_node;
+        guint            color;
 
-        layout = pango_cairo_create_layout (cr);
+        gl_debug (DEBUG_LABEL, "START");
 
-        desc = pango_font_description_new ();
-        pango_font_description_set_family (desc, family);
-        pango_font_description_set_weight (desc, weight);
-        pango_font_description_set_style  (desc, style);
-        pango_font_description_set_size   (desc, size * PANGO_SCALE);
-        
-        pango_layout_set_font_description (layout, desc);
-        pango_font_description_free       (desc);
+        color_node = gl_label_object_get_text_color (object);
+        color = gl_color_node_expand (color_node, record);
+        if (color_node->field_flag && screen_flag)
+        {
+                color = GL_COLOR_MERGE_DEFAULT;
+        }
+        gl_color_node_free (&color_node);
 
-        pango_layout_set_text (layout, text, -1);
-        pango_layout_set_width (layout, -1);
-        pango_layout_get_size (layout, &iw, &ih);
-        layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
+        draw_text_real (object, cr, screen_flag, record, color);
 
-        g_object_unref (layout);
+        gl_debug (DEBUG_LABEL, "END");
+}
 
-        g_print ("Object w = %g, layout w = %g\n", width, layout_width);
 
-        if ( layout_width > width )
-        {
-                /* Scale down. */
-                new_size = size * (width-2*GL_LABEL_TEXT_MARGIN)/layout_width;
+/*****************************************************************************/
+/* Draw shadow method.                                                       */
+/*****************************************************************************/
+static void
+draw_shadow (glLabelObject *object,
+             cairo_t       *cr,
+             gboolean       screen_flag,
+             glMergeRecord *record)
+{
+        glColorNode     *color_node;
+        guint            color;
+        glColorNode     *shadow_color_node;
+        gdouble          shadow_opacity;
+        guint            shadow_color;
 
-                /* Round down to nearest 1/2 point */
-                new_size = (int)(new_size*2.0) / 2.0;
+        gl_debug (DEBUG_LABEL, "START");
 
-                /* don't get ridiculously small. */
-                if (new_size < 1.0)
-                {
-                        new_size = 1.0;
-                }
+        color_node = gl_label_object_get_text_color (object);
+        color = gl_color_node_expand (color_node, record);
+        if (color_node->field_flag && screen_flag)
+        {
+                color = GL_COLOR_MERGE_DEFAULT;
         }
-        else
+        gl_color_node_free (&color_node);
+
+        shadow_color_node = gl_label_object_get_shadow_color (object);
+        if (shadow_color_node->field_flag)
         {
-                new_size = size;
+                shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
         }
+        shadow_opacity = gl_label_object_get_shadow_opacity (object);
+        shadow_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, color);
+        gl_color_node_free (&shadow_color_node);
 
-        return new_size;
+        draw_text_real (object, cr, screen_flag, record, shadow_color);
+
+        gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/*****************************************************************************/
+/* Draw text.                                                                */
+/*****************************************************************************/
+static void
+draw_text_real (glLabelObject *object,
+                cairo_t       *cr,
+                gboolean       screen_flag,
+                glMergeRecord *record,
+                guint          color)
+{
+        gl_debug (DEBUG_LABEL, "START");
+
+        set_text_path (GL_LABEL_TEXT (object), cr, screen_flag, record);
+
+        cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
+        cairo_fill (cr);
+
+        gl_debug (DEBUG_LABEL, "END");
 }
 
 
@@ -1088,20 +1205,89 @@ object_at (glLabelObject *object,
            gdouble        y)
 {
         gdouble           w, h;
+        gdouble           scale_x, scale_y;
 
         gl_label_object_get_size (object, &w, &h);
 
-        cairo_rectangle (cr, 0.0, 0.0, w, h);
-
-        if (cairo_in_fill (cr, x, y))
+        if ( (x >= 0) && (x <= w) && (y >= 0) && (y <= h) )
         {
-                return TRUE;
+                cairo_new_path (cr);
+                set_text_path (GL_LABEL_TEXT (object), cr, TRUE, NULL);
+                if (cairo_in_fill (cr, x, y))
+                {
+                        return TRUE;
+                }
+
+
+                scale_x = 1.0;
+                scale_y = 1.0;
+                cairo_device_to_user_distance (cr, &scale_x, &scale_y);
+
+                cairo_set_line_width (cr, 2*SELECTION_SLOP_PIXELS*scale_x);
+
+                if (cairo_in_stroke (cr, x, y))
+                {
+                        return TRUE;
+                }
+
+
+                if (gl_label_object_is_selected (object))
+                {
+                        cairo_new_path (cr);
+                        cairo_rectangle (cr, 0, 0, w, h);
+
+                        scale_x = 1.0;
+                        scale_y = 1.0;
+                        cairo_device_to_user_distance (cr, &scale_x, &scale_y);
+
+                        cairo_set_line_width (cr, 2*SELECTION_SLOP_PIXELS*scale_x);
+
+                        if (cairo_in_stroke (cr, x, y))
+                        {
+                                return TRUE;
+                        }
+                }
+
         }
 
         return FALSE;
 }
 
 
+/*****************************************************************************/
+/* Draw text style handles.                                                  */
+/*****************************************************************************/
+static void
+draw_handles (glLabelObject     *object,
+              cairo_t           *cr)
+{
+        gdouble w, h;
+        gdouble scale_x, scale_y;
+        gdouble dashes[2] = { 2, 2 };
+
+        gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
+
+        cairo_save (cr);
+
+        cairo_rectangle (cr, 0, 0, w, h);
+
+        scale_x = 1.0;
+        scale_y = 1.0;
+        cairo_device_to_user_distance (cr, &scale_x, &scale_y);
+        cairo_scale (cr, scale_x, scale_y);
+
+        cairo_set_dash (cr, dashes, 2, 0);
+        cairo_set_line_width (cr, HANDLE_OUTLINE_WIDTH_PIXELS);
+        cairo_set_source_rgba (cr, HANDLE_OUTLINE_RGBA_ARGS);
+        cairo_stroke (cr);
+
+        cairo_restore (cr);
+
+        gl_label_object_draw_handles_box (object, cr);
+}
+
+
+
 
 /*
  * Local Variables:       -- emacs