-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
-
/*
- * (GLABELS) Label and Business Card Creation program for GNOME
- *
- * label_text.c: GLabels label text object
+ * label-text.c
+ * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
*
- * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>.
+ * This file is part of gLabels.
*
- * This program is free software; you can redistribute it and/or modify
+ * gLabels is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
+ * gLabels is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
+
#include "label-text.h"
-#include <glib/gmem.h>
-#include <glib/gstrfuncs.h>
-#include <glib/gmessages.h>
+#include <glib/gi18n.h>
+#include <glib.h>
#include <pango/pango.h>
#include <math.h>
+#include <string.h>
-#include "util.h"
+#include "font-util.h"
+#include "font-history.h"
#include "debug.h"
+
/*========================================================*/
/* Private macros and constants. */
/*========================================================*/
-#define DEFAULT_FONT_FAMILY "Sans"
-#define DEFAULT_FONT_SIZE 14.0
-#define DEFAULT_FONT_WEIGHT PANGO_WEIGHT_NORMAL
-#define DEFAULT_FONT_ITALIC_FLAG FALSE
-#define DEFAULT_ALIGN PANGO_ALIGN_LEFT
-#define DEFAULT_COLOR GL_COLOR (0,0,0)
-#define DEFAULT_TEXT_LINE_SPACING 1.0
-#define DEFAULT_AUTO_SHRINK FALSE
-
#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;
gboolean size_changed;
gdouble w;
gdouble h;
+
+ gboolean checkpoint_flag;
};
+
/*========================================================*/
/* Private globals. */
/*========================================================*/
+
/*========================================================*/
/* Private function prototypes. */
/*========================================================*/
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);
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);
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,
gboolean screen_flag,
glMergeRecord *record);
+static void draw_text_real (glLabelObject *object,
+ cairo_t *cr,
+ gboolean screen_flag,
+ glMergeRecord *record,
+ guint color);
+
static gdouble auto_shrink_font_size (cairo_t *cr,
gchar *family,
gdouble size,
gchar *text,
gdouble width);
+static gboolean object_at (glLabelObject *object,
+ cairo_t *cr,
+ gdouble x_pixels,
+ gdouble y_pixels);
+
+static void draw_handles (glLabelObject *object,
+ cairo_t *cr);
+
-\f
/*****************************************************************************/
-/* Boilerplate object stuff. */
+/* Object infrastructure. */
/*****************************************************************************/
-G_DEFINE_TYPE (glLabelText, gl_label_text, GL_TYPE_LABEL_OBJECT);
+G_DEFINE_TYPE (glLabelText, gl_label_text, GL_TYPE_LABEL_OBJECT)
+
+/*****************************************************************************/
+/* Class Init Function. */
+/*****************************************************************************/
static void
gl_label_text_class_init (glLabelTextClass *class)
{
label_object_class->get_text_color = get_text_color;
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;
}
+
+/*****************************************************************************/
+/* Object Instance Init Function. */
+/*****************************************************************************/
static void
gl_label_text_init (glLabelText *ltext)
{
ltext->priv->tag_table = gtk_text_tag_table_new ();
ltext->priv->buffer = gtk_text_buffer_new (ltext->priv->tag_table);
- ltext->priv->font_family = g_strdup(DEFAULT_FONT_FAMILY);
- ltext->priv->font_size = DEFAULT_FONT_SIZE;
- ltext->priv->font_weight = DEFAULT_FONT_WEIGHT;
- ltext->priv->font_italic_flag = DEFAULT_FONT_ITALIC_FLAG;
- ltext->priv->align = DEFAULT_ALIGN;
- ltext->priv->color_node = gl_color_node_new_default ();
- ltext->priv->color_node->color = DEFAULT_COLOR;
- ltext->priv->line_spacing = DEFAULT_TEXT_LINE_SPACING;
- ltext->priv->auto_shrink = DEFAULT_AUTO_SHRINK;
-
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);
}
+
+/*****************************************************************************/
+/* Finalize Method. */
+/*****************************************************************************/
static void
gl_label_text_finalize (GObject *object)
{
G_OBJECT_CLASS (gl_label_text_parent_class)->finalize (object);
}
+
/*****************************************************************************/
-/* NEW label "text" object. */
+/** New Object Generator. */
/*****************************************************************************/
GObject *
-gl_label_text_new (glLabel *label)
+gl_label_text_new (glLabel *label,
+ gboolean checkpoint)
{
- glLabelText *ltext;
+ glLabelText *ltext;
+ glColorNode *color_node;
ltext = g_object_new (gl_label_text_get_type(), NULL);
- gl_label_object_set_parent (GL_LABEL_OBJECT(ltext), label);
+ if (label != NULL)
+ {
+ if ( checkpoint )
+ {
+ gl_label_checkpoint (label, _("Create text object"));
+ }
+
+ color_node = gl_color_node_new_default ();
+
+ color_node->color = gl_label_get_default_text_color (label);
+
+ ltext->priv->font_family = gl_label_get_default_font_family (label);
+ ltext->priv->font_size = gl_label_get_default_font_size (label);
+ ltext->priv->font_weight = gl_label_get_default_font_weight (label);
+ ltext->priv->font_italic_flag = gl_label_get_default_font_italic_flag (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);
}
+
/*****************************************************************************/
/* Copy object contents. */
/*****************************************************************************/
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;
/*****************************************************************************/
void
gl_label_text_set_lines (glLabelText *ltext,
- GList *lines)
+ GList *lines,
+ gboolean checkpoint)
{
gchar *text;
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,
+ 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");
+}
+
+
/*****************************************************************************/
/* Get object params. */
/*****************************************************************************/
return ltext->priv->buffer;
}
+
GList *
gl_label_text_get_lines (glLabelText *ltext)
{
return lines;
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. text buffer "changed" callback. */
-/*---------------------------------------------------------------------------*/
-void buffer_changed_cb (GtkTextBuffer *textbuffer,
- glLabelText *ltext)
+
+gchar *
+gl_label_text_get_text (glLabelText *ltext)
+{
+ GtkTextIter start, end;
+ gchar *text;
+
+ g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
+
+ gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
+ text = gtk_text_buffer_get_text (ltext->priv->buffer,
+ &start, &end, FALSE);
+
+ return text;
+}
+
+
+/*****************************************************************************/
+/* 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. */
+/*****************************************************************************/
+static void
+buffer_changed_cb (GtkTextBuffer *textbuffer,
+ glLabelText *ltext)
{
ltext->priv->size_changed = TRUE;
gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. get object size method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Get object size method. */
+/*****************************************************************************/
static void
get_size (glLabelObject *object,
gdouble *w,
gl_debug (DEBUG_LABEL, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. set font family method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Set font family method. */
+/*****************************************************************************/
static void
set_font_family (glLabelObject *object,
- const gchar *font_family)
+ const gchar *font_family,
+ gboolean checkpoint)
{
glLabelText *ltext = (glLabelText *)object;
- GList *family_names;
gchar *good_font_family;
+ glLabel *label;
gl_debug (DEBUG_LABEL, "START");
g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
g_return_if_fail (font_family);
- family_names = gl_util_get_font_family_list ();
- if (g_list_find_custom (family_names, font_family, (GCompareFunc)g_utf8_collate)) {
- good_font_family = g_strdup (font_family);
- } else {
- if (family_names != NULL) {
- good_font_family = g_strdup (family_names->data); /* 1st entry */
- } else {
- good_font_family = g_strdup (font_family);
- }
- }
+ good_font_family = gl_font_util_validate_family (font_family);
if (ltext->priv->font_family) {
- if (g_strcasecmp (ltext->priv->font_family, good_font_family) == 0) {
+ if (strcmp (ltext->priv->font_family, good_font_family) == 0) {
g_free (good_font_family);
gl_debug (DEBUG_LABEL, "END (no change)");
return;
}
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);
ltext->priv->size_changed = TRUE;
+ gl_font_history_model_add_family (gl_font_history, ltext->priv->font_family);
+
gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
gl_debug (DEBUG_LABEL, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. set font size method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Set font size method. */
+/*****************************************************************************/
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");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. set font weight method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Set font weight method. */
+/*****************************************************************************/
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");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. set font italic flag method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Set font italic flag method. */
+/*****************************************************************************/
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");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. set text alignment method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Set text alignment method. */
+/*****************************************************************************/
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");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. set text line spacing method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Set text line spacing method. */
+/*****************************************************************************/
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");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. set text color method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Set text color method. */
+/*****************************************************************************/
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");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. get font family method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Get font family method. */
+/*****************************************************************************/
static gchar *
get_font_family (glLabelObject *object)
{
return g_strdup (ltext->priv->font_family);
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. get font size method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Get font size method. */
+/*****************************************************************************/
static gdouble
get_font_size (glLabelObject *object)
{
return ltext->priv->font_size;
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. get font weight method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Get font weight method. */
+/*****************************************************************************/
static PangoWeight
get_font_weight (glLabelObject *object)
{
return ltext->priv->font_weight;
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. get font italic flag method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Get font italic flag method. */
+/*****************************************************************************/
static gboolean
get_font_italic_flag (glLabelObject *object)
{
return ltext->priv->font_italic_flag;
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. get text alignment method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Get text alignment method. */
+/*****************************************************************************/
static PangoAlignment
get_text_alignment (glLabelObject *object)
{
return ltext->priv->align;
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. get text line spacing method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Get text line spacing method. */
+/*****************************************************************************/
static gdouble
get_text_line_spacing (glLabelObject *object)
{
return ltext->priv->line_spacing;
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. get text color method. */
-/*---------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Get text color method. */
+/*****************************************************************************/
static glColorNode*
get_text_color (glLabelObject *object)
{
return gl_color_node_dup (ltext->priv->color_node);
}
+
/*****************************************************************************/
/* Set auto shrink flag. */
/*****************************************************************************/
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");
}
+
/*****************************************************************************/
/* Query auto shrink flag. */
/*****************************************************************************/
return ltext->priv->auto_shrink;
}
+
/*****************************************************************************/
-/* 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)
{
- gdouble x0, y0;
- cairo_matrix_t matrix;
- 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;
- glColorNode *color_node;
- gboolean auto_shrink;
- guint color;
- gdouble text_line_spacing;
- PangoAlignment alignment;
- PangoStyle style;
- PangoLayout *layout;
+ PangoLayout *layout;
PangoFontDescription *desc;
- gdouble scale_x, scale_y;
- cairo_font_options_t *font_options;
- PangoContext *context;
+ gint iw, ih;
+ gdouble layout_width;
+ gdouble new_size;
+ 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);
+
+ 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;
- gl_label_object_get_position (object, &x0, &y0);
- gl_label_object_get_matrix (object, &matrix);
+ g_object_unref (layout);
- 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);
+ 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;
+ /* Scale down. */
+ new_size = size * (width-2*GL_LABEL_TEXT_MARGIN)/layout_width;
+
+ /* Round down to nearest 1/2 point */
+ new_size = (int)(new_size*2.0) / 2.0;
+
+ /* don't get ridiculously small. */
+ if (new_size < 1.0)
+ {
+ new_size = 1.0;
+ }
}
- gl_color_node_free (&color_node);
-
- 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));
+ else
+ {
+ new_size = size;
+ }
+
+ return new_size;
+}
+
+
+/*****************************************************************************/
+/* Update pango layout. */
+/*****************************************************************************/
+static void
+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;
+ gdouble font_size;
+ gboolean auto_shrink;
+ PangoLayout *layout;
+ PangoStyle style;
+ PangoFontDescription *desc;
+ cairo_font_options_t *font_options;
+ PangoContext *context;
+
+
+ gl_debug (DEBUG_LABEL, "START");
+
+ 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);
- g_print ("Autosize new size = %g\n", font_size);
}
- /*
- * 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 ();
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_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);
- g_object_unref (layout);
+ gl_debug (DEBUG_LABEL, "END");
+}
- gl_text_node_lines_free (&lines);
- g_free (font_family);
+/*****************************************************************************/
+/* Draw object method. */
+/*****************************************************************************/
+static void
+draw_object (glLabelObject *object,
+ cairo_t *cr,
+ gboolean screen_flag,
+ glMergeRecord *record)
+{
+ glColorNode *color_node;
+ guint color;
- gl_debug (DEBUG_LABEL, "END");
+ gl_debug (DEBUG_LABEL, "START");
+
+ 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);
+
+ gl_debug (DEBUG_LABEL, "END");
}
+
/*****************************************************************************/
/* Draw shadow method. */
/*****************************************************************************/
gboolean screen_flag,
glMergeRecord *record)
{
- gdouble x0, y0;
- cairo_matrix_t matrix;
- 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;
- guint color;
- glColorNode *color_node;
- gdouble text_line_spacing;
- glColorNode *shadow_color_node;
- gdouble shadow_opacity;
- guint shadow_color;
- PangoAlignment alignment;
- PangoStyle style;
- PangoLayout *layout;
- PangoFontDescription *desc;
- gdouble scale_x, scale_y;
- cairo_font_options_t *font_options;
- PangoContext *context;
+ glColorNode *color_node;
+ guint color;
+ glColorNode *shadow_color_node;
+ gdouble shadow_opacity;
+ guint shadow_color;
+ gl_debug (DEBUG_LABEL, "START");
- gl_debug (DEBUG_LABEL, "START");
+ 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);
- gl_label_object_get_position (object, &x0, &y0);
- gl_label_object_get_matrix (object, &matrix);
+ 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);
- 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);
+ draw_text_real (object, cr, screen_flag, record, shadow_color);
- color_node = gl_label_object_get_text_color (object);
- color = gl_color_node_expand (color_node, record);
- gl_color_node_free (&color_node);
-
- 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));
-
- 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);
+ gl_debug (DEBUG_LABEL, "END");
+}
- text = gl_text_node_lines_expand (lines, record);
- style = font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
+/*****************************************************************************/
+/* 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);
- if (!screen_flag && record && auto_shrink && (raw_w != 0.0))
- {
- font_size = auto_shrink_font_size (cr,
- font_family,
- font_size,
- font_weight,
- style,
- text,
- object_w);
- }
-
+ cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
+ cairo_fill (cr);
- /*
- * 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);
+ gl_debug (DEBUG_LABEL, "END");
+}
- layout = pango_cairo_create_layout (cr);
- font_options = cairo_font_options_create ();
- cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
- context = pango_layout_get_context (layout);
- pango_cairo_context_set_font_options (context, font_options);
- cairo_font_options_destroy (font_options);
+/*****************************************************************************/
+/* Is object at coordinates? */
+/*****************************************************************************/
+static gboolean
+object_at (glLabelObject *object,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y)
+{
+ gdouble w, h;
+ gdouble scale_x, scale_y;
- 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_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);
+ gl_label_object_get_size (object, &w, &h);
- pango_layout_set_text (layout, text, -1);
- pango_layout_set_spacing (layout, font_size * (text_line_spacing-1) * PANGO_SCALE / scale_x);
- if (raw_w == 0.0)
- {
- pango_layout_set_width (layout, -1);
- }
- else
+ if ( (x >= 0) && (x <= w) && (y >= 0) && (y <= h) )
{
- pango_layout_set_width (layout, object_w * PANGO_SCALE / scale_x);
- }
- pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
- pango_layout_set_alignment (layout, alignment);
+ cairo_new_path (cr);
+ set_text_path (GL_LABEL_TEXT (object), cr, TRUE, NULL);
+ if (cairo_in_fill (cr, x, y))
+ {
+ return TRUE;
+ }
- cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (shadow_color));
- cairo_move_to (cr, GL_LABEL_TEXT_MARGIN/scale_x, 0);
- pango_cairo_show_layout (cr, layout);
+ scale_x = 1.0;
+ scale_y = 1.0;
+ cairo_device_to_user_distance (cr, &scale_x, &scale_y);
- cairo_restore (cr);
+ cairo_set_line_width (cr, 2*SELECTION_SLOP_PIXELS*scale_x);
- g_object_unref (layout);
+ if (cairo_in_stroke (cr, x, y))
+ {
+ return TRUE;
+ }
- gl_text_node_lines_free (&lines);
- g_free (font_family);
- gl_debug (DEBUG_LABEL, "END");
+ 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;
}
+
/*****************************************************************************/
-/* Automatically shrink text size to fit within horizontal width. */
+/* Draw text style handles. */
/*****************************************************************************/
-static gdouble
-auto_shrink_font_size (cairo_t *cr,
- gchar *family,
- gdouble size,
- PangoWeight weight,
- PangoStyle style,
- gchar *text,
- gdouble width)
+static void
+draw_handles (glLabelObject *object,
+ cairo_t *cr)
{
- PangoLayout *layout;
- PangoFontDescription *desc;
- gint iw, ih;
- gdouble layout_width;
- gdouble new_size;
+ gdouble w, h;
+ gdouble scale_x, scale_y;
+ gdouble dashes[2] = { 2, 2 };
- layout = pango_cairo_create_layout (cr);
+ gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
- 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);
+ cairo_save (cr);
- 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;
+ cairo_rectangle (cr, 0, 0, w, h);
- g_object_unref (layout);
+ 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);
- g_print ("Object w = %g, layout w = %g\n", width, layout_width);
+ 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);
- if ( layout_width > width )
- {
- /* Scale down. */
- new_size = size * (width-2*GL_LABEL_TEXT_MARGIN)/layout_width;
+ cairo_restore (cr);
- /* Round down to nearest 1/2 point */
- new_size = (int)(new_size*2.0) / 2.0;
+ gl_label_object_draw_handles_box (object, cr);
+}
- /* don't get ridiculously small. */
- if (new_size < 1.0)
- {
- new_size = 1.0;
- }
- }
- else
- {
- new_size = size;
- }
- return new_size;
-}
+
+/*
+ * Local Variables: -- emacs
+ * mode: C -- emacs
+ * c-basic-offset: 8 -- emacs
+ * tab-width: 8 -- emacs
+ * indent-tabs-mode: nil -- emacs
+ * End: -- emacs
+ */