3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * gLabels is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
23 #include "label-text.h"
25 #include <glib/gi18n.h>
27 #include <pango/pango.h>
31 #include "font-util.h"
32 #include "font-history.h"
37 /*========================================================*/
38 /* Private macros and constants. */
39 /*========================================================*/
41 #define FONT_SCALE (72.0/96.0)
44 /*========================================================*/
46 /*========================================================*/
48 struct _glLabelTextPrivate {
49 GtkTextTagTable *tag_table;
50 GtkTextBuffer *buffer;
54 PangoWeight font_weight;
55 gboolean font_italic_flag;
57 glColorNode *color_node;
61 gboolean size_changed;
65 gboolean checkpoint_flag;
69 /*========================================================*/
70 /* Private globals. */
71 /*========================================================*/
74 /*========================================================*/
75 /* Private function prototypes. */
76 /*========================================================*/
78 static void gl_label_text_finalize (GObject *object);
80 static void copy (glLabelObject *dst_object,
81 glLabelObject *src_object);
83 static void buffer_begin_user_action_cb (GtkTextBuffer *textbuffer,
86 static void buffer_changed_cb (GtkTextBuffer *textbuffer,
89 static void get_size (glLabelObject *object,
93 static void set_font_family (glLabelObject *object,
94 const gchar *font_family,
97 static void set_font_size (glLabelObject *object,
101 static void set_font_weight (glLabelObject *object,
102 PangoWeight font_weight,
103 gboolean checkpoint);
105 static void set_font_italic_flag (glLabelObject *object,
106 gboolean font_italic_flag,
107 gboolean checkpoint);
109 static void set_text_alignment (glLabelObject *object,
110 PangoAlignment text_alignment,
111 gboolean checkpoint);
113 static void set_text_line_spacing (glLabelObject *object,
114 gdouble text_line_spacing,
115 gboolean checkpoint);
117 static void set_text_color (glLabelObject *object,
118 glColorNode *text_color_node,
119 gboolean checkpoint);
121 static gchar *get_font_family (glLabelObject *object);
123 static gdouble get_font_size (glLabelObject *object);
125 static PangoWeight get_font_weight (glLabelObject *object);
127 static gboolean get_font_italic_flag (glLabelObject *object);
129 static PangoAlignment get_text_alignment (glLabelObject *object);
131 static gdouble get_text_line_spacing (glLabelObject *object);
133 static glColorNode* get_text_color (glLabelObject *object);
135 static void draw_object (glLabelObject *object,
137 gboolean screen_flag,
138 glMergeRecord *record);
140 static void draw_shadow (glLabelObject *object,
142 gboolean screen_flag,
143 glMergeRecord *record);
145 static void draw_text_real (glLabelObject *object,
147 gboolean screen_flag,
148 glMergeRecord *record,
151 static gdouble auto_shrink_font_size (cairo_t *cr,
159 static gboolean object_at (glLabelObject *object,
165 /*****************************************************************************/
166 /* Object infrastructure. */
167 /*****************************************************************************/
168 G_DEFINE_TYPE (glLabelText, gl_label_text, GL_TYPE_LABEL_OBJECT);
171 /*****************************************************************************/
172 /* Class Init Function. */
173 /*****************************************************************************/
175 gl_label_text_class_init (glLabelTextClass *class)
177 GObjectClass *object_class = G_OBJECT_CLASS (class);
178 glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
180 gl_label_text_parent_class = g_type_class_peek_parent (class);
182 label_object_class->copy = copy;
184 label_object_class->get_size = get_size;
186 label_object_class->set_font_family = set_font_family;
187 label_object_class->set_font_size = set_font_size;
188 label_object_class->set_font_weight = set_font_weight;
189 label_object_class->set_font_italic_flag = set_font_italic_flag;
190 label_object_class->set_text_alignment = set_text_alignment;
191 label_object_class->set_text_line_spacing = set_text_line_spacing;
192 label_object_class->set_text_color = set_text_color;
193 label_object_class->get_font_family = get_font_family;
194 label_object_class->get_font_size = get_font_size;
195 label_object_class->get_font_weight = get_font_weight;
196 label_object_class->get_font_italic_flag = get_font_italic_flag;
197 label_object_class->get_text_alignment = get_text_alignment;
198 label_object_class->get_text_line_spacing = get_text_line_spacing;
199 label_object_class->get_text_color = get_text_color;
200 label_object_class->draw_object = draw_object;
201 label_object_class->draw_shadow = draw_shadow;
202 label_object_class->object_at = object_at;
204 object_class->finalize = gl_label_text_finalize;
208 /*****************************************************************************/
209 /* Object Instance Init Function. */
210 /*****************************************************************************/
212 gl_label_text_init (glLabelText *ltext)
214 ltext->priv = g_new0 (glLabelTextPrivate, 1);
216 ltext->priv->tag_table = gtk_text_tag_table_new ();
217 ltext->priv->buffer = gtk_text_buffer_new (ltext->priv->tag_table);
219 ltext->priv->size_changed = TRUE;
221 ltext->priv->checkpoint_flag = TRUE;
223 g_signal_connect (G_OBJECT(ltext->priv->buffer), "begin-user-action",
224 G_CALLBACK(buffer_begin_user_action_cb), ltext);
225 g_signal_connect (G_OBJECT(ltext->priv->buffer), "changed",
226 G_CALLBACK(buffer_changed_cb), ltext);
230 /*****************************************************************************/
231 /* Finalize Method. */
232 /*****************************************************************************/
234 gl_label_text_finalize (GObject *object)
236 glLabelText *ltext = GL_LABEL_TEXT (object);
238 g_return_if_fail (object && GL_IS_LABEL_TEXT (object));
240 g_object_unref (ltext->priv->tag_table);
241 g_object_unref (ltext->priv->buffer);
242 g_free (ltext->priv->font_family);
243 gl_color_node_free (&(ltext->priv->color_node));
244 g_free (ltext->priv);
246 G_OBJECT_CLASS (gl_label_text_parent_class)->finalize (object);
250 /*****************************************************************************/
251 /** New Object Generator. */
252 /*****************************************************************************/
254 gl_label_text_new (glLabel *label,
258 glColorNode *color_node;
260 ltext = g_object_new (gl_label_text_get_type(), NULL);
266 gl_label_checkpoint (label, _("Create text object"));
269 color_node = gl_color_node_new_default ();
271 color_node->color = gl_label_get_default_text_color (label);
273 ltext->priv->font_family = gl_label_get_default_font_family (label);
274 ltext->priv->font_size = gl_label_get_default_font_size (label);
275 ltext->priv->font_weight = gl_label_get_default_font_weight (label);
276 ltext->priv->font_italic_flag = gl_label_get_default_font_italic_flag (label);
277 ltext->priv->align = gl_label_get_default_text_alignment (label);
278 ltext->priv->color_node = color_node;
279 ltext->priv->line_spacing = gl_label_get_default_text_line_spacing (label);
281 gl_label_add_object (label, GL_LABEL_OBJECT (ltext));
282 gl_label_object_set_parent (GL_LABEL_OBJECT (ltext), label);
285 return G_OBJECT (ltext);
289 /*****************************************************************************/
290 /* Copy object contents. */
291 /*****************************************************************************/
293 copy (glLabelObject *dst_object,
294 glLabelObject *src_object)
296 glLabelText *ltext = (glLabelText *)src_object;
297 glLabelText *new_ltext = (glLabelText *)dst_object;
299 glColorNode *text_color_node;
301 gl_debug (DEBUG_LABEL, "START");
303 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
304 g_return_if_fail (new_ltext && GL_IS_LABEL_TEXT (new_ltext));
306 lines = gl_label_text_get_lines (ltext);
307 text_color_node = get_text_color (src_object);
308 gl_label_text_set_lines (new_ltext, lines, FALSE);
310 new_ltext->priv->font_family = g_strdup (ltext->priv->font_family);
311 new_ltext->priv->font_size = ltext->priv->font_size;
312 new_ltext->priv->font_weight = ltext->priv->font_weight;
313 new_ltext->priv->font_italic_flag = ltext->priv->font_italic_flag;
314 set_text_color (dst_object, text_color_node, FALSE);
315 new_ltext->priv->align = ltext->priv->align;
316 new_ltext->priv->line_spacing = ltext->priv->line_spacing;
317 new_ltext->priv->auto_shrink = ltext->priv->auto_shrink;
319 new_ltext->priv->size_changed = ltext->priv->size_changed;
320 new_ltext->priv->w = ltext->priv->w;
321 new_ltext->priv->h = ltext->priv->h;
323 gl_color_node_free (&text_color_node);
324 gl_text_node_lines_free (&lines);
326 gl_debug (DEBUG_LABEL, "END");
330 /*****************************************************************************/
331 /* Set object params. */
332 /*****************************************************************************/
334 gl_label_text_set_lines (glLabelText *ltext,
340 gl_debug (DEBUG_LABEL, "START");
342 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
344 ltext->priv->checkpoint_flag = checkpoint;
346 text = gl_text_node_lines_expand (lines, NULL);
347 gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
350 ltext->priv->size_changed = TRUE;
352 ltext->priv->checkpoint_flag = TRUE;
354 gl_debug (DEBUG_LABEL, "END");
359 gl_label_text_set_text (glLabelText *ltext,
363 gl_debug (DEBUG_LABEL, "START");
365 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
367 ltext->priv->checkpoint_flag = checkpoint;
369 gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
371 ltext->priv->size_changed = TRUE;
373 ltext->priv->checkpoint_flag = TRUE;
375 gl_debug (DEBUG_LABEL, "END");
379 /*****************************************************************************/
380 /* Get object params. */
381 /*****************************************************************************/
383 gl_label_text_get_buffer (glLabelText *ltext)
385 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
387 return ltext->priv->buffer;
392 gl_label_text_get_lines (glLabelText *ltext)
394 GtkTextIter start, end;
398 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
400 gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
401 text = gtk_text_buffer_get_text (ltext->priv->buffer,
402 &start, &end, FALSE);
403 lines = gl_text_node_lines_new_from_text (text);
411 gl_label_text_get_text (glLabelText *ltext)
413 GtkTextIter start, end;
416 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
418 gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
419 text = gtk_text_buffer_get_text (ltext->priv->buffer,
420 &start, &end, FALSE);
426 /*****************************************************************************/
427 /* Text buffer "changed" callback. */
428 /*****************************************************************************/
430 buffer_begin_user_action_cb (GtkTextBuffer *textbuffer,
435 if ( ltext->priv->checkpoint_flag )
437 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
438 gl_label_checkpoint (label, _("Typing"));
443 /*****************************************************************************/
444 /* Text buffer "changed" callback. */
445 /*****************************************************************************/
447 buffer_changed_cb (GtkTextBuffer *textbuffer,
452 ltext->priv->size_changed = TRUE;
454 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
458 /*****************************************************************************/
459 /* Get object size method. */
460 /*****************************************************************************/
462 get_size (glLabelObject *object,
466 glLabelText *ltext = (glLabelText *)object;
467 PangoFontMap *fontmap;
468 PangoContext *context;
469 cairo_font_options_t *options;
472 PangoFontDescription *desc;
474 gdouble line_spacing;
475 GtkTextIter start, end;
477 gdouble w_parent, h_parent;
480 gl_debug (DEBUG_LABEL, "START");
482 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
484 gl_label_object_get_raw_size (object, &w_parent, &h_parent);
486 if ( (w_parent != 0.0) || (h_parent != 0.0) ) {
492 if (!ltext->priv->size_changed)
499 font_size = GL_LABEL_TEXT (object)->priv->font_size * FONT_SCALE;
500 line_spacing = GL_LABEL_TEXT (object)->priv->line_spacing;
502 gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
503 text = gtk_text_buffer_get_text (ltext->priv->buffer,
504 &start, &end, FALSE);
507 fontmap = pango_cairo_font_map_new ();
508 context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
509 options = cairo_font_options_create ();
510 cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
511 pango_cairo_context_set_font_options (context, options);
512 cairo_font_options_destroy (options);
514 layout = pango_layout_new (context);
516 style = GL_LABEL_TEXT (object)->priv->font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
518 desc = pango_font_description_new ();
519 pango_font_description_set_family (desc, GL_LABEL_TEXT (object)->priv->font_family);
520 pango_font_description_set_weight (desc, GL_LABEL_TEXT (object)->priv->font_weight);
521 pango_font_description_set_style (desc, style);
522 pango_font_description_set_size (desc, font_size * PANGO_SCALE);
523 pango_layout_set_font_description (layout, desc);
524 pango_font_description_free (desc);
526 pango_layout_set_spacing (layout, font_size * (line_spacing-1) * PANGO_SCALE);
527 pango_layout_set_text (layout, text, -1);
528 pango_layout_get_size (layout, &iw, &ih);
529 *w = ltext->priv->w = iw / PANGO_SCALE + 2*GL_LABEL_TEXT_MARGIN;
530 *h = ltext->priv->h = ih / PANGO_SCALE;
531 ltext->priv->size_changed = FALSE;
533 g_object_unref (layout);
534 g_object_unref (context);
535 g_object_unref (fontmap);
538 gl_debug (DEBUG_LABEL, "END");
542 /*****************************************************************************/
543 /* Set font family method. */
544 /*****************************************************************************/
546 set_font_family (glLabelObject *object,
547 const gchar *font_family,
550 glLabelText *ltext = (glLabelText *)object;
551 gchar *good_font_family;
554 gl_debug (DEBUG_LABEL, "START");
556 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
557 g_return_if_fail (font_family);
559 good_font_family = gl_font_util_validate_family (font_family);
561 if (ltext->priv->font_family) {
562 if (strcmp (ltext->priv->font_family, good_font_family) == 0) {
563 g_free (good_font_family);
564 gl_debug (DEBUG_LABEL, "END (no change)");
567 g_free (ltext->priv->font_family);
572 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
573 gl_label_checkpoint (label, _("Font family"));
576 ltext->priv->font_family = g_strdup (good_font_family);
577 g_free (good_font_family);
579 gl_debug (DEBUG_LABEL, "new font family = %s", ltext->priv->font_family);
581 ltext->priv->size_changed = TRUE;
583 gl_font_history_model_add_family (gl_font_history, ltext->priv->font_family);
585 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
587 gl_debug (DEBUG_LABEL, "END");
591 /*****************************************************************************/
592 /* Set font size method. */
593 /*****************************************************************************/
595 set_font_size (glLabelObject *object,
599 glLabelText *ltext = (glLabelText *)object;
602 gl_debug (DEBUG_LABEL, "START");
604 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
606 if (ltext->priv->font_size != font_size)
610 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
611 gl_label_checkpoint (label, _("Font size"));
614 ltext->priv->size_changed = TRUE;
616 ltext->priv->font_size = font_size;
617 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
620 gl_debug (DEBUG_LABEL, "END");
624 /*****************************************************************************/
625 /* Set font weight method. */
626 /*****************************************************************************/
628 set_font_weight (glLabelObject *object,
629 PangoWeight font_weight,
632 glLabelText *ltext = (glLabelText *)object;
635 gl_debug (DEBUG_LABEL, "START");
637 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
639 if (ltext->priv->font_weight != font_weight)
643 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
644 gl_label_checkpoint (label, _("Font weight"));
647 ltext->priv->size_changed = TRUE;
649 ltext->priv->font_weight = font_weight;
650 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
653 gl_debug (DEBUG_LABEL, "END");
657 /*****************************************************************************/
658 /* Set font italic flag method. */
659 /*****************************************************************************/
661 set_font_italic_flag (glLabelObject *object,
662 gboolean font_italic_flag,
665 glLabelText *ltext = (glLabelText *)object;
668 gl_debug (DEBUG_LABEL, "START");
670 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
672 if (ltext->priv->font_italic_flag != font_italic_flag)
676 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
677 gl_label_checkpoint (label, _("Italic"));
680 ltext->priv->size_changed = TRUE;
682 ltext->priv->font_italic_flag = font_italic_flag;
683 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
686 gl_debug (DEBUG_LABEL, "END");
690 /*****************************************************************************/
691 /* Set text alignment method. */
692 /*****************************************************************************/
694 set_text_alignment (glLabelObject *object,
695 PangoAlignment text_alignment,
698 glLabelText *ltext = (glLabelText *)object;
701 gl_debug (DEBUG_LABEL, "START");
703 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
705 if (ltext->priv->align != text_alignment)
709 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
710 gl_label_checkpoint (label, _("Align text"));
713 ltext->priv->size_changed = TRUE;
715 ltext->priv->align = text_alignment;
716 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
719 gl_debug (DEBUG_LABEL, "END");
723 /*****************************************************************************/
724 /* Set text line spacing method. */
725 /*****************************************************************************/
727 set_text_line_spacing (glLabelObject *object,
728 gdouble line_spacing,
731 glLabelText *ltext = (glLabelText *)object;
734 gl_debug (DEBUG_LABEL, "START");
736 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
738 if (ltext->priv->line_spacing != line_spacing)
742 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
743 gl_label_checkpoint (label, _("Line spacing"));
746 ltext->priv->size_changed = TRUE;
748 ltext->priv->line_spacing = line_spacing;
749 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
752 gl_debug (DEBUG_LABEL, "END");
756 /*****************************************************************************/
757 /* Set text color method. */
758 /*****************************************************************************/
760 set_text_color (glLabelObject *object,
761 glColorNode *text_color_node,
764 glLabelText *ltext = (glLabelText *)object;
767 gl_debug (DEBUG_LABEL, "START");
769 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
771 if (!gl_color_node_equal (ltext->priv->color_node, text_color_node))
775 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
776 gl_label_checkpoint (label, _("Text color"));
779 gl_color_node_free (&(ltext->priv->color_node));
780 ltext->priv->color_node = gl_color_node_dup (text_color_node);
782 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
785 gl_debug (DEBUG_LABEL, "END");
789 /*****************************************************************************/
790 /* Get font family method. */
791 /*****************************************************************************/
793 get_font_family (glLabelObject *object)
795 glLabelText *ltext = (glLabelText *)object;
797 gl_debug (DEBUG_LABEL, "");
799 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
801 return g_strdup (ltext->priv->font_family);
805 /*****************************************************************************/
806 /* Get font size method. */
807 /*****************************************************************************/
809 get_font_size (glLabelObject *object)
811 glLabelText *ltext = (glLabelText *)object;
813 gl_debug (DEBUG_LABEL, "");
815 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), 0.0);
817 return ltext->priv->font_size;
821 /*****************************************************************************/
822 /* Get font weight method. */
823 /*****************************************************************************/
825 get_font_weight (glLabelObject *object)
827 glLabelText *ltext = (glLabelText *)object;
829 gl_debug (DEBUG_LABEL, "");
831 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), PANGO_WEIGHT_NORMAL);
833 return ltext->priv->font_weight;
837 /*****************************************************************************/
838 /* Get font italic flag method. */
839 /*****************************************************************************/
841 get_font_italic_flag (glLabelObject *object)
843 glLabelText *ltext = (glLabelText *)object;
845 gl_debug (DEBUG_LABEL, "");
847 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), FALSE);
849 return ltext->priv->font_italic_flag;
853 /*****************************************************************************/
854 /* Get text alignment method. */
855 /*****************************************************************************/
856 static PangoAlignment
857 get_text_alignment (glLabelObject *object)
859 glLabelText *ltext = (glLabelText *)object;
861 gl_debug (DEBUG_LABEL, "");
863 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), GTK_JUSTIFY_LEFT);
865 return ltext->priv->align;
869 /*****************************************************************************/
870 /* Get text line spacing method. */
871 /*****************************************************************************/
873 get_text_line_spacing (glLabelObject *object)
875 glLabelText *ltext = (glLabelText *)object;
877 gl_debug (DEBUG_LABEL, "");
879 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), 0.0);
881 return ltext->priv->line_spacing;
885 /*****************************************************************************/
886 /* Get text color method. */
887 /*****************************************************************************/
889 get_text_color (glLabelObject *object)
891 glLabelText *ltext = (glLabelText *)object;
893 gl_debug (DEBUG_LABEL, "");
895 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), 0);
897 return gl_color_node_dup (ltext->priv->color_node);
901 /*****************************************************************************/
902 /* Set auto shrink flag. */
903 /*****************************************************************************/
905 gl_label_text_set_auto_shrink (glLabelText *ltext,
906 gboolean auto_shrink,
911 gl_debug (DEBUG_LABEL, "BEGIN");
913 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
915 if (ltext->priv->auto_shrink != auto_shrink)
919 label = gl_label_object_get_parent (GL_LABEL_OBJECT (ltext));
920 gl_label_checkpoint (label, _("Auto shrink"));
923 ltext->priv->auto_shrink = auto_shrink;
924 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
927 gl_debug (DEBUG_LABEL, "END");
931 /*****************************************************************************/
932 /* Query auto shrink flag. */
933 /*****************************************************************************/
935 gl_label_text_get_auto_shrink (glLabelText *ltext)
937 gl_debug (DEBUG_LABEL, "");
939 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), 0);
941 return ltext->priv->auto_shrink;
945 /*****************************************************************************/
946 /* Draw object method. */
947 /*****************************************************************************/
949 draw_object (glLabelObject *object,
951 gboolean screen_flag,
952 glMergeRecord *record)
954 glColorNode *color_node;
957 gl_debug (DEBUG_LABEL, "START");
959 color_node = gl_label_object_get_text_color (object);
960 color = gl_color_node_expand (color_node, record);
961 if (color_node->field_flag && screen_flag)
963 color = GL_COLOR_MERGE_DEFAULT;
965 gl_color_node_free (&color_node);
967 draw_text_real (object, cr, screen_flag, record, color);
969 gl_debug (DEBUG_LABEL, "END");
973 /*****************************************************************************/
974 /* Draw shadow method. */
975 /*****************************************************************************/
977 draw_shadow (glLabelObject *object,
979 gboolean screen_flag,
980 glMergeRecord *record)
982 glColorNode *color_node;
984 glColorNode *shadow_color_node;
985 gdouble shadow_opacity;
988 gl_debug (DEBUG_LABEL, "START");
990 color_node = gl_label_object_get_text_color (object);
991 color = gl_color_node_expand (color_node, record);
992 if (color_node->field_flag && screen_flag)
994 color = GL_COLOR_MERGE_DEFAULT;
996 gl_color_node_free (&color_node);
998 shadow_color_node = gl_label_object_get_shadow_color (object);
999 if (shadow_color_node->field_flag)
1001 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
1003 shadow_opacity = gl_label_object_get_shadow_opacity (object);
1004 shadow_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, color);
1005 gl_color_node_free (&shadow_color_node);
1007 draw_text_real (object, cr, screen_flag, record, shadow_color);
1009 gl_debug (DEBUG_LABEL, "END");
1013 /*****************************************************************************/
1015 /*****************************************************************************/
1017 draw_text_real (glLabelObject *object,
1019 gboolean screen_flag,
1020 glMergeRecord *record,
1023 gdouble object_w, object_h;
1024 gdouble raw_w, raw_h;
1029 PangoWeight font_weight;
1030 gboolean font_italic_flag;
1031 gboolean auto_shrink;
1032 gdouble text_line_spacing;
1033 PangoAlignment alignment;
1035 PangoLayout *layout;
1036 PangoFontDescription *desc;
1037 gdouble scale_x, scale_y;
1038 cairo_font_options_t *font_options;
1039 PangoContext *context;
1042 gl_debug (DEBUG_LABEL, "START");
1044 gl_label_object_get_size (object, &object_w, &object_h);
1045 gl_label_object_get_raw_size (object, &raw_w, &raw_h);
1046 lines = gl_label_text_get_lines (GL_LABEL_TEXT (object));
1047 font_family = gl_label_object_get_font_family (object);
1048 font_size = gl_label_object_get_font_size (object) * FONT_SCALE;
1049 font_weight = gl_label_object_get_font_weight (object);
1050 font_italic_flag = gl_label_object_get_font_italic_flag (object);
1052 alignment = gl_label_object_get_text_alignment (object);
1054 gl_label_object_get_text_line_spacing (object);
1055 auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
1057 text = gl_text_node_lines_expand (lines, record);
1059 style = font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
1062 if (!screen_flag && record && auto_shrink && (raw_w != 0.0))
1064 font_size = auto_shrink_font_size (cr,
1075 * Workaround for pango Bug#341481.
1076 * Render font at device scale and scale font size accordingly.
1080 cairo_device_to_user_distance (cr, &scale_x, &scale_y);
1081 scale_x = fabs (scale_x);
1082 scale_y = fabs (scale_y);
1084 cairo_scale (cr, scale_x, scale_y);
1086 layout = pango_cairo_create_layout (cr);
1088 font_options = cairo_font_options_create ();
1089 cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
1090 context = pango_layout_get_context (layout);
1091 pango_cairo_context_set_font_options (context, font_options);
1092 cairo_font_options_destroy (font_options);
1094 desc = pango_font_description_new ();
1095 pango_font_description_set_family (desc, font_family);
1096 pango_font_description_set_weight (desc, font_weight);
1097 pango_font_description_set_style (desc, style);
1098 pango_font_description_set_size (desc, font_size * PANGO_SCALE / scale_x);
1099 pango_layout_set_font_description (layout, desc);
1100 pango_font_description_free (desc);
1102 pango_layout_set_text (layout, text, -1);
1103 pango_layout_set_spacing (layout, font_size * (text_line_spacing-1) * PANGO_SCALE / scale_x);
1106 pango_layout_set_width (layout, -1);
1110 pango_layout_set_width (layout, object_w * PANGO_SCALE / scale_x);
1112 pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
1113 pango_layout_set_alignment (layout, alignment);
1116 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
1117 cairo_move_to (cr, GL_LABEL_TEXT_MARGIN/scale_x, 0);
1118 pango_cairo_show_layout (cr, layout);
1122 g_object_unref (layout);
1125 gl_text_node_lines_free (&lines);
1126 g_free (font_family);
1128 gl_debug (DEBUG_LABEL, "END");
1132 /*****************************************************************************/
1133 /* Automatically shrink text size to fit within horizontal width. */
1134 /*****************************************************************************/
1136 auto_shrink_font_size (cairo_t *cr,
1144 PangoLayout *layout;
1145 PangoFontDescription *desc;
1147 gdouble layout_width;
1150 layout = pango_cairo_create_layout (cr);
1152 desc = pango_font_description_new ();
1153 pango_font_description_set_family (desc, family);
1154 pango_font_description_set_weight (desc, weight);
1155 pango_font_description_set_style (desc, style);
1156 pango_font_description_set_size (desc, size * PANGO_SCALE);
1158 pango_layout_set_font_description (layout, desc);
1159 pango_font_description_free (desc);
1161 pango_layout_set_text (layout, text, -1);
1162 pango_layout_set_width (layout, -1);
1163 pango_layout_get_size (layout, &iw, &ih);
1164 layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
1166 g_object_unref (layout);
1168 g_print ("Object w = %g, layout w = %g\n", width, layout_width);
1170 if ( layout_width > width )
1173 new_size = size * (width-2*GL_LABEL_TEXT_MARGIN)/layout_width;
1175 /* Round down to nearest 1/2 point */
1176 new_size = (int)(new_size*2.0) / 2.0;
1178 /* don't get ridiculously small. */
1193 /*****************************************************************************/
1194 /* Is object at coordinates? */
1195 /*****************************************************************************/
1197 object_at (glLabelObject *object,
1204 gl_label_object_get_size (object, &w, &h);
1206 cairo_rectangle (cr, 0.0, 0.0, w, h);
1208 if (cairo_in_fill (cr, x, y))
1219 * Local Variables: -- emacs
1221 * c-basic-offset: 8 -- emacs
1222 * tab-width: 8 -- emacs
1223 * indent-tabs-mode: nil -- emacs