TextLine first implementation.
[dia.git] / lib / textline.c
blob6955c47853c16528a9858611410edda1621982c3
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <glib.h>
24 #include <math.h>
26 #include <gdk/gdkkeysyms.h>
28 #include "propinternals.h"
29 #include "text.h"
30 #include "message.h"
31 #include "diarenderer.h"
32 #include "diagramdata.h"
33 #include "objchange.h"
34 #include "textline.h"
36 static void text_line_dirty_cache(TextLine *text_line);
37 static void text_line_cache_values(TextLine *text_line);
39 /** Sets this object to display a particular string.
40 * @param text_line The object to change.
41 * @param string The string to display. This string will be copied.
43 void
44 text_line_set_string(TextLine *text_line, const gchar *string)
46 if (text_line->chars == NULL ||
47 strcmp(text_line->chars, string)) {
48 if (text_line->chars != NULL) {
49 g_free(text_line->chars);
52 text_line->chars = g_strdup(string);
54 text_line_dirty_cache(text_line);
58 /** Sets the font used by this object.
59 * @param text_line The object to change.
60 * @param font The font to use for displaying this object.
62 void
63 text_line_set_font(TextLine *text_line, DiaFont *font)
65 if (text_line->font != font) {
66 DiaFont *old_font = text_line->font;
67 dia_font_ref(font);
68 text_line->font = font;
69 if (old_font != NULL) {
70 dia_font_unref(old_font);
72 text_line_dirty_cache(text_line);
76 /** Sets the font height used by this object.
77 * @param text_line The object to change.
78 * @param height The font height to use for displaying this object
79 * (in cm, from baseline to baseline)
81 void
82 text_line_set_height(TextLine *text_line, real height)
84 if (fabs(text_line->height - height) > 0.00001) {
85 text_line->height = height;
86 text_line_dirty_cache(text_line);
90 /** Creates a new TextLine object from its components.
91 * @param string the string to display
92 * @param font the font to display the string with.
93 * @param height the height of the font, in cm from baseline to baseline.
95 TextLine *
96 text_line_new(const gchar *string, DiaFont *font, real height)
98 TextLine *text_line = g_new0(TextLine, 1);
100 text_line_set_string(text_line, string);
101 text_line_set_font(text_line, font);
102 text_line_set_height(text_line, height);
104 return text_line;
107 TextLine *
108 text_line_copy(TextLine *text_line)
110 return text_line_new(text_line->chars, text_line->font, text_line->height);
113 /** Destroy a text_line object, deallocating all memory used and unreffing
114 * reffed objects.
115 * @param text_line the object to kill.
117 void
118 text_line_destroy(TextLine *text_line)
120 if (text_line->chars != NULL) {
121 g_free(text_line->chars);
123 if (text_line->font != NULL) {
124 dia_font_unref(text_line->font);
126 /* TODO: Handle renderer's cached content. */
127 g_free(text_line);
130 /** Calculate the bounding box size of this object. Since a text object has no
131 * position or alignment, this collapses to just a size.
132 * @param text_line
133 * @param size A place to store the width and height of the text.
135 void
136 text_line_calc_boundingbox_size(TextLine *text_line, Point *size)
138 text_line_cache_values(text_line);
140 size->x = text_line->width;
141 size->y = text_line->ascent + text_line->descent;
144 /** Draw a line of text at a given position and in a given color.
145 * @param renderer
146 * @param text_line
147 * @param pos
148 * @param color
150 void
151 text_line_draw(DiaRenderer *renderer, TextLine *text_line,
152 Point *pos, Color *color)
154 #ifdef DIRECT_TEXT_LINE
155 DIA_RENDERER_GET_CLASS(renderer)->draw_text_line(renderer,
156 text_line,
157 pos, color);
158 #else
159 DIA_RENDERER_GET_CLASS(renderer)->set_font(renderer, text_line->font,
160 text_line->height);
161 DIA_RENDERER_GET_CLASS(renderer)->draw_string(renderer,
162 text_line->chars,
163 pos, ALIGN_LEFT, color);
164 #endif
167 gchar *
168 text_line_get_string(TextLine *text_line)
170 return text_line->chars;
173 DiaFont *
174 text_line_get_font(TextLine *text_line)
176 return text_line->font;
179 real
180 text_line_get_height(TextLine *text_line)
182 return text_line->height;
185 real
186 text_line_get_width(TextLine *text_line)
188 text_line_cache_values(text_line);
189 return text_line->width;
192 real
193 text_line_get_ascent(TextLine *text_line)
195 text_line_cache_values(text_line);
196 return text_line->ascent;
199 real
200 text_line_get_descent(TextLine *text_line)
202 text_line_cache_values(text_line);
203 return text_line->descent;
206 /* **** Private functions **** */
207 /** Mark this object as needing update before usage.
208 * @param text_line the object that has changed.
210 static void
211 text_line_dirty_cache(TextLine *text_line)
213 text_line->clean = FALSE;
216 static void
217 text_line_cache_values(TextLine *text_line)
219 if (!text_line->clean ||
220 text_line->chars != text_line->chars_cache ||
221 text_line->font != text_line->font_cache ||
222 text_line->height != text_line->height_cache) {
223 int n_offsets;
225 if (text_line->offsets != NULL) {
226 g_free(text_line->offsets);
228 if (text_line->chars == NULL ||
229 text_line->chars[0] == '\0') {
230 text_line->offsets = g_new(real, 0);
231 text_line->ascent = text_line->height * .5;
232 text_line->descent = text_line->height * .5;
233 text_line->width = 0;
234 } else {
235 text_line->offsets =
236 dia_font_get_sizes(text_line->chars, text_line->font, text_line->height,
237 &text_line->width, &text_line->ascent,
238 &text_line->descent, &n_offsets);
240 text_line->clean = TRUE;
241 text_line->chars_cache = text_line->chars;
242 text_line->font_cache = text_line->font;
243 text_line->height_cache = text_line->height;