1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * gnome-canvas-hacktext.c: Hacktext item type for GnomeCanvas widget
4 * This is mainly used for gnome-print preview context
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public License
8 * as published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Federico Mena <federico@nuclecu.unam.mx>
22 * Raph Levien <raph@acm.org>
23 * Lauris Kaplinski <lauris@helixcode.com>
25 * Copyright (C) 1998-1999 The Free Software Foundation
26 * Copyright (C) 2000-2002 Ximian Inc.
39 #include <libgnomeprint/gnome-font.h>
40 #include <libgnomeprint/gnome-rfont.h>
41 #include <libgnomeprint/gnome-pgl.h>
42 #include "canvas-hacktext.h"
56 static void gl_canvas_hacktext_class_init (glCanvasHacktextClass *class);
57 static void gl_canvas_hacktext_init (glCanvasHacktext *hacktext);
58 static void gl_canvas_hacktext_destroy (GtkObject *object);
59 static void gl_canvas_hacktext_set_arg (GObject *object,
63 static void gl_canvas_hacktext_get_arg (GObject *object,
68 static void gl_canvas_hacktext_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
69 static void gl_canvas_hacktext_realize (GnomeCanvasItem *item);
70 static void gl_canvas_hacktext_unrealize (GnomeCanvasItem *item);
71 static double gl_canvas_hacktext_point (GnomeCanvasItem *item, double x, double y,
72 int cx, int cy, GnomeCanvasItem **actual_item);
73 static void gl_canvas_hacktext_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
74 static void gl_canvas_hacktext_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
75 static void gl_canvas_hacktext_req_repaint (glCanvasHacktext *hacktext, ArtIRect *bbox);
78 static GnomeCanvasItemClass *parent_class;
80 struct _glCanvasHacktextPriv {
83 GnomeGlyphList * glyphlist;
84 GnomePosGlyphList * pgl;
85 double affine[6]; /* the text to world transform (NB! mirrored Y) */
89 gl_canvas_hacktext_get_type (void)
91 static GType hacktext_type = 0;
94 static const GTypeInfo hacktext_info = {
95 sizeof (glCanvasHacktextClass),
98 (GClassInitFunc) gl_canvas_hacktext_class_init,
101 sizeof (glCanvasHacktext),
103 (GInstanceInitFunc) gl_canvas_hacktext_init,
107 hacktext_type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM,
112 return hacktext_type;
116 gl_canvas_hacktext_class_init (glCanvasHacktextClass *class)
118 GObjectClass *gobject_class;
119 GtkObjectClass *object_class;
120 GnomeCanvasItemClass *item_class;
122 gobject_class = (GObjectClass *) class;
123 object_class = (GtkObjectClass *) class;
124 item_class = (GnomeCanvasItemClass *) class;
126 parent_class = g_type_class_peek_parent (class);
128 gobject_class->set_property = gl_canvas_hacktext_set_arg;
129 gobject_class->get_property = gl_canvas_hacktext_get_arg;
131 g_object_class_install_property
134 g_param_spec_string ("text", NULL, NULL,
136 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
138 g_object_class_install_property
141 g_param_spec_pointer ("glyphlist", NULL, NULL,
142 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
144 g_object_class_install_property
147 g_param_spec_string ("fill_color", NULL, NULL,
149 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
151 g_object_class_install_property
154 g_param_spec_uint ("fill_color_rgba", NULL, NULL,
156 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
158 g_object_class_install_property
161 g_param_spec_pointer ("font", NULL, NULL,
162 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
164 g_object_class_install_property
167 g_param_spec_double ("x", NULL, NULL,
168 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
169 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
171 g_object_class_install_property
174 g_param_spec_double ("y", NULL, NULL,
175 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
176 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
179 object_class->destroy = gl_canvas_hacktext_destroy;
181 item_class->update = gl_canvas_hacktext_update;
182 item_class->realize = gl_canvas_hacktext_realize;
183 item_class->unrealize = gl_canvas_hacktext_unrealize;
184 item_class->point = gl_canvas_hacktext_point;
185 item_class->bounds = gl_canvas_hacktext_bounds;
186 item_class->render = gl_canvas_hacktext_render;
190 gl_canvas_hacktext_init (glCanvasHacktext *hacktext)
192 hacktext->text = NULL;
193 hacktext->priv = g_new (glCanvasHacktextPriv, 1);
194 hacktext->priv->font = NULL;
195 hacktext->priv->glyphlist = NULL;
196 hacktext->priv->pgl = NULL;
198 art_affine_identity (hacktext->priv->affine);
202 gl_canvas_hacktext_destroy (GtkObject *object)
204 glCanvasHacktext *hacktext;
206 g_return_if_fail (object != NULL);
207 g_return_if_fail (GL_IS_CANVAS_HACKTEXT (object));
209 hacktext = GL_CANVAS_HACKTEXT (object);
211 if (hacktext->text) {
212 g_free (hacktext->text);
213 hacktext->text = NULL;
216 if (hacktext->priv) {
217 if (hacktext->priv->font) gnome_font_unref (hacktext->priv->font);
218 if (hacktext->priv->glyphlist) gnome_glyphlist_unref (hacktext->priv->glyphlist);
219 if (hacktext->priv->pgl) gnome_pgl_destroy (hacktext->priv->pgl);
220 g_free (hacktext->priv);
221 hacktext->priv = NULL;
224 if (GTK_OBJECT_CLASS (parent_class)->destroy)
225 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
229 art_drect_hacktext (ArtDRect *bbox, glCanvasHacktext *hacktext)
231 g_assert (bbox != NULL);
232 g_assert (hacktext != NULL);
234 g_return_if_fail (hacktext->priv);
236 if (GTK_OBJECT_FLAGS (hacktext) & GNOME_CANVAS_UPDATE_REQUESTED) {
237 gnome_canvas_update_now (GNOME_CANVAS_ITEM (hacktext)->canvas);
240 if (!hacktext->priv->pgl) return;
242 gnome_pgl_bbox (hacktext->priv->pgl, bbox);
245 /* Computes the bounding box of the hacktext. Assumes that the number of points in the hacktext is
249 get_bounds (glCanvasHacktext *hacktext, double *bx1, double *by1, double *bx2, double *by2)
253 /* Compute bounds of hacktext */
254 art_drect_hacktext (&bbox, hacktext);
264 #ifdef IFED_OUT_BY_CHEMA_TO_KILL_COMPILE_WARNING
265 /* Convenience function to set a GC's foreground color to the specified pixel value */
267 set_gc_foreground (GdkGC *gc, gulong pixel)
275 gdk_gc_set_foreground (gc, &c);
280 gl_canvas_hacktext_set_arg (GObject *object,
285 GnomeCanvasItem *item;
286 glCanvasHacktext *bp;
292 item = GNOME_CANVAS_ITEM (object);
293 bp = GL_CANVAS_HACKTEXT (object);
302 if (bp->priv->glyphlist) {
303 gnome_glyphlist_unref (bp->priv->glyphlist);
304 bp->priv->glyphlist = NULL;
307 if (text) bp->text = g_value_dup_string (value);
309 gnome_canvas_item_request_update (item);
313 gl = g_value_get_pointer (value);
320 if (bp->priv->glyphlist) {
321 gnome_glyphlist_unref (bp->priv->glyphlist);
322 bp->priv->glyphlist = NULL;
325 /* fixme: should be duplicate() */
327 if (gl) gnome_glyphlist_ref (gl);
329 bp->priv->glyphlist = gl;
331 gnome_canvas_item_request_update (item);
336 if (gnome_canvas_get_color (item->canvas, g_value_get_string(value), &color)) {
338 bp->fill_pixel = color.pixel;
340 ((color.red & 0xff00) << 16) |
341 ((color.green & 0xff00) << 8) |
342 (color.blue & 0xff00) |
345 bp->fill_set = FALSE;
349 gnome_canvas_item_request_update (item);
352 case ARG_FILL_COLOR_RGBA:
354 bp->fill_rgba = g_value_get_uint (value);
356 /* should probably request repaint on the fill_svp */
357 gnome_canvas_item_request_update (item);
362 font = g_value_get_pointer (value);
363 if (font) gnome_font_ref (font);
364 if (bp->priv->font) gnome_font_unref (bp->priv->font);
365 bp->priv->font = font;
366 bp->size = gnome_font_get_size (bp->priv->font);
367 gnome_canvas_item_request_update (item);
371 bp->x = g_value_get_double (value);
372 gnome_canvas_item_request_update (item);
376 bp->y = g_value_get_double (value);
377 gnome_canvas_item_request_update (item);
386 gl_canvas_hacktext_get_arg (GObject *object,
391 glCanvasHacktext *bp;
393 bp = GL_CANVAS_HACKTEXT (object);
398 g_value_set_string (value, g_strdup (bp->text));
400 g_value_set_string (value, NULL);
402 case ARG_FILL_COLOR_RGBA:
403 g_value_set_uint (value, bp->fill_color);
407 g_value_set_pointer (value, bp->priv->font);
411 g_value_set_double (value, bp->x);
415 g_value_set_double (value, bp->y);
419 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
425 gl_canvas_hacktext_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
427 glCanvasHacktext *hacktext;
428 ArtIRect ibbox = {0, 0, 0, 0};
430 hacktext = (glCanvasHacktext *) item;
432 if (parent_class->update)
433 (* parent_class->update) (item, affine, clip_path, flags);
435 if (hacktext->priv->pgl) gl_canvas_hacktext_req_repaint (hacktext, NULL);
437 gnome_canvas_item_reset_bounds (item);
439 hacktext->priv->affine[0] = affine[0];
440 hacktext->priv->affine[1] = affine[1];
441 hacktext->priv->affine[2] = -affine[2];
442 hacktext->priv->affine[3] = -affine[3];
443 hacktext->priv->affine[4] = affine[4] + hacktext->x * affine[0] + hacktext->y * affine[2];
444 hacktext->priv->affine[5] = affine[5] + hacktext->x * affine[1] + hacktext->y * affine[3];
446 if (hacktext->text) {
447 if (hacktext->priv->glyphlist) {
448 gnome_glyphlist_unref (hacktext->priv->glyphlist);
449 hacktext->priv->glyphlist = NULL;
452 if (!hacktext->priv->font) return;
454 hacktext->priv->glyphlist = gnome_glyphlist_from_text_dumb (hacktext->priv->font, hacktext->fill_rgba,
459 if (hacktext->priv->glyphlist) {
460 GnomePosGlyphList * pgl;
462 pgl = gnome_pgl_from_gl (hacktext->priv->glyphlist, hacktext->priv->affine, GNOME_PGL_RENDER_DEFAULT);
464 if (hacktext->priv->pgl) gnome_pgl_destroy (hacktext->priv->pgl);
466 hacktext->priv->pgl = pgl;
469 gl_canvas_hacktext_req_repaint (hacktext, &ibbox);
471 hacktext->item.x1 = ibbox.x0;
472 hacktext->item.y1 = ibbox.y0;
473 hacktext->item.x2 = ibbox.x1;
474 hacktext->item.y2 = ibbox.y1;
478 gl_canvas_hacktext_realize (GnomeCanvasItem *item)
480 glCanvasHacktext *hacktext;
482 hacktext = (glCanvasHacktext *) item;
484 if (parent_class->realize)
485 (* parent_class->realize) (item);
489 gl_canvas_hacktext_unrealize (GnomeCanvasItem *item)
491 glCanvasHacktext *hacktext;
493 hacktext = (glCanvasHacktext *) item;
495 if (parent_class->unrealize)
496 (* parent_class->unrealize) (item);
500 gl_canvas_hacktext_point (GnomeCanvasItem *item, double mx, double my,
501 int cx, int cy, GnomeCanvasItem **actual_item)
503 glCanvasHacktext * hacktext;
505 hacktext = (glCanvasHacktext *) item;
507 if (!hacktext->priv->pgl) return 1e18;
511 if (gnome_pgl_test_point (hacktext->priv->pgl, cx, cy)) return 0.0;
517 gl_canvas_hacktext_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
519 glCanvasHacktext *hacktext;
521 g_return_if_fail (item != NULL);
522 g_return_if_fail (GL_IS_CANVAS_HACKTEXT (item));
524 hacktext = GL_CANVAS_HACKTEXT (item);
526 if (hacktext->text == NULL) {
527 *x1 = *y1 = *x2 = *y2 = 0.0;
531 get_bounds (hacktext, x1, y1, x2, y2);
535 gl_canvas_hacktext_req_repaint (glCanvasHacktext *hacktext,
540 g_return_if_fail (hacktext->priv);
542 if (!hacktext->priv->pgl) return;
544 if (gnome_pgl_bbox (hacktext->priv->pgl, &gbbox)) {
546 art_drect_to_irect (&ibox, &gbbox);
547 gnome_canvas_request_redraw (hacktext->item.canvas, ibox.x0, ibox.y0, ibox.x1, ibox.y1);
548 if (bbox) art_irect_union (bbox, bbox, &ibox);
553 gl_canvas_hacktext_render (GnomeCanvasItem *item,
556 glCanvasHacktext * hacktext;
558 hacktext = (glCanvasHacktext *) item;
560 g_return_if_fail (hacktext->priv);
562 if (!hacktext->priv->pgl) return;
564 gnome_canvas_buf_ensure_buf (buf);
568 gnome_rfont_render_pgl_rgb8 (hacktext->priv->pgl,
569 -buf->rect.x0, -buf->rect.y0,
571 buf->rect.x1 - buf->rect.x0,
572 buf->rect.y1 - buf->rect.y0,
574 GNOME_RFONT_RENDER_DEFAULT);