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"
26 #include <pango/pango.h>
30 #include "font-util.h"
31 #include "font-history.h"
36 /*========================================================*/
37 /* Private macros and constants. */
38 /*========================================================*/
40 #define FONT_SCALE (72.0/96.0)
43 /*========================================================*/
45 /*========================================================*/
47 struct _glLabelTextPrivate {
48 GtkTextTagTable *tag_table;
49 GtkTextBuffer *buffer;
53 PangoWeight font_weight;
54 gboolean font_italic_flag;
56 glColorNode *color_node;
60 gboolean size_changed;
66 /*========================================================*/
67 /* Private globals. */
68 /*========================================================*/
71 /*========================================================*/
72 /* Private function prototypes. */
73 /*========================================================*/
75 static void gl_label_text_finalize (GObject *object);
77 static void copy (glLabelObject *dst_object,
78 glLabelObject *src_object);
80 static void buffer_changed_cb (GtkTextBuffer *textbuffer,
83 static void get_size (glLabelObject *object,
87 static void set_font_family (glLabelObject *object,
88 const gchar *font_family);
90 static void set_font_size (glLabelObject *object,
93 static void set_font_weight (glLabelObject *object,
94 PangoWeight font_weight);
96 static void set_font_italic_flag (glLabelObject *object,
97 gboolean font_italic_flag);
99 static void set_text_alignment (glLabelObject *object,
100 PangoAlignment text_alignment);
102 static void set_text_line_spacing (glLabelObject *object,
103 gdouble text_line_spacing);
105 static void set_text_color (glLabelObject *object,
106 glColorNode *text_color_node);
108 static gchar *get_font_family (glLabelObject *object);
110 static gdouble get_font_size (glLabelObject *object);
112 static PangoWeight get_font_weight (glLabelObject *object);
114 static gboolean get_font_italic_flag (glLabelObject *object);
116 static PangoAlignment get_text_alignment (glLabelObject *object);
118 static gdouble get_text_line_spacing (glLabelObject *object);
120 static glColorNode* get_text_color (glLabelObject *object);
122 static void draw_object (glLabelObject *object,
124 gboolean screen_flag,
125 glMergeRecord *record);
127 static void draw_shadow (glLabelObject *object,
129 gboolean screen_flag,
130 glMergeRecord *record);
132 static void draw_text_real (glLabelObject *object,
134 gboolean screen_flag,
135 glMergeRecord *record,
138 static gdouble auto_shrink_font_size (cairo_t *cr,
146 static gboolean object_at (glLabelObject *object,
152 /*****************************************************************************/
153 /* Object infrastructure. */
154 /*****************************************************************************/
155 G_DEFINE_TYPE (glLabelText, gl_label_text, GL_TYPE_LABEL_OBJECT);
158 /*****************************************************************************/
159 /* Class Init Function. */
160 /*****************************************************************************/
162 gl_label_text_class_init (glLabelTextClass *class)
164 GObjectClass *object_class = G_OBJECT_CLASS (class);
165 glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
167 gl_label_text_parent_class = g_type_class_peek_parent (class);
169 label_object_class->copy = copy;
171 label_object_class->get_size = get_size;
173 label_object_class->set_font_family = set_font_family;
174 label_object_class->set_font_size = set_font_size;
175 label_object_class->set_font_weight = set_font_weight;
176 label_object_class->set_font_italic_flag = set_font_italic_flag;
177 label_object_class->set_text_alignment = set_text_alignment;
178 label_object_class->set_text_line_spacing = set_text_line_spacing;
179 label_object_class->set_text_color = set_text_color;
180 label_object_class->get_font_family = get_font_family;
181 label_object_class->get_font_size = get_font_size;
182 label_object_class->get_font_weight = get_font_weight;
183 label_object_class->get_font_italic_flag = get_font_italic_flag;
184 label_object_class->get_text_alignment = get_text_alignment;
185 label_object_class->get_text_line_spacing = get_text_line_spacing;
186 label_object_class->get_text_color = get_text_color;
187 label_object_class->draw_object = draw_object;
188 label_object_class->draw_shadow = draw_shadow;
189 label_object_class->object_at = object_at;
191 object_class->finalize = gl_label_text_finalize;
195 /*****************************************************************************/
196 /* Object Instance Init Function. */
197 /*****************************************************************************/
199 gl_label_text_init (glLabelText *ltext)
201 ltext->priv = g_new0 (glLabelTextPrivate, 1);
203 ltext->priv->tag_table = gtk_text_tag_table_new ();
204 ltext->priv->buffer = gtk_text_buffer_new (ltext->priv->tag_table);
206 ltext->priv->size_changed = TRUE;
208 g_signal_connect (G_OBJECT(ltext->priv->buffer), "changed",
209 G_CALLBACK(buffer_changed_cb), ltext);
213 /*****************************************************************************/
214 /* Finalize Method. */
215 /*****************************************************************************/
217 gl_label_text_finalize (GObject *object)
219 glLabelText *ltext = GL_LABEL_TEXT (object);
221 g_return_if_fail (object && GL_IS_LABEL_TEXT (object));
223 g_object_unref (ltext->priv->tag_table);
224 g_object_unref (ltext->priv->buffer);
225 g_free (ltext->priv->font_family);
226 gl_color_node_free (&(ltext->priv->color_node));
227 g_free (ltext->priv);
229 G_OBJECT_CLASS (gl_label_text_parent_class)->finalize (object);
233 /*****************************************************************************/
234 /** New Object Generator. */
235 /*****************************************************************************/
237 gl_label_text_new (glLabel *label)
240 glColorNode *color_node;
242 ltext = g_object_new (gl_label_text_get_type(), NULL);
246 gl_label_object_set_parent (GL_LABEL_OBJECT(ltext), label);
248 color_node = gl_color_node_new_default ();
250 color_node->color = gl_label_get_default_text_color (label);
252 ltext->priv->font_family = gl_label_get_default_font_family (label);
253 ltext->priv->font_size = gl_label_get_default_font_size (label);
254 ltext->priv->font_weight = gl_label_get_default_font_weight (label);
255 ltext->priv->font_italic_flag = gl_label_get_default_font_italic_flag (label);
256 ltext->priv->align = gl_label_get_default_text_alignment (label);
257 ltext->priv->color_node = color_node;
258 ltext->priv->line_spacing = gl_label_get_default_text_line_spacing (label);
261 return G_OBJECT (ltext);
265 /*****************************************************************************/
266 /* Copy object contents. */
267 /*****************************************************************************/
269 copy (glLabelObject *dst_object,
270 glLabelObject *src_object)
272 glLabelText *ltext = (glLabelText *)src_object;
273 glLabelText *new_ltext = (glLabelText *)dst_object;
275 glColorNode *text_color_node;
277 gl_debug (DEBUG_LABEL, "START");
279 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
280 g_return_if_fail (new_ltext && GL_IS_LABEL_TEXT (new_ltext));
282 lines = gl_label_text_get_lines (ltext);
283 text_color_node = get_text_color (src_object);
284 gl_label_text_set_lines (new_ltext, lines);
286 new_ltext->priv->font_family = g_strdup (ltext->priv->font_family);
287 new_ltext->priv->font_size = ltext->priv->font_size;
288 new_ltext->priv->font_weight = ltext->priv->font_weight;
289 new_ltext->priv->font_italic_flag = ltext->priv->font_italic_flag;
290 set_text_color (dst_object, text_color_node);
291 new_ltext->priv->align = ltext->priv->align;
292 new_ltext->priv->line_spacing = ltext->priv->line_spacing;
293 new_ltext->priv->auto_shrink = ltext->priv->auto_shrink;
295 new_ltext->priv->size_changed = ltext->priv->size_changed;
296 new_ltext->priv->w = ltext->priv->w;
297 new_ltext->priv->h = ltext->priv->h;
299 gl_color_node_free (&text_color_node);
300 gl_text_node_lines_free (&lines);
302 gl_debug (DEBUG_LABEL, "END");
306 /*****************************************************************************/
307 /* Set object params. */
308 /*****************************************************************************/
310 gl_label_text_set_lines (glLabelText *ltext,
315 gl_debug (DEBUG_LABEL, "START");
317 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
319 text = gl_text_node_lines_expand (lines, NULL);
320 gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
323 ltext->priv->size_changed = TRUE;
325 gl_debug (DEBUG_LABEL, "END");
330 gl_label_text_set_text (glLabelText *ltext,
333 gl_debug (DEBUG_LABEL, "START");
335 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
337 gtk_text_buffer_set_text (ltext->priv->buffer, text, -1);
339 ltext->priv->size_changed = TRUE;
341 gl_debug (DEBUG_LABEL, "END");
345 /*****************************************************************************/
346 /* Get object params. */
347 /*****************************************************************************/
349 gl_label_text_get_buffer (glLabelText *ltext)
351 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
353 return ltext->priv->buffer;
358 gl_label_text_get_lines (glLabelText *ltext)
360 GtkTextIter start, end;
364 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
366 gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
367 text = gtk_text_buffer_get_text (ltext->priv->buffer,
368 &start, &end, FALSE);
369 lines = gl_text_node_lines_new_from_text (text);
377 gl_label_text_get_text (glLabelText *ltext)
379 GtkTextIter start, end;
382 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
384 gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
385 text = gtk_text_buffer_get_text (ltext->priv->buffer,
386 &start, &end, FALSE);
392 /*****************************************************************************/
393 /* Text buffer "changed" callback. */
394 /*****************************************************************************/
396 buffer_changed_cb (GtkTextBuffer *textbuffer,
399 ltext->priv->size_changed = TRUE;
401 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
405 /*****************************************************************************/
406 /* Get object size method. */
407 /*****************************************************************************/
409 get_size (glLabelObject *object,
413 glLabelText *ltext = (glLabelText *)object;
414 PangoFontMap *fontmap;
415 PangoContext *context;
416 cairo_font_options_t *options;
419 PangoFontDescription *desc;
421 gdouble line_spacing;
422 GtkTextIter start, end;
424 gdouble w_parent, h_parent;
427 gl_debug (DEBUG_LABEL, "START");
429 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
431 gl_label_object_get_raw_size (object, &w_parent, &h_parent);
433 if ( (w_parent != 0.0) || (h_parent != 0.0) ) {
439 if (!ltext->priv->size_changed)
446 font_size = GL_LABEL_TEXT (object)->priv->font_size * FONT_SCALE;
447 line_spacing = GL_LABEL_TEXT (object)->priv->line_spacing;
449 gtk_text_buffer_get_bounds (ltext->priv->buffer, &start, &end);
450 text = gtk_text_buffer_get_text (ltext->priv->buffer,
451 &start, &end, FALSE);
454 fontmap = pango_cairo_font_map_new ();
455 context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
456 options = cairo_font_options_create ();
457 cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
458 pango_cairo_context_set_font_options (context, options);
459 cairo_font_options_destroy (options);
461 layout = pango_layout_new (context);
463 style = GL_LABEL_TEXT (object)->priv->font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
465 desc = pango_font_description_new ();
466 pango_font_description_set_family (desc, GL_LABEL_TEXT (object)->priv->font_family);
467 pango_font_description_set_weight (desc, GL_LABEL_TEXT (object)->priv->font_weight);
468 pango_font_description_set_style (desc, style);
469 pango_font_description_set_size (desc, font_size * PANGO_SCALE);
470 pango_layout_set_font_description (layout, desc);
471 pango_font_description_free (desc);
473 pango_layout_set_spacing (layout, font_size * (line_spacing-1) * PANGO_SCALE);
474 pango_layout_set_text (layout, text, -1);
475 pango_layout_get_size (layout, &iw, &ih);
476 *w = ltext->priv->w = iw / PANGO_SCALE + 2*GL_LABEL_TEXT_MARGIN;
477 *h = ltext->priv->h = ih / PANGO_SCALE;
478 ltext->priv->size_changed = FALSE;
480 g_object_unref (layout);
481 g_object_unref (context);
482 g_object_unref (fontmap);
485 gl_debug (DEBUG_LABEL, "END");
489 /*****************************************************************************/
490 /* Set font family method. */
491 /*****************************************************************************/
493 set_font_family (glLabelObject *object,
494 const gchar *font_family)
496 glLabelText *ltext = (glLabelText *)object;
497 gchar *good_font_family;
499 gl_debug (DEBUG_LABEL, "START");
501 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
502 g_return_if_fail (font_family);
504 good_font_family = gl_font_util_validate_family (font_family);
506 if (ltext->priv->font_family) {
507 if (strcmp (ltext->priv->font_family, good_font_family) == 0) {
508 g_free (good_font_family);
509 gl_debug (DEBUG_LABEL, "END (no change)");
512 g_free (ltext->priv->font_family);
514 ltext->priv->font_family = g_strdup (good_font_family);
515 g_free (good_font_family);
517 gl_debug (DEBUG_LABEL, "new font family = %s", ltext->priv->font_family);
519 ltext->priv->size_changed = TRUE;
521 gl_font_history_model_add_family (gl_font_history, ltext->priv->font_family);
523 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
525 gl_debug (DEBUG_LABEL, "END");
529 /*****************************************************************************/
530 /* Set font size method. */
531 /*****************************************************************************/
533 set_font_size (glLabelObject *object,
536 glLabelText *ltext = (glLabelText *)object;
538 gl_debug (DEBUG_LABEL, "START");
540 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
542 if (ltext->priv->font_size != font_size) {
544 ltext->priv->size_changed = TRUE;
546 ltext->priv->font_size = font_size;
547 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
551 gl_debug (DEBUG_LABEL, "END");
555 /*****************************************************************************/
556 /* Set font weight method. */
557 /*****************************************************************************/
559 set_font_weight (glLabelObject *object,
560 PangoWeight font_weight)
562 glLabelText *ltext = (glLabelText *)object;
564 gl_debug (DEBUG_LABEL, "START");
566 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
568 if (ltext->priv->font_weight != font_weight) {
570 ltext->priv->size_changed = TRUE;
572 ltext->priv->font_weight = font_weight;
573 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
577 gl_debug (DEBUG_LABEL, "END");
581 /*****************************************************************************/
582 /* Set font italic flag method. */
583 /*****************************************************************************/
585 set_font_italic_flag (glLabelObject *object,
586 gboolean font_italic_flag)
588 glLabelText *ltext = (glLabelText *)object;
590 gl_debug (DEBUG_LABEL, "START");
592 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
594 if (ltext->priv->font_italic_flag != font_italic_flag) {
596 ltext->priv->size_changed = TRUE;
598 ltext->priv->font_italic_flag = font_italic_flag;
599 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
603 gl_debug (DEBUG_LABEL, "END");
607 /*****************************************************************************/
608 /* Set text alignment method. */
609 /*****************************************************************************/
611 set_text_alignment (glLabelObject *object,
612 PangoAlignment text_alignment)
614 glLabelText *ltext = (glLabelText *)object;
616 gl_debug (DEBUG_LABEL, "START");
618 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
620 if (ltext->priv->align != text_alignment) {
622 ltext->priv->size_changed = TRUE;
624 ltext->priv->align = text_alignment;
625 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
629 gl_debug (DEBUG_LABEL, "END");
633 /*****************************************************************************/
634 /* Set text line spacing method. */
635 /*****************************************************************************/
637 set_text_line_spacing (glLabelObject *object,
638 gdouble line_spacing)
640 glLabelText *ltext = (glLabelText *)object;
642 gl_debug (DEBUG_LABEL, "START");
644 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
646 if (ltext->priv->line_spacing != line_spacing) {
648 ltext->priv->size_changed = TRUE;
650 ltext->priv->line_spacing = line_spacing;
651 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
655 gl_debug (DEBUG_LABEL, "END");
659 /*****************************************************************************/
660 /* Set text color method. */
661 /*****************************************************************************/
663 set_text_color (glLabelObject *object,
664 glColorNode *text_color_node)
666 glLabelText *ltext = (glLabelText *)object;
668 gl_debug (DEBUG_LABEL, "START");
670 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
672 if (!gl_color_node_equal (ltext->priv->color_node, text_color_node)) {
674 gl_color_node_free (&(ltext->priv->color_node));
675 ltext->priv->color_node = gl_color_node_dup (text_color_node);
677 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
681 gl_debug (DEBUG_LABEL, "END");
685 /*****************************************************************************/
686 /* Get font family method. */
687 /*****************************************************************************/
689 get_font_family (glLabelObject *object)
691 glLabelText *ltext = (glLabelText *)object;
693 gl_debug (DEBUG_LABEL, "");
695 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), NULL);
697 return g_strdup (ltext->priv->font_family);
701 /*****************************************************************************/
702 /* Get font size method. */
703 /*****************************************************************************/
705 get_font_size (glLabelObject *object)
707 glLabelText *ltext = (glLabelText *)object;
709 gl_debug (DEBUG_LABEL, "");
711 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), 0.0);
713 return ltext->priv->font_size;
717 /*****************************************************************************/
718 /* Get font weight method. */
719 /*****************************************************************************/
721 get_font_weight (glLabelObject *object)
723 glLabelText *ltext = (glLabelText *)object;
725 gl_debug (DEBUG_LABEL, "");
727 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), PANGO_WEIGHT_NORMAL);
729 return ltext->priv->font_weight;
733 /*****************************************************************************/
734 /* Get font italic flag method. */
735 /*****************************************************************************/
737 get_font_italic_flag (glLabelObject *object)
739 glLabelText *ltext = (glLabelText *)object;
741 gl_debug (DEBUG_LABEL, "");
743 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), FALSE);
745 return ltext->priv->font_italic_flag;
749 /*****************************************************************************/
750 /* Get text alignment method. */
751 /*****************************************************************************/
752 static PangoAlignment
753 get_text_alignment (glLabelObject *object)
755 glLabelText *ltext = (glLabelText *)object;
757 gl_debug (DEBUG_LABEL, "");
759 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), GTK_JUSTIFY_LEFT);
761 return ltext->priv->align;
765 /*****************************************************************************/
766 /* Get text line spacing method. */
767 /*****************************************************************************/
769 get_text_line_spacing (glLabelObject *object)
771 glLabelText *ltext = (glLabelText *)object;
773 gl_debug (DEBUG_LABEL, "");
775 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), 0.0);
777 return ltext->priv->line_spacing;
781 /*****************************************************************************/
782 /* Get text color method. */
783 /*****************************************************************************/
785 get_text_color (glLabelObject *object)
787 glLabelText *ltext = (glLabelText *)object;
789 gl_debug (DEBUG_LABEL, "");
791 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), 0);
793 return gl_color_node_dup (ltext->priv->color_node);
797 /*****************************************************************************/
798 /* Set auto shrink flag. */
799 /*****************************************************************************/
801 gl_label_text_set_auto_shrink (glLabelText *ltext,
802 gboolean auto_shrink)
804 gl_debug (DEBUG_LABEL, "BEGIN");
806 g_return_if_fail (ltext && GL_IS_LABEL_TEXT (ltext));
808 if (ltext->priv->auto_shrink != auto_shrink) {
810 ltext->priv->auto_shrink = auto_shrink;
811 gl_label_object_emit_changed (GL_LABEL_OBJECT(ltext));
815 gl_debug (DEBUG_LABEL, "END");
819 /*****************************************************************************/
820 /* Query auto shrink flag. */
821 /*****************************************************************************/
823 gl_label_text_get_auto_shrink (glLabelText *ltext)
825 gl_debug (DEBUG_LABEL, "");
827 g_return_val_if_fail (ltext && GL_IS_LABEL_TEXT (ltext), 0);
829 return ltext->priv->auto_shrink;
833 /*****************************************************************************/
834 /* Draw object method. */
835 /*****************************************************************************/
837 draw_object (glLabelObject *object,
839 gboolean screen_flag,
840 glMergeRecord *record)
842 glColorNode *color_node;
845 gl_debug (DEBUG_LABEL, "START");
847 color_node = gl_label_object_get_text_color (object);
848 color = gl_color_node_expand (color_node, record);
849 if (color_node->field_flag && screen_flag)
851 color = GL_COLOR_MERGE_DEFAULT;
853 gl_color_node_free (&color_node);
855 draw_text_real (object, cr, screen_flag, record, color);
857 gl_debug (DEBUG_LABEL, "END");
861 /*****************************************************************************/
862 /* Draw shadow method. */
863 /*****************************************************************************/
865 draw_shadow (glLabelObject *object,
867 gboolean screen_flag,
868 glMergeRecord *record)
870 glColorNode *color_node;
872 glColorNode *shadow_color_node;
873 gdouble shadow_opacity;
876 gl_debug (DEBUG_LABEL, "START");
878 color_node = gl_label_object_get_text_color (object);
879 color = gl_color_node_expand (color_node, record);
880 if (color_node->field_flag && screen_flag)
882 color = GL_COLOR_MERGE_DEFAULT;
884 gl_color_node_free (&color_node);
886 shadow_color_node = gl_label_object_get_shadow_color (object);
887 if (shadow_color_node->field_flag)
889 shadow_color_node->color = GL_COLOR_SHADOW_MERGE_DEFAULT;
891 shadow_opacity = gl_label_object_get_shadow_opacity (object);
892 shadow_color = gl_color_shadow (shadow_color_node->color, shadow_opacity, color);
893 gl_color_node_free (&shadow_color_node);
895 draw_text_real (object, cr, screen_flag, record, shadow_color);
897 gl_debug (DEBUG_LABEL, "END");
901 /*****************************************************************************/
903 /*****************************************************************************/
905 draw_text_real (glLabelObject *object,
907 gboolean screen_flag,
908 glMergeRecord *record,
911 gdouble object_w, object_h;
912 gdouble raw_w, raw_h;
917 PangoWeight font_weight;
918 gboolean font_italic_flag;
919 gboolean auto_shrink;
920 gdouble text_line_spacing;
921 PangoAlignment alignment;
924 PangoFontDescription *desc;
925 gdouble scale_x, scale_y;
926 cairo_font_options_t *font_options;
927 PangoContext *context;
930 gl_debug (DEBUG_LABEL, "START");
932 gl_label_object_get_size (object, &object_w, &object_h);
933 gl_label_object_get_raw_size (object, &raw_w, &raw_h);
934 lines = gl_label_text_get_lines (GL_LABEL_TEXT (object));
935 font_family = gl_label_object_get_font_family (object);
936 font_size = gl_label_object_get_font_size (object) * FONT_SCALE;
937 font_weight = gl_label_object_get_font_weight (object);
938 font_italic_flag = gl_label_object_get_font_italic_flag (object);
940 alignment = gl_label_object_get_text_alignment (object);
942 gl_label_object_get_text_line_spacing (object);
943 auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
945 text = gl_text_node_lines_expand (lines, record);
947 style = font_italic_flag ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
950 if (!screen_flag && record && auto_shrink && (raw_w != 0.0))
952 font_size = auto_shrink_font_size (cr,
963 * Workaround for pango Bug#341481.
964 * Render font at device scale and scale font size accordingly.
968 cairo_device_to_user_distance (cr, &scale_x, &scale_y);
969 scale_x = fabs (scale_x);
970 scale_y = fabs (scale_y);
972 cairo_scale (cr, scale_x, scale_y);
974 layout = pango_cairo_create_layout (cr);
976 font_options = cairo_font_options_create ();
977 cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
978 context = pango_layout_get_context (layout);
979 pango_cairo_context_set_font_options (context, font_options);
980 cairo_font_options_destroy (font_options);
982 desc = pango_font_description_new ();
983 pango_font_description_set_family (desc, font_family);
984 pango_font_description_set_weight (desc, font_weight);
985 pango_font_description_set_style (desc, style);
986 pango_font_description_set_size (desc, font_size * PANGO_SCALE / scale_x);
987 pango_layout_set_font_description (layout, desc);
988 pango_font_description_free (desc);
990 pango_layout_set_text (layout, text, -1);
991 pango_layout_set_spacing (layout, font_size * (text_line_spacing-1) * PANGO_SCALE / scale_x);
994 pango_layout_set_width (layout, -1);
998 pango_layout_set_width (layout, object_w * PANGO_SCALE / scale_x);
1000 pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
1001 pango_layout_set_alignment (layout, alignment);
1004 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
1005 cairo_move_to (cr, GL_LABEL_TEXT_MARGIN/scale_x, 0);
1006 pango_cairo_show_layout (cr, layout);
1010 g_object_unref (layout);
1013 gl_text_node_lines_free (&lines);
1014 g_free (font_family);
1016 gl_debug (DEBUG_LABEL, "END");
1020 /*****************************************************************************/
1021 /* Automatically shrink text size to fit within horizontal width. */
1022 /*****************************************************************************/
1024 auto_shrink_font_size (cairo_t *cr,
1032 PangoLayout *layout;
1033 PangoFontDescription *desc;
1035 gdouble layout_width;
1038 layout = pango_cairo_create_layout (cr);
1040 desc = pango_font_description_new ();
1041 pango_font_description_set_family (desc, family);
1042 pango_font_description_set_weight (desc, weight);
1043 pango_font_description_set_style (desc, style);
1044 pango_font_description_set_size (desc, size * PANGO_SCALE);
1046 pango_layout_set_font_description (layout, desc);
1047 pango_font_description_free (desc);
1049 pango_layout_set_text (layout, text, -1);
1050 pango_layout_set_width (layout, -1);
1051 pango_layout_get_size (layout, &iw, &ih);
1052 layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
1054 g_object_unref (layout);
1056 g_print ("Object w = %g, layout w = %g\n", width, layout_width);
1058 if ( layout_width > width )
1061 new_size = size * (width-2*GL_LABEL_TEXT_MARGIN)/layout_width;
1063 /* Round down to nearest 1/2 point */
1064 new_size = (int)(new_size*2.0) / 2.0;
1066 /* don't get ridiculously small. */
1081 /*****************************************************************************/
1082 /* Is object at coordinates? */
1083 /*****************************************************************************/
1085 object_at (glLabelObject *object,
1092 gl_label_object_get_size (object, &w, &h);
1094 cairo_rectangle (cr, 0.0, 0.0, w, h);
1096 if (cairo_in_fill (cr, x, y))
1107 * Local Variables: -- emacs
1109 * c-basic-offset: 8 -- emacs
1110 * tab-width: 8 -- emacs
1111 * indent-tabs-mode: nil -- emacs