1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ |
---|
2 | /* |
---|
3 | * $Id: gnome-canvas-text.c,v 1.1.1.1 2003-01-04 19:43:26 ghudson Exp $ |
---|
4 | * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation |
---|
5 | * All rights reserved. |
---|
6 | * |
---|
7 | * This file is part of the Gnome Library. |
---|
8 | * |
---|
9 | * The Gnome Library is free software; you can redistribute it and/or |
---|
10 | * modify it under the terms of the GNU Library General Public License as |
---|
11 | * published by the Free Software Foundation; either version 2 of the |
---|
12 | * License, or (at your option) any later version. |
---|
13 | * |
---|
14 | * The Gnome Library is distributed in the hope that it will be useful, |
---|
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
17 | * Library General Public License for more details. |
---|
18 | * |
---|
19 | * You should have received a copy of the GNU Library General Public |
---|
20 | * License along with the Gnome Library; see the file COPYING.LIB. If not, |
---|
21 | * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
22 | * Boston, MA 02111-1307, USA. |
---|
23 | */ |
---|
24 | /* |
---|
25 | @NOTATION@ |
---|
26 | */ |
---|
27 | /* Text item type for GnomeCanvas widget |
---|
28 | * |
---|
29 | * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas |
---|
30 | * widget. Tk is copyrighted by the Regents of the University of California, |
---|
31 | * Sun Microsystems, and other parties. |
---|
32 | * |
---|
33 | * |
---|
34 | * Author: Federico Mena <federico@nuclecu.unam.mx> |
---|
35 | * Port to Pango co-done by Gergõ Érdi <cactus@cactus.rulez.org> |
---|
36 | */ |
---|
37 | |
---|
38 | #include <config.h> |
---|
39 | #include <math.h> |
---|
40 | #include <string.h> |
---|
41 | #include "gnome-canvas-text.h" |
---|
42 | #include <pango/pangoft2.h> |
---|
43 | |
---|
44 | #include "libart_lgpl/art_affine.h" |
---|
45 | #include "libart_lgpl/art_rgb_a_affine.h" |
---|
46 | #include "libart_lgpl/art_rgb.h" |
---|
47 | #include "libart_lgpl/art_rgb_bitmap_affine.h" |
---|
48 | #include "gnome-canvas-util.h" |
---|
49 | #include "gnome-canvas-i18n.h" |
---|
50 | |
---|
51 | |
---|
52 | |
---|
53 | /* Object argument IDs */ |
---|
54 | enum { |
---|
55 | PROP_0, |
---|
56 | |
---|
57 | /* Text contents */ |
---|
58 | PROP_TEXT, |
---|
59 | PROP_MARKUP, |
---|
60 | |
---|
61 | /* Position */ |
---|
62 | PROP_X, |
---|
63 | PROP_Y, |
---|
64 | |
---|
65 | /* Font */ |
---|
66 | PROP_FONT, |
---|
67 | PROP_FONT_DESC, |
---|
68 | PROP_FAMILY, PROP_FAMILY_SET, |
---|
69 | |
---|
70 | /* Style */ |
---|
71 | PROP_ATTRIBUTES, |
---|
72 | PROP_STYLE, PROP_STYLE_SET, |
---|
73 | PROP_VARIANT, PROP_VARIANT_SET, |
---|
74 | PROP_WEIGHT, PROP_WEIGHT_SET, |
---|
75 | PROP_STRETCH, PROP_STRETCH_SET, |
---|
76 | PROP_SIZE, PROP_SIZE_SET, |
---|
77 | PROP_SIZE_POINTS, |
---|
78 | PROP_STRIKETHROUGH, PROP_STRIKETHROUGH_SET, |
---|
79 | PROP_UNDERLINE, PROP_UNDERLINE_SET, |
---|
80 | PROP_RISE, PROP_RISE_SET, |
---|
81 | PROP_SCALE, PROP_SCALE_SET, |
---|
82 | |
---|
83 | /* Clipping */ |
---|
84 | PROP_ANCHOR, |
---|
85 | PROP_JUSTIFICATION, |
---|
86 | PROP_CLIP_WIDTH, |
---|
87 | PROP_CLIP_HEIGHT, |
---|
88 | PROP_CLIP, |
---|
89 | PROP_X_OFFSET, |
---|
90 | PROP_Y_OFFSET, |
---|
91 | |
---|
92 | /* Coloring */ |
---|
93 | PROP_FILL_COLOR, |
---|
94 | PROP_FILL_COLOR_GDK, |
---|
95 | PROP_FILL_COLOR_RGBA, |
---|
96 | PROP_FILL_STIPPLE, |
---|
97 | |
---|
98 | /* Rendered size accessors */ |
---|
99 | PROP_TEXT_WIDTH, |
---|
100 | PROP_TEXT_HEIGHT |
---|
101 | }; |
---|
102 | |
---|
103 | struct _GnomeCanvasTextPrivate { |
---|
104 | guint render_dirty : 1; |
---|
105 | FT_Bitmap bitmap; |
---|
106 | }; |
---|
107 | |
---|
108 | |
---|
109 | static void gnome_canvas_text_class_init (GnomeCanvasTextClass *class); |
---|
110 | static void gnome_canvas_text_init (GnomeCanvasText *text); |
---|
111 | static void gnome_canvas_text_destroy (GtkObject *object); |
---|
112 | static void gnome_canvas_text_set_property (GObject *object, |
---|
113 | guint param_id, |
---|
114 | const GValue *value, |
---|
115 | GParamSpec *pspec); |
---|
116 | static void gnome_canvas_text_get_property (GObject *object, |
---|
117 | guint param_id, |
---|
118 | GValue *value, |
---|
119 | GParamSpec *pspec); |
---|
120 | |
---|
121 | static void gnome_canvas_text_update (GnomeCanvasItem *item, double *affine, |
---|
122 | ArtSVP *clip_path, int flags); |
---|
123 | static void gnome_canvas_text_realize (GnomeCanvasItem *item); |
---|
124 | static void gnome_canvas_text_unrealize (GnomeCanvasItem *item); |
---|
125 | static void gnome_canvas_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, |
---|
126 | int x, int y, int width, int height); |
---|
127 | static double gnome_canvas_text_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, |
---|
128 | GnomeCanvasItem **actual_item); |
---|
129 | static void gnome_canvas_text_bounds (GnomeCanvasItem *item, |
---|
130 | double *x1, double *y1, double *x2, double *y2); |
---|
131 | static void gnome_canvas_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf); |
---|
132 | |
---|
133 | static void gnome_canvas_text_set_markup (GnomeCanvasText *textitem, |
---|
134 | const gchar *markup); |
---|
135 | |
---|
136 | static void gnome_canvas_text_set_font_desc (GnomeCanvasText *textitem, |
---|
137 | PangoFontDescription *font_desc); |
---|
138 | |
---|
139 | static void gnome_canvas_text_apply_font_desc (GnomeCanvasText *textitem); |
---|
140 | static void gnome_canvas_text_apply_attributes (GnomeCanvasText *textitem); |
---|
141 | |
---|
142 | static void add_attr (PangoAttrList *attr_list, |
---|
143 | PangoAttribute *attr); |
---|
144 | |
---|
145 | static GnomeCanvasItemClass *parent_class; |
---|
146 | |
---|
147 | |
---|
148 | |
---|
149 | /** |
---|
150 | * gnome_canvas_text_get_type: |
---|
151 | * @void: |
---|
152 | * |
---|
153 | * Registers the &GnomeCanvasText class if necessary, and returns the type ID |
---|
154 | * associated to it. |
---|
155 | * |
---|
156 | * Return value: The type ID of the &GnomeCanvasText class. |
---|
157 | **/ |
---|
158 | GType |
---|
159 | gnome_canvas_text_get_type (void) |
---|
160 | { |
---|
161 | static GType text_type; |
---|
162 | |
---|
163 | if (!text_type) { |
---|
164 | static const GTypeInfo object_info = { |
---|
165 | sizeof (GnomeCanvasTextClass), |
---|
166 | (GBaseInitFunc) NULL, |
---|
167 | (GBaseFinalizeFunc) NULL, |
---|
168 | (GClassInitFunc) gnome_canvas_text_class_init, |
---|
169 | (GClassFinalizeFunc) NULL, |
---|
170 | NULL, /* class_data */ |
---|
171 | sizeof (GnomeCanvasText), |
---|
172 | 0, /* n_preallocs */ |
---|
173 | (GInstanceInitFunc) gnome_canvas_text_init, |
---|
174 | NULL /* value_table */ |
---|
175 | }; |
---|
176 | |
---|
177 | text_type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM, "GnomeCanvasText", |
---|
178 | &object_info, 0); |
---|
179 | } |
---|
180 | |
---|
181 | return text_type; |
---|
182 | } |
---|
183 | |
---|
184 | /* Class initialization function for the text item */ |
---|
185 | static void |
---|
186 | gnome_canvas_text_class_init (GnomeCanvasTextClass *class) |
---|
187 | { |
---|
188 | GObjectClass *gobject_class; |
---|
189 | GtkObjectClass *object_class; |
---|
190 | GnomeCanvasItemClass *item_class; |
---|
191 | |
---|
192 | gobject_class = (GObjectClass *) class; |
---|
193 | object_class = (GtkObjectClass *) class; |
---|
194 | item_class = (GnomeCanvasItemClass *) class; |
---|
195 | |
---|
196 | parent_class = g_type_class_peek_parent (class); |
---|
197 | |
---|
198 | gobject_class->set_property = gnome_canvas_text_set_property; |
---|
199 | gobject_class->get_property = gnome_canvas_text_get_property; |
---|
200 | |
---|
201 | /* Text */ |
---|
202 | g_object_class_install_property |
---|
203 | (gobject_class, |
---|
204 | PROP_TEXT, |
---|
205 | g_param_spec_string ("text", |
---|
206 | _("Text"), |
---|
207 | _("Text to render"), |
---|
208 | NULL, |
---|
209 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
210 | |
---|
211 | g_object_class_install_property |
---|
212 | (gobject_class, |
---|
213 | PROP_MARKUP, |
---|
214 | g_param_spec_string ("markup", |
---|
215 | _("Markup"), |
---|
216 | _("Marked up text to render"), |
---|
217 | NULL, |
---|
218 | (G_PARAM_WRITABLE))); |
---|
219 | |
---|
220 | /* Position */ |
---|
221 | g_object_class_install_property |
---|
222 | (gobject_class, |
---|
223 | PROP_X, |
---|
224 | g_param_spec_double ("x", NULL, NULL, |
---|
225 | -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, |
---|
226 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
227 | |
---|
228 | g_object_class_install_property |
---|
229 | (gobject_class, |
---|
230 | PROP_Y, |
---|
231 | g_param_spec_double ("y", NULL, NULL, |
---|
232 | -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, |
---|
233 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
234 | |
---|
235 | |
---|
236 | /* Font */ |
---|
237 | g_object_class_install_property |
---|
238 | (gobject_class, |
---|
239 | PROP_FONT, |
---|
240 | g_param_spec_string ("font", |
---|
241 | _("Font"), |
---|
242 | _("Font description as a string"), |
---|
243 | NULL, |
---|
244 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
245 | |
---|
246 | g_object_class_install_property |
---|
247 | (gobject_class, |
---|
248 | PROP_FONT_DESC, |
---|
249 | g_param_spec_boxed ("font_desc", |
---|
250 | _("Font description"), |
---|
251 | _("Font description as a PangoFontDescription struct"), |
---|
252 | PANGO_TYPE_FONT_DESCRIPTION, |
---|
253 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
254 | |
---|
255 | g_object_class_install_property |
---|
256 | (gobject_class, |
---|
257 | PROP_FAMILY, |
---|
258 | g_param_spec_string ("family", |
---|
259 | _("Font family"), |
---|
260 | _("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"), |
---|
261 | NULL, |
---|
262 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
263 | |
---|
264 | /* Style */ |
---|
265 | g_object_class_install_property |
---|
266 | (gobject_class, |
---|
267 | PROP_ATTRIBUTES, |
---|
268 | g_param_spec_boxed ("attributes", NULL, NULL, |
---|
269 | PANGO_TYPE_ATTR_LIST, |
---|
270 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
271 | |
---|
272 | g_object_class_install_property |
---|
273 | (gobject_class, |
---|
274 | PROP_STYLE, |
---|
275 | g_param_spec_enum ("style", |
---|
276 | _("Font style"), |
---|
277 | _("Font style"), |
---|
278 | PANGO_TYPE_STYLE, |
---|
279 | PANGO_STYLE_NORMAL, |
---|
280 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
281 | |
---|
282 | g_object_class_install_property |
---|
283 | (gobject_class, |
---|
284 | PROP_VARIANT, |
---|
285 | g_param_spec_enum ("variant", |
---|
286 | _("Font variant"), |
---|
287 | _("Font variant"), |
---|
288 | PANGO_TYPE_VARIANT, |
---|
289 | PANGO_VARIANT_NORMAL, |
---|
290 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
291 | |
---|
292 | g_object_class_install_property |
---|
293 | (gobject_class, |
---|
294 | PROP_WEIGHT, |
---|
295 | g_param_spec_int ("weight", |
---|
296 | _("Font weight"), |
---|
297 | _("Font weight"), |
---|
298 | 0, |
---|
299 | G_MAXINT, |
---|
300 | PANGO_WEIGHT_NORMAL, |
---|
301 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
302 | |
---|
303 | |
---|
304 | g_object_class_install_property |
---|
305 | (gobject_class, |
---|
306 | PROP_STRETCH, |
---|
307 | g_param_spec_enum ("stretch", |
---|
308 | _("Font stretch"), |
---|
309 | _("Font stretch"), |
---|
310 | PANGO_TYPE_STRETCH, |
---|
311 | PANGO_STRETCH_NORMAL, |
---|
312 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
313 | |
---|
314 | g_object_class_install_property |
---|
315 | (gobject_class, |
---|
316 | PROP_SIZE, |
---|
317 | g_param_spec_int ("size", |
---|
318 | _("Font size"), |
---|
319 | _("Font size"), |
---|
320 | 0, |
---|
321 | G_MAXINT, |
---|
322 | 0, |
---|
323 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
324 | |
---|
325 | g_object_class_install_property |
---|
326 | (gobject_class, |
---|
327 | PROP_SIZE_POINTS, |
---|
328 | g_param_spec_double ("size_points", |
---|
329 | _("Font points"), |
---|
330 | _("Font size in points"), |
---|
331 | 0.0, |
---|
332 | G_MAXDOUBLE, |
---|
333 | 0.0, |
---|
334 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
335 | |
---|
336 | g_object_class_install_property |
---|
337 | (gobject_class, |
---|
338 | PROP_RISE, |
---|
339 | g_param_spec_int ("rise", |
---|
340 | _("Rise"), |
---|
341 | _("Offset of text above the baseline (below the baseline if rise is negative)"), |
---|
342 | -G_MAXINT, |
---|
343 | G_MAXINT, |
---|
344 | 0, |
---|
345 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
346 | |
---|
347 | g_object_class_install_property |
---|
348 | (gobject_class, |
---|
349 | PROP_STRIKETHROUGH, |
---|
350 | g_param_spec_boolean ("strikethrough", |
---|
351 | _("Strikethrough"), |
---|
352 | _("Whether to strike through the text"), |
---|
353 | FALSE, |
---|
354 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
355 | |
---|
356 | g_object_class_install_property |
---|
357 | (gobject_class, |
---|
358 | PROP_UNDERLINE, |
---|
359 | g_param_spec_enum ("underline", |
---|
360 | _("Underline"), |
---|
361 | _("Style of underline for this text"), |
---|
362 | PANGO_TYPE_UNDERLINE, |
---|
363 | PANGO_UNDERLINE_NONE, |
---|
364 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
365 | |
---|
366 | g_object_class_install_property |
---|
367 | (gobject_class, |
---|
368 | PROP_SCALE, |
---|
369 | g_param_spec_double ("scale", |
---|
370 | _("Scale"), |
---|
371 | _("Size of font, relative to default size"), |
---|
372 | 0.0, |
---|
373 | G_MAXDOUBLE, |
---|
374 | 1.0, |
---|
375 | G_PARAM_READABLE | G_PARAM_WRITABLE)); |
---|
376 | |
---|
377 | g_object_class_install_property |
---|
378 | (gobject_class, |
---|
379 | PROP_ANCHOR, |
---|
380 | g_param_spec_enum ("anchor", NULL, NULL, |
---|
381 | GTK_TYPE_ANCHOR_TYPE, |
---|
382 | GTK_ANCHOR_CENTER, |
---|
383 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
384 | g_object_class_install_property |
---|
385 | (gobject_class, |
---|
386 | PROP_JUSTIFICATION, |
---|
387 | g_param_spec_enum ("justification", NULL, NULL, |
---|
388 | GTK_TYPE_JUSTIFICATION, |
---|
389 | GTK_JUSTIFY_LEFT, |
---|
390 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
391 | g_object_class_install_property |
---|
392 | (gobject_class, |
---|
393 | PROP_CLIP_WIDTH, |
---|
394 | g_param_spec_double ("clip_width", NULL, NULL, |
---|
395 | -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, |
---|
396 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
397 | g_object_class_install_property |
---|
398 | (gobject_class, |
---|
399 | PROP_CLIP_HEIGHT, |
---|
400 | g_param_spec_double ("clip_height", NULL, NULL, |
---|
401 | -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, |
---|
402 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
403 | g_object_class_install_property |
---|
404 | (gobject_class, |
---|
405 | PROP_CLIP, |
---|
406 | g_param_spec_boolean ("clip", NULL, NULL, |
---|
407 | FALSE, |
---|
408 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
409 | g_object_class_install_property |
---|
410 | (gobject_class, |
---|
411 | PROP_X_OFFSET, |
---|
412 | g_param_spec_double ("x_offset", NULL, NULL, |
---|
413 | -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, |
---|
414 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
415 | g_object_class_install_property |
---|
416 | (gobject_class, |
---|
417 | PROP_Y_OFFSET, |
---|
418 | g_param_spec_double ("y_offset", NULL, NULL, |
---|
419 | -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, |
---|
420 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
421 | g_object_class_install_property |
---|
422 | (gobject_class, |
---|
423 | PROP_FILL_COLOR, |
---|
424 | g_param_spec_string ("fill_color", |
---|
425 | _("Color"), |
---|
426 | _("Text color, as string"), |
---|
427 | NULL, |
---|
428 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
429 | g_object_class_install_property |
---|
430 | (gobject_class, |
---|
431 | PROP_FILL_COLOR_GDK, |
---|
432 | g_param_spec_boxed ("fill_color_gdk", |
---|
433 | _("Color"), |
---|
434 | _("Text color, as a GdkColor"), |
---|
435 | GDK_TYPE_COLOR, |
---|
436 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
437 | g_object_class_install_property |
---|
438 | (gobject_class, |
---|
439 | PROP_FILL_COLOR_RGBA, |
---|
440 | g_param_spec_uint ("fill_color_rgba", |
---|
441 | _("Color"), |
---|
442 | _("Text color, as an R/G/B/A combined integer"), |
---|
443 | 0, G_MAXUINT, 0, |
---|
444 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
445 | g_object_class_install_property |
---|
446 | (gobject_class, |
---|
447 | PROP_FILL_STIPPLE, |
---|
448 | g_param_spec_object ("fill_stipple", NULL, NULL, |
---|
449 | GDK_TYPE_DRAWABLE, |
---|
450 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
451 | g_object_class_install_property |
---|
452 | (gobject_class, |
---|
453 | PROP_TEXT_WIDTH, |
---|
454 | g_param_spec_double ("text_width", |
---|
455 | _("Text width"), |
---|
456 | _("Width of the rendered text"), |
---|
457 | 0.0, G_MAXDOUBLE, 0.0, |
---|
458 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
459 | g_object_class_install_property |
---|
460 | (gobject_class, |
---|
461 | PROP_TEXT_HEIGHT, |
---|
462 | g_param_spec_double ("text_height", |
---|
463 | _("Text height"), |
---|
464 | _("Height of the rendered text"), |
---|
465 | 0.0, G_MAXDOUBLE, 0.0, |
---|
466 | (G_PARAM_READABLE | G_PARAM_WRITABLE))); |
---|
467 | |
---|
468 | /* Style props are set (explicitly applied) or not */ |
---|
469 | #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (gobject_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE)) |
---|
470 | |
---|
471 | ADD_SET_PROP ("family_set", PROP_FAMILY_SET, |
---|
472 | _("Font family set"), |
---|
473 | _("Whether this tag affects the font family")); |
---|
474 | |
---|
475 | ADD_SET_PROP ("style_set", PROP_STYLE_SET, |
---|
476 | _("Font style set"), |
---|
477 | _("Whether this tag affects the font style")); |
---|
478 | |
---|
479 | ADD_SET_PROP ("variant_set", PROP_VARIANT_SET, |
---|
480 | _("Font variant set"), |
---|
481 | _("Whether this tag affects the font variant")); |
---|
482 | |
---|
483 | ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET, |
---|
484 | _("Font weight set"), |
---|
485 | _("Whether this tag affects the font weight")); |
---|
486 | |
---|
487 | ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET, |
---|
488 | _("Font stretch set"), |
---|
489 | _("Whether this tag affects the font stretch")); |
---|
490 | |
---|
491 | ADD_SET_PROP ("size_set", PROP_SIZE_SET, |
---|
492 | _("Font size set"), |
---|
493 | _("Whether this tag affects the font size")); |
---|
494 | |
---|
495 | ADD_SET_PROP ("rise_set", PROP_RISE_SET, |
---|
496 | _("Rise set"), |
---|
497 | _("Whether this tag affects the rise")); |
---|
498 | |
---|
499 | ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET, |
---|
500 | _("Strikethrough set"), |
---|
501 | _("Whether this tag affects strikethrough")); |
---|
502 | |
---|
503 | ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET, |
---|
504 | _("Underline set"), |
---|
505 | _("Whether this tag affects underlining")); |
---|
506 | |
---|
507 | ADD_SET_PROP ("scale_set", PROP_SCALE_SET, |
---|
508 | _("Scale set"), |
---|
509 | _("Whether this tag affects font scaling")); |
---|
510 | #undef ADD_SET_PROP |
---|
511 | |
---|
512 | object_class->destroy = gnome_canvas_text_destroy; |
---|
513 | |
---|
514 | item_class->update = gnome_canvas_text_update; |
---|
515 | item_class->realize = gnome_canvas_text_realize; |
---|
516 | item_class->unrealize = gnome_canvas_text_unrealize; |
---|
517 | item_class->draw = gnome_canvas_text_draw; |
---|
518 | item_class->point = gnome_canvas_text_point; |
---|
519 | item_class->bounds = gnome_canvas_text_bounds; |
---|
520 | item_class->render = gnome_canvas_text_render; |
---|
521 | } |
---|
522 | |
---|
523 | /* Object initialization function for the text item */ |
---|
524 | static void |
---|
525 | gnome_canvas_text_init (GnomeCanvasText *text) |
---|
526 | { |
---|
527 | text->x = 0.0; |
---|
528 | text->y = 0.0; |
---|
529 | text->anchor = GTK_ANCHOR_CENTER; |
---|
530 | text->justification = GTK_JUSTIFY_LEFT; |
---|
531 | text->clip_width = 0.0; |
---|
532 | text->clip_height = 0.0; |
---|
533 | text->xofs = 0.0; |
---|
534 | text->yofs = 0.0; |
---|
535 | text->layout = NULL; |
---|
536 | |
---|
537 | text->font_desc = NULL; |
---|
538 | |
---|
539 | text->underline = PANGO_UNDERLINE_NONE; |
---|
540 | text->strikethrough = FALSE; |
---|
541 | text->rise = 0; |
---|
542 | |
---|
543 | text->underline_set = FALSE; |
---|
544 | text->strike_set = FALSE; |
---|
545 | text->rise_set = FALSE; |
---|
546 | |
---|
547 | text->priv = g_new (GnomeCanvasTextPrivate, 1); |
---|
548 | text->priv->bitmap.buffer = NULL; |
---|
549 | text->priv->render_dirty = 1; |
---|
550 | } |
---|
551 | |
---|
552 | /* Destroy handler for the text item */ |
---|
553 | static void |
---|
554 | gnome_canvas_text_destroy (GtkObject *object) |
---|
555 | { |
---|
556 | GnomeCanvasText *text; |
---|
557 | |
---|
558 | g_return_if_fail (GNOME_IS_CANVAS_TEXT (object)); |
---|
559 | |
---|
560 | text = GNOME_CANVAS_TEXT (object); |
---|
561 | |
---|
562 | /* remember, destroy can be run multiple times! */ |
---|
563 | |
---|
564 | g_free (text->text); |
---|
565 | text->text = NULL; |
---|
566 | |
---|
567 | if (text->layout) |
---|
568 | g_object_unref (G_OBJECT (text->layout)); |
---|
569 | text->layout = NULL; |
---|
570 | |
---|
571 | if (text->font_desc) { |
---|
572 | pango_font_description_free (text->font_desc); |
---|
573 | text->font_desc = NULL; |
---|
574 | } |
---|
575 | |
---|
576 | if (text->attr_list) |
---|
577 | pango_attr_list_unref (text->attr_list); |
---|
578 | text->attr_list = NULL; |
---|
579 | |
---|
580 | if (text->stipple) |
---|
581 | gdk_bitmap_unref (text->stipple); |
---|
582 | text->stipple = NULL; |
---|
583 | |
---|
584 | if (text->priv && text->priv->bitmap.buffer) { |
---|
585 | g_free (text->priv->bitmap.buffer); |
---|
586 | } |
---|
587 | g_free (text->priv); |
---|
588 | text->priv = NULL; |
---|
589 | |
---|
590 | if (GTK_OBJECT_CLASS (parent_class)->destroy) |
---|
591 | (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); |
---|
592 | } |
---|
593 | |
---|
594 | static void |
---|
595 | get_bounds (GnomeCanvasText *text, double *px1, double *py1, double *px2, double *py2) |
---|
596 | { |
---|
597 | GnomeCanvasItem *item; |
---|
598 | double wx, wy; |
---|
599 | |
---|
600 | item = GNOME_CANVAS_ITEM (text); |
---|
601 | |
---|
602 | /* Get canvas pixel coordinates for text position */ |
---|
603 | |
---|
604 | |
---|
605 | wx = text->x; |
---|
606 | wy = text->y; |
---|
607 | gnome_canvas_item_i2w (item, &wx, &wy); |
---|
608 | gnome_canvas_w2c (item->canvas, wx + text->xofs, wy + text->yofs, &text->cx, &text->cy); |
---|
609 | |
---|
610 | /* Get canvas pixel coordinates for clip rectangle position */ |
---|
611 | |
---|
612 | gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy); |
---|
613 | text->clip_cwidth = text->clip_width * item->canvas->pixels_per_unit; |
---|
614 | text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit; |
---|
615 | |
---|
616 | /* Anchor text */ |
---|
617 | |
---|
618 | switch (text->anchor) { |
---|
619 | case GTK_ANCHOR_NW: |
---|
620 | case GTK_ANCHOR_W: |
---|
621 | case GTK_ANCHOR_SW: |
---|
622 | break; |
---|
623 | |
---|
624 | case GTK_ANCHOR_N: |
---|
625 | case GTK_ANCHOR_CENTER: |
---|
626 | case GTK_ANCHOR_S: |
---|
627 | text->cx -= text->max_width / 2; |
---|
628 | text->clip_cx -= text->clip_cwidth / 2; |
---|
629 | break; |
---|
630 | |
---|
631 | case GTK_ANCHOR_NE: |
---|
632 | case GTK_ANCHOR_E: |
---|
633 | case GTK_ANCHOR_SE: |
---|
634 | text->cx -= text->max_width; |
---|
635 | text->clip_cx -= text->clip_cwidth; |
---|
636 | break; |
---|
637 | |
---|
638 | default: |
---|
639 | break; |
---|
640 | } |
---|
641 | |
---|
642 | switch (text->anchor) { |
---|
643 | case GTK_ANCHOR_NW: |
---|
644 | case GTK_ANCHOR_N: |
---|
645 | case GTK_ANCHOR_NE: |
---|
646 | break; |
---|
647 | |
---|
648 | case GTK_ANCHOR_W: |
---|
649 | case GTK_ANCHOR_CENTER: |
---|
650 | case GTK_ANCHOR_E: |
---|
651 | text->cy -= text->height / 2; |
---|
652 | text->clip_cy -= text->clip_cheight / 2; |
---|
653 | break; |
---|
654 | |
---|
655 | case GTK_ANCHOR_SW: |
---|
656 | case GTK_ANCHOR_S: |
---|
657 | case GTK_ANCHOR_SE: |
---|
658 | text->cy -= text->height; |
---|
659 | text->clip_cy -= text->clip_cheight; |
---|
660 | break; |
---|
661 | |
---|
662 | default: |
---|
663 | break; |
---|
664 | } |
---|
665 | |
---|
666 | /* Bounds */ |
---|
667 | |
---|
668 | if (text->clip) { |
---|
669 | *px1 = text->clip_cx; |
---|
670 | *py1 = text->clip_cy; |
---|
671 | *px2 = text->clip_cx + text->clip_cwidth; |
---|
672 | *py2 = text->clip_cy + text->clip_cheight; |
---|
673 | } else { |
---|
674 | *px1 = text->cx; |
---|
675 | *py1 = text->cy; |
---|
676 | *px2 = text->cx + text->max_width; |
---|
677 | *py2 = text->cy + text->height; |
---|
678 | } |
---|
679 | } |
---|
680 | |
---|
681 | /* Convenience function to set the text's GC's foreground color */ |
---|
682 | static void |
---|
683 | set_text_gc_foreground (GnomeCanvasText *text) |
---|
684 | { |
---|
685 | GdkColor c; |
---|
686 | |
---|
687 | if (!text->gc) |
---|
688 | return; |
---|
689 | |
---|
690 | c.pixel = text->pixel; |
---|
691 | gdk_gc_set_foreground (text->gc, &c); |
---|
692 | } |
---|
693 | |
---|
694 | /* Sets the stipple pattern for the text */ |
---|
695 | static void |
---|
696 | set_stipple (GnomeCanvasText *text, GdkBitmap *stipple, int reconfigure) |
---|
697 | { |
---|
698 | if (text->stipple && !reconfigure) |
---|
699 | gdk_bitmap_unref (text->stipple); |
---|
700 | |
---|
701 | text->stipple = stipple; |
---|
702 | if (stipple && !reconfigure) |
---|
703 | gdk_bitmap_ref (stipple); |
---|
704 | |
---|
705 | if (text->gc) { |
---|
706 | if (stipple) { |
---|
707 | gdk_gc_set_stipple (text->gc, stipple); |
---|
708 | gdk_gc_set_fill (text->gc, GDK_STIPPLED); |
---|
709 | } else |
---|
710 | gdk_gc_set_fill (text->gc, GDK_SOLID); |
---|
711 | } |
---|
712 | } |
---|
713 | |
---|
714 | static PangoFontMask |
---|
715 | get_property_font_set_mask (guint prop_id) |
---|
716 | { |
---|
717 | switch (prop_id) |
---|
718 | { |
---|
719 | case PROP_FAMILY_SET: |
---|
720 | return PANGO_FONT_MASK_FAMILY; |
---|
721 | case PROP_STYLE_SET: |
---|
722 | return PANGO_FONT_MASK_STYLE; |
---|
723 | case PROP_VARIANT_SET: |
---|
724 | return PANGO_FONT_MASK_VARIANT; |
---|
725 | case PROP_WEIGHT_SET: |
---|
726 | return PANGO_FONT_MASK_WEIGHT; |
---|
727 | case PROP_STRETCH_SET: |
---|
728 | return PANGO_FONT_MASK_STRETCH; |
---|
729 | case PROP_SIZE_SET: |
---|
730 | return PANGO_FONT_MASK_SIZE; |
---|
731 | } |
---|
732 | |
---|
733 | return 0; |
---|
734 | } |
---|
735 | |
---|
736 | static void |
---|
737 | ensure_font (GnomeCanvasText *text) |
---|
738 | { |
---|
739 | if (!text->font_desc) |
---|
740 | text->font_desc = pango_font_description_new (); |
---|
741 | } |
---|
742 | |
---|
743 | /* Set_arg handler for the text item */ |
---|
744 | static void |
---|
745 | gnome_canvas_text_set_property (GObject *object, |
---|
746 | guint param_id, |
---|
747 | const GValue *value, |
---|
748 | GParamSpec *pspec) |
---|
749 | { |
---|
750 | GnomeCanvasItem *item; |
---|
751 | GnomeCanvasText *text; |
---|
752 | GdkColor color = { 0, 0, 0, 0, }; |
---|
753 | GdkColor *pcolor; |
---|
754 | gboolean color_changed; |
---|
755 | int have_pixel; |
---|
756 | PangoAlignment align; |
---|
757 | |
---|
758 | g_return_if_fail (object != NULL); |
---|
759 | g_return_if_fail (GNOME_IS_CANVAS_TEXT (object)); |
---|
760 | |
---|
761 | item = GNOME_CANVAS_ITEM (object); |
---|
762 | text = GNOME_CANVAS_TEXT (object); |
---|
763 | |
---|
764 | color_changed = FALSE; |
---|
765 | have_pixel = FALSE; |
---|
766 | |
---|
767 | |
---|
768 | if (!text->layout) { |
---|
769 | |
---|
770 | PangoContext *gtk_context, *context; |
---|
771 | gtk_context = gtk_widget_get_pango_context (GTK_WIDGET (item->canvas)); |
---|
772 | |
---|
773 | if (item->canvas->aa) { |
---|
774 | PangoLanguage *language; |
---|
775 | gint pixels, mm; |
---|
776 | double dpi_x; |
---|
777 | double dpi_y; |
---|
778 | |
---|
779 | pixels = gdk_screen_width (); |
---|
780 | mm = gdk_screen_width_mm (); |
---|
781 | dpi_x = (((double) pixels * 25.4) / (double) mm); |
---|
782 | |
---|
783 | pixels = gdk_screen_height (); |
---|
784 | mm = gdk_screen_height_mm (); |
---|
785 | dpi_y = (((double) pixels * 25.4) / (double) mm); |
---|
786 | |
---|
787 | context = pango_ft2_get_context (dpi_x, dpi_y); |
---|
788 | language = pango_context_get_language (gtk_context); |
---|
789 | pango_context_set_language (context, language); |
---|
790 | pango_context_set_base_dir (context, |
---|
791 | pango_context_get_base_dir (gtk_context)); |
---|
792 | pango_context_set_font_description (context, |
---|
793 | pango_context_get_font_description (gtk_context)); |
---|
794 | |
---|
795 | } else |
---|
796 | context = gtk_context; |
---|
797 | |
---|
798 | |
---|
799 | text->layout = pango_layout_new (context); |
---|
800 | |
---|
801 | if (item->canvas->aa) |
---|
802 | g_object_unref (G_OBJECT (context)); |
---|
803 | } |
---|
804 | |
---|
805 | switch (param_id) { |
---|
806 | case PROP_TEXT: |
---|
807 | if (text->text) |
---|
808 | g_free (text->text); |
---|
809 | |
---|
810 | text->text = g_value_dup_string (value); |
---|
811 | pango_layout_set_text (text->layout, text->text, -1); |
---|
812 | |
---|
813 | text->priv->render_dirty = 1; |
---|
814 | break; |
---|
815 | |
---|
816 | case PROP_MARKUP: |
---|
817 | gnome_canvas_text_set_markup (text, |
---|
818 | g_value_get_string (value)); |
---|
819 | text->priv->render_dirty = 1; |
---|
820 | break; |
---|
821 | |
---|
822 | case PROP_X: |
---|
823 | text->x = g_value_get_double (value); |
---|
824 | break; |
---|
825 | |
---|
826 | case PROP_Y: |
---|
827 | text->y = g_value_get_double (value); |
---|
828 | break; |
---|
829 | |
---|
830 | case PROP_FONT: { |
---|
831 | const char *font_name; |
---|
832 | PangoFontDescription *font_desc; |
---|
833 | |
---|
834 | font_name = g_value_get_string (value); |
---|
835 | if (font_name) |
---|
836 | font_desc = pango_font_description_from_string (font_name); |
---|
837 | else |
---|
838 | font_desc = NULL; |
---|
839 | |
---|
840 | gnome_canvas_text_set_font_desc (text, font_desc); |
---|
841 | if (font_desc) |
---|
842 | pango_font_description_free (font_desc); |
---|
843 | |
---|
844 | break; |
---|
845 | } |
---|
846 | |
---|
847 | case PROP_FONT_DESC: |
---|
848 | gnome_canvas_text_set_font_desc (text, g_value_peek_pointer (value)); |
---|
849 | break; |
---|
850 | |
---|
851 | case PROP_FAMILY: |
---|
852 | case PROP_STYLE: |
---|
853 | case PROP_VARIANT: |
---|
854 | case PROP_WEIGHT: |
---|
855 | case PROP_STRETCH: |
---|
856 | case PROP_SIZE: |
---|
857 | case PROP_SIZE_POINTS: |
---|
858 | ensure_font (text); |
---|
859 | |
---|
860 | switch (param_id) { |
---|
861 | case PROP_FAMILY: |
---|
862 | pango_font_description_set_family (text->font_desc, |
---|
863 | g_value_get_string (value)); |
---|
864 | break; |
---|
865 | case PROP_STYLE: |
---|
866 | pango_font_description_set_style (text->font_desc, |
---|
867 | g_value_get_enum (value)); |
---|
868 | break; |
---|
869 | case PROP_VARIANT: |
---|
870 | pango_font_description_set_variant (text->font_desc, |
---|
871 | g_value_get_enum (value)); |
---|
872 | break; |
---|
873 | case PROP_WEIGHT: |
---|
874 | pango_font_description_set_weight (text->font_desc, |
---|
875 | g_value_get_int (value)); |
---|
876 | break; |
---|
877 | case PROP_STRETCH: |
---|
878 | pango_font_description_set_stretch (text->font_desc, |
---|
879 | g_value_get_enum (value)); |
---|
880 | break; |
---|
881 | case PROP_SIZE: |
---|
882 | /* FIXME: This is bogus! It should be pixels, not points/PANGO_SCALE! */ |
---|
883 | pango_font_description_set_size (text->font_desc, |
---|
884 | g_value_get_int (value)); |
---|
885 | break; |
---|
886 | case PROP_SIZE_POINTS: |
---|
887 | pango_font_description_set_size (text->font_desc, |
---|
888 | g_value_get_double (value) * PANGO_SCALE); |
---|
889 | break; |
---|
890 | } |
---|
891 | |
---|
892 | gnome_canvas_text_apply_font_desc (text); |
---|
893 | text->priv->render_dirty = 1; |
---|
894 | break; |
---|
895 | |
---|
896 | case PROP_FAMILY_SET: |
---|
897 | case PROP_STYLE_SET: |
---|
898 | case PROP_VARIANT_SET: |
---|
899 | case PROP_WEIGHT_SET: |
---|
900 | case PROP_STRETCH_SET: |
---|
901 | case PROP_SIZE_SET: |
---|
902 | if (!g_value_get_boolean (value) && text->font_desc) |
---|
903 | pango_font_description_unset_fields (text->font_desc, |
---|
904 | get_property_font_set_mask (param_id)); |
---|
905 | break; |
---|
906 | |
---|
907 | case PROP_SCALE: |
---|
908 | text->scale = g_value_get_double (value); |
---|
909 | text->scale_set = TRUE; |
---|
910 | |
---|
911 | gnome_canvas_text_apply_font_desc (text); |
---|
912 | text->priv->render_dirty = 1; |
---|
913 | break; |
---|
914 | |
---|
915 | case PROP_SCALE_SET: |
---|
916 | text->scale_set = g_value_get_boolean (value); |
---|
917 | |
---|
918 | gnome_canvas_text_apply_font_desc (text); |
---|
919 | text->priv->render_dirty = 1; |
---|
920 | break; |
---|
921 | |
---|
922 | case PROP_UNDERLINE: |
---|
923 | text->underline = g_value_get_enum (value); |
---|
924 | text->underline_set = TRUE; |
---|
925 | |
---|
926 | gnome_canvas_text_apply_attributes (text); |
---|
927 | text->priv->render_dirty = 1; |
---|
928 | break; |
---|
929 | |
---|
930 | case PROP_UNDERLINE_SET: |
---|
931 | text->underline_set = g_value_get_boolean (value); |
---|
932 | |
---|
933 | gnome_canvas_text_apply_attributes (text); |
---|
934 | text->priv->render_dirty = 1; |
---|
935 | break; |
---|
936 | |
---|
937 | case PROP_STRIKETHROUGH: |
---|
938 | text->strikethrough = g_value_get_boolean (value); |
---|
939 | text->strike_set = TRUE; |
---|
940 | |
---|
941 | gnome_canvas_text_apply_attributes (text); |
---|
942 | text->priv->render_dirty = 1; |
---|
943 | break; |
---|
944 | |
---|
945 | case PROP_STRIKETHROUGH_SET: |
---|
946 | text->strike_set = g_value_get_boolean (value); |
---|
947 | |
---|
948 | gnome_canvas_text_apply_attributes (text); |
---|
949 | text->priv->render_dirty = 1; |
---|
950 | break; |
---|
951 | |
---|
952 | case PROP_RISE: |
---|
953 | text->rise = g_value_get_int (value); |
---|
954 | text->rise_set = TRUE; |
---|
955 | |
---|
956 | gnome_canvas_text_apply_attributes (text); |
---|
957 | text->priv->render_dirty = 1; |
---|
958 | break; |
---|
959 | |
---|
960 | case PROP_RISE_SET: |
---|
961 | text->rise_set = TRUE; |
---|
962 | |
---|
963 | gnome_canvas_text_apply_attributes (text); |
---|
964 | text->priv->render_dirty = 1; |
---|
965 | break; |
---|
966 | |
---|
967 | case PROP_ATTRIBUTES: |
---|
968 | if (text->attr_list) |
---|
969 | pango_attr_list_unref (text->attr_list); |
---|
970 | |
---|
971 | text->attr_list = g_value_peek_pointer (value); |
---|
972 | |
---|
973 | gnome_canvas_text_apply_attributes (text); |
---|
974 | text->priv->render_dirty = 1; |
---|
975 | break; |
---|
976 | |
---|
977 | case PROP_ANCHOR: |
---|
978 | text->anchor = g_value_get_enum (value); |
---|
979 | break; |
---|
980 | |
---|
981 | case PROP_JUSTIFICATION: |
---|
982 | text->justification = g_value_get_enum (value); |
---|
983 | |
---|
984 | switch (text->justification) { |
---|
985 | case GTK_JUSTIFY_LEFT: |
---|
986 | align = PANGO_ALIGN_LEFT; |
---|
987 | break; |
---|
988 | case GTK_JUSTIFY_CENTER: |
---|
989 | align = PANGO_ALIGN_CENTER; |
---|
990 | break; |
---|
991 | case GTK_JUSTIFY_RIGHT: |
---|
992 | align = PANGO_ALIGN_RIGHT; |
---|
993 | break; |
---|
994 | default: |
---|
995 | /* GTK_JUSTIFY_FILL isn't supported yet. */ |
---|
996 | align = PANGO_ALIGN_LEFT; |
---|
997 | break; |
---|
998 | } |
---|
999 | pango_layout_set_alignment (text->layout, align); |
---|
1000 | text->priv->render_dirty = 1; |
---|
1001 | break; |
---|
1002 | |
---|
1003 | case PROP_CLIP_WIDTH: |
---|
1004 | text->clip_width = fabs (g_value_get_double (value)); |
---|
1005 | text->priv->render_dirty = 1; |
---|
1006 | break; |
---|
1007 | |
---|
1008 | case PROP_CLIP_HEIGHT: |
---|
1009 | text->clip_height = fabs (g_value_get_double (value)); |
---|
1010 | text->priv->render_dirty = 1; |
---|
1011 | break; |
---|
1012 | |
---|
1013 | case PROP_CLIP: |
---|
1014 | text->clip = g_value_get_boolean (value); |
---|
1015 | text->priv->render_dirty = 1; |
---|
1016 | break; |
---|
1017 | |
---|
1018 | case PROP_X_OFFSET: |
---|
1019 | text->xofs = g_value_get_double (value); |
---|
1020 | break; |
---|
1021 | |
---|
1022 | case PROP_Y_OFFSET: |
---|
1023 | text->yofs = g_value_get_double (value); |
---|
1024 | break; |
---|
1025 | |
---|
1026 | case PROP_FILL_COLOR: { |
---|
1027 | const char *color_name; |
---|
1028 | |
---|
1029 | color_name = g_value_get_string (value); |
---|
1030 | if (color_name) { |
---|
1031 | gdk_color_parse (color_name, &color); |
---|
1032 | |
---|
1033 | text->rgba = ((color.red & 0xff00) << 16 | |
---|
1034 | (color.green & 0xff00) << 8 | |
---|
1035 | (color.blue & 0xff00) | |
---|
1036 | 0xff); |
---|
1037 | color_changed = TRUE; |
---|
1038 | } |
---|
1039 | text->priv->render_dirty = 1; |
---|
1040 | break; |
---|
1041 | } |
---|
1042 | |
---|
1043 | case PROP_FILL_COLOR_GDK: |
---|
1044 | pcolor = g_value_get_boxed (value); |
---|
1045 | if (pcolor) { |
---|
1046 | GdkColormap *colormap; |
---|
1047 | |
---|
1048 | color = *pcolor; |
---|
1049 | colormap = gtk_widget_get_colormap (GTK_WIDGET (item->canvas)); |
---|
1050 | gdk_rgb_find_color (colormap, &color); |
---|
1051 | have_pixel = TRUE; |
---|
1052 | } |
---|
1053 | |
---|
1054 | text->rgba = ((color.red & 0xff00) << 16 | |
---|
1055 | (color.green & 0xff00) << 8| |
---|
1056 | (color.blue & 0xff00) | |
---|
1057 | 0xff); |
---|
1058 | color_changed = TRUE; |
---|
1059 | break; |
---|
1060 | |
---|
1061 | case PROP_FILL_COLOR_RGBA: |
---|
1062 | text->rgba = g_value_get_uint (value); |
---|
1063 | color_changed = TRUE; |
---|
1064 | text->priv->render_dirty = 1; |
---|
1065 | break; |
---|
1066 | |
---|
1067 | case PROP_FILL_STIPPLE: |
---|
1068 | set_stipple (text, (GdkBitmap *)g_value_get_object (value), FALSE); |
---|
1069 | break; |
---|
1070 | |
---|
1071 | default: |
---|
1072 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); |
---|
1073 | break; |
---|
1074 | } |
---|
1075 | |
---|
1076 | if (color_changed) { |
---|
1077 | if (have_pixel) |
---|
1078 | text->pixel = color.pixel; |
---|
1079 | else |
---|
1080 | text->pixel = gnome_canvas_get_color_pixel (item->canvas, text->rgba); |
---|
1081 | |
---|
1082 | if (!item->canvas->aa) |
---|
1083 | set_text_gc_foreground (text); |
---|
1084 | } |
---|
1085 | |
---|
1086 | /* Calculate text dimensions */ |
---|
1087 | |
---|
1088 | if (text->layout) |
---|
1089 | pango_layout_get_pixel_size (text->layout, |
---|
1090 | &text->max_width, |
---|
1091 | &text->height); |
---|
1092 | else { |
---|
1093 | text->max_width = 0; |
---|
1094 | text->height = 0; |
---|
1095 | } |
---|
1096 | |
---|
1097 | gnome_canvas_item_request_update (item); |
---|
1098 | } |
---|
1099 | |
---|
1100 | /* Get_arg handler for the text item */ |
---|
1101 | static void |
---|
1102 | gnome_canvas_text_get_property (GObject *object, |
---|
1103 | guint param_id, |
---|
1104 | GValue *value, |
---|
1105 | GParamSpec *pspec) |
---|
1106 | { |
---|
1107 | GnomeCanvasText *text; |
---|
1108 | |
---|
1109 | g_return_if_fail (object != NULL); |
---|
1110 | g_return_if_fail (GNOME_IS_CANVAS_TEXT (object)); |
---|
1111 | |
---|
1112 | text = GNOME_CANVAS_TEXT (object); |
---|
1113 | |
---|
1114 | switch (param_id) { |
---|
1115 | case PROP_TEXT: |
---|
1116 | g_value_set_string (value, text->text); |
---|
1117 | break; |
---|
1118 | |
---|
1119 | case PROP_X: |
---|
1120 | g_value_set_double (value, text->x); |
---|
1121 | break; |
---|
1122 | |
---|
1123 | case PROP_Y: |
---|
1124 | g_value_set_double (value, text->y); |
---|
1125 | break; |
---|
1126 | |
---|
1127 | case PROP_FONT: |
---|
1128 | case PROP_FONT_DESC: |
---|
1129 | case PROP_FAMILY: |
---|
1130 | case PROP_STYLE: |
---|
1131 | case PROP_VARIANT: |
---|
1132 | case PROP_WEIGHT: |
---|
1133 | case PROP_STRETCH: |
---|
1134 | case PROP_SIZE: |
---|
1135 | case PROP_SIZE_POINTS: |
---|
1136 | ensure_font (text); |
---|
1137 | |
---|
1138 | switch (param_id) { |
---|
1139 | case PROP_FONT: |
---|
1140 | { |
---|
1141 | /* FIXME GValue imposes a totally gratuitous string copy |
---|
1142 | * here, we could just hand off string ownership |
---|
1143 | */ |
---|
1144 | gchar *str; |
---|
1145 | |
---|
1146 | str = pango_font_description_to_string (text->font_desc); |
---|
1147 | g_value_set_string (value, str); |
---|
1148 | g_free (str); |
---|
1149 | |
---|
1150 | break; |
---|
1151 | } |
---|
1152 | |
---|
1153 | case PROP_FONT_DESC: |
---|
1154 | g_value_set_boxed (value, text->font_desc); |
---|
1155 | break; |
---|
1156 | |
---|
1157 | case PROP_FAMILY: |
---|
1158 | g_value_set_string (value, pango_font_description_get_family (text->font_desc)); |
---|
1159 | break; |
---|
1160 | |
---|
1161 | case PROP_STYLE: |
---|
1162 | g_value_set_enum (value, pango_font_description_get_style (text->font_desc)); |
---|
1163 | break; |
---|
1164 | |
---|
1165 | case PROP_VARIANT: |
---|
1166 | g_value_set_enum (value, pango_font_description_get_variant (text->font_desc)); |
---|
1167 | break; |
---|
1168 | |
---|
1169 | case PROP_WEIGHT: |
---|
1170 | g_value_set_int (value, pango_font_description_get_weight (text->font_desc)); |
---|
1171 | break; |
---|
1172 | |
---|
1173 | case PROP_STRETCH: |
---|
1174 | g_value_set_enum (value, pango_font_description_get_stretch (text->font_desc)); |
---|
1175 | break; |
---|
1176 | |
---|
1177 | case PROP_SIZE: |
---|
1178 | g_value_set_int (value, pango_font_description_get_size (text->font_desc)); |
---|
1179 | break; |
---|
1180 | |
---|
1181 | case PROP_SIZE_POINTS: |
---|
1182 | g_value_set_double (value, ((double)pango_font_description_get_size (text->font_desc)) / (double)PANGO_SCALE); |
---|
1183 | break; |
---|
1184 | } |
---|
1185 | break; |
---|
1186 | |
---|
1187 | case PROP_FAMILY_SET: |
---|
1188 | case PROP_STYLE_SET: |
---|
1189 | case PROP_VARIANT_SET: |
---|
1190 | case PROP_WEIGHT_SET: |
---|
1191 | case PROP_STRETCH_SET: |
---|
1192 | case PROP_SIZE_SET: |
---|
1193 | { |
---|
1194 | PangoFontMask set_mask = text->font_desc ? pango_font_description_get_set_fields (text->font_desc) : 0; |
---|
1195 | PangoFontMask test_mask = get_property_font_set_mask (param_id); |
---|
1196 | g_value_set_boolean (value, (set_mask & test_mask) != 0); |
---|
1197 | |
---|
1198 | break; |
---|
1199 | } |
---|
1200 | |
---|
1201 | case PROP_SCALE: |
---|
1202 | g_value_set_double (value, text->scale); |
---|
1203 | break; |
---|
1204 | case PROP_SCALE_SET: |
---|
1205 | g_value_set_boolean (value, text->scale_set); |
---|
1206 | break; |
---|
1207 | |
---|
1208 | case PROP_UNDERLINE: |
---|
1209 | g_value_set_enum (value, text->underline); |
---|
1210 | break; |
---|
1211 | case PROP_UNDERLINE_SET: |
---|
1212 | g_value_set_boolean (value, text->underline_set); |
---|
1213 | break; |
---|
1214 | |
---|
1215 | case PROP_STRIKETHROUGH: |
---|
1216 | g_value_set_boolean (value, text->strikethrough); |
---|
1217 | break; |
---|
1218 | case PROP_STRIKETHROUGH_SET: |
---|
1219 | g_value_set_boolean (value, text->strike_set); |
---|
1220 | break; |
---|
1221 | |
---|
1222 | case PROP_RISE: |
---|
1223 | g_value_set_int (value, text->rise); |
---|
1224 | break; |
---|
1225 | case PROP_RISE_SET: |
---|
1226 | g_value_set_boolean (value, text->rise_set); |
---|
1227 | break; |
---|
1228 | |
---|
1229 | case PROP_ATTRIBUTES: |
---|
1230 | g_value_set_boxed (value, text->attr_list); |
---|
1231 | break; |
---|
1232 | |
---|
1233 | case PROP_ANCHOR: |
---|
1234 | g_value_set_enum (value, text->anchor); |
---|
1235 | break; |
---|
1236 | |
---|
1237 | case PROP_JUSTIFICATION: |
---|
1238 | g_value_set_enum (value, text->justification); |
---|
1239 | break; |
---|
1240 | |
---|
1241 | case PROP_CLIP_WIDTH: |
---|
1242 | g_value_set_double (value, text->clip_width); |
---|
1243 | break; |
---|
1244 | |
---|
1245 | case PROP_CLIP_HEIGHT: |
---|
1246 | g_value_set_double (value, text->clip_height); |
---|
1247 | break; |
---|
1248 | |
---|
1249 | case PROP_CLIP: |
---|
1250 | g_value_set_boolean (value, text->clip); |
---|
1251 | break; |
---|
1252 | |
---|
1253 | case PROP_X_OFFSET: |
---|
1254 | g_value_set_double (value, text->xofs); |
---|
1255 | break; |
---|
1256 | |
---|
1257 | case PROP_Y_OFFSET: |
---|
1258 | g_value_set_double (value, text->yofs); |
---|
1259 | break; |
---|
1260 | |
---|
1261 | case PROP_FILL_COLOR: |
---|
1262 | g_value_set_string_take_ownership (value, |
---|
1263 | g_strdup_printf ("#%02x%02x%02x", |
---|
1264 | text->rgba >> 24, |
---|
1265 | (text->rgba >> 16) & 0xff, |
---|
1266 | (text->rgba >> 8) & 0xff)); |
---|
1267 | break; |
---|
1268 | |
---|
1269 | case PROP_FILL_COLOR_GDK: { |
---|
1270 | GnomeCanvas *canvas = GNOME_CANVAS_ITEM (text)->canvas; |
---|
1271 | GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (canvas)); |
---|
1272 | GdkColor color; |
---|
1273 | |
---|
1274 | gdk_colormap_query_color (colormap, text->pixel, &color); |
---|
1275 | g_value_set_boxed (value, &color); |
---|
1276 | break; |
---|
1277 | } |
---|
1278 | case PROP_FILL_COLOR_RGBA: |
---|
1279 | g_value_set_uint (value, text->rgba); |
---|
1280 | break; |
---|
1281 | |
---|
1282 | case PROP_FILL_STIPPLE: |
---|
1283 | g_value_set_object (value, text->stipple); |
---|
1284 | break; |
---|
1285 | |
---|
1286 | case PROP_TEXT_WIDTH: |
---|
1287 | g_value_set_double (value, text->max_width / text->item.canvas->pixels_per_unit); |
---|
1288 | break; |
---|
1289 | |
---|
1290 | case PROP_TEXT_HEIGHT: |
---|
1291 | g_value_set_double (value, text->height / text->item.canvas->pixels_per_unit); |
---|
1292 | break; |
---|
1293 | |
---|
1294 | default: |
---|
1295 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); |
---|
1296 | break; |
---|
1297 | } |
---|
1298 | } |
---|
1299 | |
---|
1300 | /* */ |
---|
1301 | static void |
---|
1302 | gnome_canvas_text_apply_font_desc (GnomeCanvasText *text) |
---|
1303 | { |
---|
1304 | PangoFontDescription *font_desc = |
---|
1305 | pango_font_description_copy ( |
---|
1306 | GTK_WIDGET (GNOME_CANVAS_ITEM (text)->canvas)->style->font_desc); |
---|
1307 | |
---|
1308 | if (text->font_desc) |
---|
1309 | pango_font_description_merge (font_desc, text->font_desc, TRUE); |
---|
1310 | |
---|
1311 | pango_layout_set_font_description (text->layout, font_desc); |
---|
1312 | pango_font_description_free (font_desc); |
---|
1313 | } |
---|
1314 | |
---|
1315 | static void |
---|
1316 | add_attr (PangoAttrList *attr_list, |
---|
1317 | PangoAttribute *attr) |
---|
1318 | { |
---|
1319 | attr->start_index = 0; |
---|
1320 | attr->end_index = G_MAXINT; |
---|
1321 | |
---|
1322 | pango_attr_list_insert (attr_list, attr); |
---|
1323 | } |
---|
1324 | |
---|
1325 | /* */ |
---|
1326 | static void |
---|
1327 | gnome_canvas_text_apply_attributes (GnomeCanvasText *text) |
---|
1328 | { |
---|
1329 | PangoAttrList *attr_list; |
---|
1330 | |
---|
1331 | if (text->attr_list) |
---|
1332 | attr_list = pango_attr_list_copy (text->attr_list); |
---|
1333 | else |
---|
1334 | attr_list = pango_attr_list_new (); |
---|
1335 | |
---|
1336 | if (text->underline_set) |
---|
1337 | add_attr (attr_list, pango_attr_underline_new (text->underline)); |
---|
1338 | if (text->strike_set) |
---|
1339 | add_attr (attr_list, pango_attr_strikethrough_new (text->strikethrough)); |
---|
1340 | if (text->rise_set) |
---|
1341 | add_attr (attr_list, pango_attr_rise_new (text->rise)); |
---|
1342 | |
---|
1343 | pango_layout_set_attributes (text->layout, attr_list); |
---|
1344 | pango_attr_list_unref (attr_list); |
---|
1345 | } |
---|
1346 | |
---|
1347 | static void |
---|
1348 | gnome_canvas_text_set_font_desc (GnomeCanvasText *text, |
---|
1349 | PangoFontDescription *font_desc) |
---|
1350 | { |
---|
1351 | if (text->font_desc) |
---|
1352 | pango_font_description_free (text->font_desc); |
---|
1353 | |
---|
1354 | if (font_desc) |
---|
1355 | text->font_desc = pango_font_description_copy (font_desc); |
---|
1356 | else |
---|
1357 | text->font_desc = NULL; |
---|
1358 | |
---|
1359 | gnome_canvas_text_apply_font_desc (text); |
---|
1360 | text->priv->render_dirty = 1; |
---|
1361 | } |
---|
1362 | |
---|
1363 | /* Setting the text from a Pango markup string */ |
---|
1364 | static void |
---|
1365 | gnome_canvas_text_set_markup (GnomeCanvasText *textitem, |
---|
1366 | const gchar *markup) |
---|
1367 | { |
---|
1368 | PangoAttrList *attr_list = NULL; |
---|
1369 | gchar *text = NULL; |
---|
1370 | GError *error = NULL; |
---|
1371 | |
---|
1372 | if (textitem->text) |
---|
1373 | g_free (textitem->text); |
---|
1374 | if (textitem->attr_list) |
---|
1375 | pango_attr_list_unref (textitem->attr_list); |
---|
1376 | |
---|
1377 | if (markup && !pango_parse_markup (markup, -1, |
---|
1378 | 0, |
---|
1379 | &attr_list, &text, NULL, |
---|
1380 | &error)) |
---|
1381 | { |
---|
1382 | g_warning ("Failed to set cell text from markup due to error parsing markup: %s", |
---|
1383 | error->message); |
---|
1384 | g_error_free (error); |
---|
1385 | return; |
---|
1386 | } |
---|
1387 | |
---|
1388 | textitem->text = text; |
---|
1389 | textitem->attr_list = attr_list; |
---|
1390 | |
---|
1391 | pango_layout_set_text (textitem->layout, text, -1); |
---|
1392 | |
---|
1393 | gnome_canvas_text_apply_attributes (textitem); |
---|
1394 | } |
---|
1395 | |
---|
1396 | /* Update handler for the text item */ |
---|
1397 | static void |
---|
1398 | gnome_canvas_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) |
---|
1399 | { |
---|
1400 | GnomeCanvasText *text; |
---|
1401 | double x1, y1, x2, y2; |
---|
1402 | |
---|
1403 | text = GNOME_CANVAS_TEXT (item); |
---|
1404 | |
---|
1405 | if (parent_class->update) |
---|
1406 | (* parent_class->update) (item, affine, clip_path, flags); |
---|
1407 | |
---|
1408 | set_text_gc_foreground (text); |
---|
1409 | set_stipple (text, text->stipple, TRUE); |
---|
1410 | get_bounds (text, &x1, &y1, &x2, &y2); |
---|
1411 | |
---|
1412 | gnome_canvas_update_bbox (item, |
---|
1413 | floor (x1), floor (y1), |
---|
1414 | ceil (x2), ceil (y2)); |
---|
1415 | } |
---|
1416 | |
---|
1417 | /* Realize handler for the text item */ |
---|
1418 | static void |
---|
1419 | gnome_canvas_text_realize (GnomeCanvasItem *item) |
---|
1420 | { |
---|
1421 | GnomeCanvasText *text; |
---|
1422 | |
---|
1423 | text = GNOME_CANVAS_TEXT (item); |
---|
1424 | |
---|
1425 | if (parent_class->realize) |
---|
1426 | (* parent_class->realize) (item); |
---|
1427 | |
---|
1428 | text->gc = gdk_gc_new (item->canvas->layout.bin_window); |
---|
1429 | } |
---|
1430 | |
---|
1431 | /* Unrealize handler for the text item */ |
---|
1432 | static void |
---|
1433 | gnome_canvas_text_unrealize (GnomeCanvasItem *item) |
---|
1434 | { |
---|
1435 | GnomeCanvasText *text; |
---|
1436 | |
---|
1437 | text = GNOME_CANVAS_TEXT (item); |
---|
1438 | |
---|
1439 | gdk_gc_unref (text->gc); |
---|
1440 | text->gc = NULL; |
---|
1441 | |
---|
1442 | if (parent_class->unrealize) |
---|
1443 | (* parent_class->unrealize) (item); |
---|
1444 | } |
---|
1445 | |
---|
1446 | /* Draw handler for the text item */ |
---|
1447 | static void |
---|
1448 | gnome_canvas_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable, |
---|
1449 | int x, int y, int width, int height) |
---|
1450 | { |
---|
1451 | GnomeCanvasText *text; |
---|
1452 | GdkRectangle rect; |
---|
1453 | |
---|
1454 | text = GNOME_CANVAS_TEXT (item); |
---|
1455 | |
---|
1456 | if (!text->text) |
---|
1457 | return; |
---|
1458 | |
---|
1459 | if (text->clip) { |
---|
1460 | rect.x = text->clip_cx - x; |
---|
1461 | rect.y = text->clip_cy - y; |
---|
1462 | rect.width = text->clip_cwidth; |
---|
1463 | rect.height = text->clip_cheight; |
---|
1464 | |
---|
1465 | gdk_gc_set_clip_rectangle (text->gc, &rect); |
---|
1466 | } |
---|
1467 | |
---|
1468 | if (text->stipple) |
---|
1469 | gnome_canvas_set_stipple_origin (item->canvas, text->gc); |
---|
1470 | |
---|
1471 | |
---|
1472 | gdk_draw_layout (drawable, text->gc, text->cx - x, text->cy - y, text->layout); |
---|
1473 | |
---|
1474 | if (text->clip) |
---|
1475 | gdk_gc_set_clip_rectangle (text->gc, NULL); |
---|
1476 | } |
---|
1477 | |
---|
1478 | |
---|
1479 | /* Render handler for the text item */ |
---|
1480 | static void |
---|
1481 | gnome_canvas_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf) |
---|
1482 | { |
---|
1483 | GnomeCanvasText *text; |
---|
1484 | guint32 fg_color; |
---|
1485 | int render_x = 0, render_y = 0; /* offsets for text rendering, |
---|
1486 | * for clipping rectangles */ |
---|
1487 | int x, y; |
---|
1488 | int w, h; |
---|
1489 | guchar *dst, *src; |
---|
1490 | int src_dx, src_dy; |
---|
1491 | int i, alpha; |
---|
1492 | int bm_rows, bm_width; |
---|
1493 | |
---|
1494 | text = GNOME_CANVAS_TEXT (item); |
---|
1495 | |
---|
1496 | if (!text->text) |
---|
1497 | return; |
---|
1498 | |
---|
1499 | fg_color = text->rgba; |
---|
1500 | |
---|
1501 | gnome_canvas_buf_ensure_buf (buf); |
---|
1502 | |
---|
1503 | bm_rows = (text->clip) ? text->clip_cheight : text->height; |
---|
1504 | bm_width = (text->clip) ? text->clip_cwidth : text->max_width; |
---|
1505 | if(text->priv->render_dirty || |
---|
1506 | bm_rows != text->priv->bitmap.rows || |
---|
1507 | bm_width != text->priv->bitmap.width) { |
---|
1508 | if(text->priv->bitmap.buffer) { |
---|
1509 | g_free(text->priv->bitmap.buffer); |
---|
1510 | } |
---|
1511 | text->priv->bitmap.rows = bm_rows; |
---|
1512 | text->priv->bitmap.width = bm_width; |
---|
1513 | text->priv->bitmap.pitch = (text->priv->bitmap.width+3)&~3; |
---|
1514 | text->priv->bitmap.buffer = g_malloc0 (text->priv->bitmap.rows * text->priv->bitmap.pitch); |
---|
1515 | text->priv->bitmap.num_grays = 256; |
---|
1516 | text->priv->bitmap.pixel_mode = ft_pixel_mode_grays; |
---|
1517 | |
---|
1518 | /* What this does is when a clipping rectangle is |
---|
1519 | being used shift the rendering of the text by the |
---|
1520 | correct amount so that the correct result is |
---|
1521 | obtained as if all text was rendered, then clipped. |
---|
1522 | In this sense we can use smaller buffers and less |
---|
1523 | rendeirng since hopefully FreeType2 checks to see |
---|
1524 | if the glyph falls in the bounding box before |
---|
1525 | rasterizing it. */ |
---|
1526 | |
---|
1527 | if(text->clip) { |
---|
1528 | render_x = text->cx - text->clip_cx; |
---|
1529 | render_y = text->cy - text->clip_cy; |
---|
1530 | } |
---|
1531 | |
---|
1532 | pango_ft2_render_layout (&text->priv->bitmap, text->layout, render_x, render_y); |
---|
1533 | |
---|
1534 | text->priv->render_dirty = 0; |
---|
1535 | } |
---|
1536 | |
---|
1537 | if (text->clip) { |
---|
1538 | x = text->clip_cx - buf->rect.x0; |
---|
1539 | y = text->clip_cy - buf->rect.y0; |
---|
1540 | } else { |
---|
1541 | x = text->cx - buf->rect.x0; |
---|
1542 | y = text->cy - buf->rect.y0; |
---|
1543 | } |
---|
1544 | |
---|
1545 | w = text->priv->bitmap.width; |
---|
1546 | h = text->priv->bitmap.rows; |
---|
1547 | |
---|
1548 | src_dx = src_dy = 0; |
---|
1549 | |
---|
1550 | if (x + w > buf->rect.x1 - buf->rect.x0) { |
---|
1551 | w = buf->rect.x1 - buf->rect.x0 - x; |
---|
1552 | } |
---|
1553 | |
---|
1554 | if (y + h > buf->rect.y1 - buf->rect.y0) { |
---|
1555 | h = buf->rect.y1 - buf->rect.y0 - y; |
---|
1556 | } |
---|
1557 | |
---|
1558 | if (x < 0) { |
---|
1559 | w -= - x; |
---|
1560 | src_dx += - x; |
---|
1561 | x = 0; |
---|
1562 | } |
---|
1563 | |
---|
1564 | if (y < 0) { |
---|
1565 | h -= -y; |
---|
1566 | src_dy += - y; |
---|
1567 | y = 0; |
---|
1568 | } |
---|
1569 | |
---|
1570 | dst = buf->buf + y * buf->buf_rowstride + x * 3; |
---|
1571 | src = text->priv->bitmap.buffer + |
---|
1572 | src_dy * text->priv->bitmap.pitch + src_dx; |
---|
1573 | while (h-- > 0) { |
---|
1574 | i = w; |
---|
1575 | while (i-- > 0) { |
---|
1576 | /* FIXME: Do the libart thing instead of divide by 255 */ |
---|
1577 | alpha = ((fg_color & 0xff) * (*src)) / 255; |
---|
1578 | dst[0] = (dst[0] * (255 - alpha) + ((fg_color >> 24) & 0xff) * alpha) / 255; |
---|
1579 | dst[1] = (dst[1] * (255 - alpha) + ((fg_color >> 16) & 0xff) * alpha) / 255; |
---|
1580 | dst[2] = (dst[2] * (255 - alpha) + ((fg_color >> 8) & 0xff) * alpha) / 255; |
---|
1581 | dst += 3; |
---|
1582 | src += 1; |
---|
1583 | } |
---|
1584 | dst += buf->buf_rowstride - w*3; |
---|
1585 | src += text->priv->bitmap.pitch - w; |
---|
1586 | } |
---|
1587 | |
---|
1588 | buf->is_bg = 0; |
---|
1589 | return; |
---|
1590 | } |
---|
1591 | |
---|
1592 | /* Point handler for the text item */ |
---|
1593 | static double |
---|
1594 | gnome_canvas_text_point (GnomeCanvasItem *item, double x, double y, |
---|
1595 | int cx, int cy, GnomeCanvasItem **actual_item) |
---|
1596 | { |
---|
1597 | GnomeCanvasText *text; |
---|
1598 | PangoLayoutIter *iter; |
---|
1599 | int x1, y1, x2, y2; |
---|
1600 | int dx, dy; |
---|
1601 | double dist, best; |
---|
1602 | |
---|
1603 | text = GNOME_CANVAS_TEXT (item); |
---|
1604 | |
---|
1605 | *actual_item = item; |
---|
1606 | |
---|
1607 | /* The idea is to build bounding rectangles for each of the lines of |
---|
1608 | * text (clipped by the clipping rectangle, if it is activated) and see |
---|
1609 | * whether the point is inside any of these. If it is, we are done. |
---|
1610 | * Otherwise, calculate the distance to the nearest rectangle. |
---|
1611 | */ |
---|
1612 | |
---|
1613 | best = 1.0e36; |
---|
1614 | |
---|
1615 | iter = pango_layout_get_iter (text->layout); |
---|
1616 | do { |
---|
1617 | PangoRectangle log_rect; |
---|
1618 | |
---|
1619 | pango_layout_iter_get_line_extents (iter, NULL, &log_rect); |
---|
1620 | |
---|
1621 | if (text->clip) { |
---|
1622 | x1 = PANGO_PIXELS (log_rect.x); |
---|
1623 | y1 = PANGO_PIXELS (log_rect.y); |
---|
1624 | x2 = PANGO_PIXELS (log_rect.x+log_rect.width); |
---|
1625 | y2 = PANGO_PIXELS (log_rect.y+log_rect.height); |
---|
1626 | |
---|
1627 | |
---|
1628 | if (x1 < text->clip_cx) |
---|
1629 | x1 = text->clip_cx; |
---|
1630 | |
---|
1631 | if (y1 < text->clip_cy) |
---|
1632 | y1 = text->clip_cy; |
---|
1633 | |
---|
1634 | if (x2 > (text->clip_cx + text->clip_width)) |
---|
1635 | x2 = text->clip_cx + text->clip_width; |
---|
1636 | |
---|
1637 | if (y2 > (text->clip_cy + text->clip_height)) |
---|
1638 | y2 = text->clip_cy + text->clip_height; |
---|
1639 | |
---|
1640 | if ((x1 >= x2) || (y1 >= y2)) |
---|
1641 | continue; |
---|
1642 | } else { |
---|
1643 | x1 = text->x; |
---|
1644 | y1 = text->y; |
---|
1645 | x2 = log_rect.width; |
---|
1646 | y2 = log_rect.height; |
---|
1647 | } |
---|
1648 | |
---|
1649 | /* Calculate distance from point to rectangle */ |
---|
1650 | |
---|
1651 | if (cx < x1) |
---|
1652 | dx = x1 - cx; |
---|
1653 | else if (cx >= x2) |
---|
1654 | dx = cx - x2 + 1; |
---|
1655 | else |
---|
1656 | dx = 0; |
---|
1657 | |
---|
1658 | if (cy < y1) |
---|
1659 | dy = y1 - cy; |
---|
1660 | else if (cy >= y2) |
---|
1661 | dy = cy - y2 + 1; |
---|
1662 | else |
---|
1663 | dy = 0; |
---|
1664 | |
---|
1665 | if ((dx == 0) && (dy == 0)) { |
---|
1666 | pango_layout_iter_free(iter); |
---|
1667 | return 0.0; |
---|
1668 | } |
---|
1669 | |
---|
1670 | dist = sqrt (dx * dx + dy * dy); |
---|
1671 | if (dist < best) |
---|
1672 | best = dist; |
---|
1673 | |
---|
1674 | } while (pango_layout_iter_next_line(iter)); |
---|
1675 | |
---|
1676 | pango_layout_iter_free(iter); |
---|
1677 | |
---|
1678 | return best / item->canvas->pixels_per_unit; |
---|
1679 | } |
---|
1680 | |
---|
1681 | /* Bounds handler for the text item */ |
---|
1682 | static void |
---|
1683 | gnome_canvas_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2) |
---|
1684 | { |
---|
1685 | GnomeCanvasText *text; |
---|
1686 | double width, height; |
---|
1687 | |
---|
1688 | text = GNOME_CANVAS_TEXT (item); |
---|
1689 | |
---|
1690 | *x1 = text->x; |
---|
1691 | *y1 = text->y; |
---|
1692 | |
---|
1693 | if (text->clip) { |
---|
1694 | width = text->clip_width; |
---|
1695 | height = text->clip_height; |
---|
1696 | } else { |
---|
1697 | width = text->max_width / item->canvas->pixels_per_unit; |
---|
1698 | height = text->height / item->canvas->pixels_per_unit; |
---|
1699 | } |
---|
1700 | |
---|
1701 | switch (text->anchor) { |
---|
1702 | case GTK_ANCHOR_NW: |
---|
1703 | case GTK_ANCHOR_W: |
---|
1704 | case GTK_ANCHOR_SW: |
---|
1705 | break; |
---|
1706 | |
---|
1707 | case GTK_ANCHOR_N: |
---|
1708 | case GTK_ANCHOR_CENTER: |
---|
1709 | case GTK_ANCHOR_S: |
---|
1710 | *x1 -= width / 2.0; |
---|
1711 | break; |
---|
1712 | |
---|
1713 | case GTK_ANCHOR_NE: |
---|
1714 | case GTK_ANCHOR_E: |
---|
1715 | case GTK_ANCHOR_SE: |
---|
1716 | *x1 -= width; |
---|
1717 | break; |
---|
1718 | |
---|
1719 | default: |
---|
1720 | break; |
---|
1721 | } |
---|
1722 | |
---|
1723 | switch (text->anchor) { |
---|
1724 | case GTK_ANCHOR_NW: |
---|
1725 | case GTK_ANCHOR_N: |
---|
1726 | case GTK_ANCHOR_NE: |
---|
1727 | break; |
---|
1728 | |
---|
1729 | case GTK_ANCHOR_W: |
---|
1730 | case GTK_ANCHOR_CENTER: |
---|
1731 | case GTK_ANCHOR_E: |
---|
1732 | *y1 -= height / 2.0; |
---|
1733 | break; |
---|
1734 | |
---|
1735 | case GTK_ANCHOR_SW: |
---|
1736 | case GTK_ANCHOR_S: |
---|
1737 | case GTK_ANCHOR_SE: |
---|
1738 | *y1 -= height; |
---|
1739 | break; |
---|
1740 | |
---|
1741 | default: |
---|
1742 | break; |
---|
1743 | } |
---|
1744 | |
---|
1745 | *x2 = *x1 + width; |
---|
1746 | *y2 = *y1 + height; |
---|
1747 | } |
---|