source: trunk/third/libgnomeprintui/libgnomeprintui/gnome-canvas-hacktext.c @ 20964

Revision 20964, 14.7 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20963, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 *  gnome-canvas-hacktext.c: Hacktext CanvasItem, used for the PrintPreview context
4 *
5 *  This program is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Library General Public License
7 *  as published by the Free Software Foundation; either version 2 of
8 *  the License, or (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU Library General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Library General Public
16 *  License along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *  Authors:
20 *    Federico Mena <federico@nuclecu.unam.mx>
21 *    Raph Levien <raph@acm.org>
22 *    Lauris Kaplinski <lauris@helixcode.com>
23 *
24 *  Copyright (C) 1998-1999 The Free Software Foundation
25 *  Copyright (C) 2000-2002 Ximian Inc.
26 *
27 */
28
29/*
30 * FIXME: TODO: Clipping
31 */
32
33#include <config.h>
34
35#include <math.h>
36#include <string.h>
37
38#include <libgnomeprint/gnome-pgl.h>
39#include <libgnomeprint/gnome-font.h>
40#include <libgnomeprint/gnome-rfont.h>
41
42#include "gnome-canvas-hacktext.h"
43#include "gnome-print-i18n.h"
44
45enum {
46        PROP_0,
47        PROP_TEXT,
48        PROP_GLYPHLIST,
49        PROP_FILL_COLOR,
50        PROP_FILL_COLOR_RGBA,
51        PROP_FONT,
52        PROP_X,
53        PROP_Y
54};
55
56
57static void gnome_canvas_hacktext_class_init    (GnomeCanvasHacktextClass *class);
58static void gnome_canvas_hacktext_init          (GnomeCanvasHacktext      *hacktext);
59static void gnome_canvas_hacktext_destroy       (GtkObject                *object);
60static void gnome_canvas_hacktext_set_property  (GObject                  *object,
61                                                 guint                    param_id,
62                                                 const GValue             *value,
63                                                 GParamSpec               *pspec);
64static void gnome_canvas_hacktext_get_property  (GObject                  *object,
65                                                 guint                    param_id,
66                                                 GValue                   *value,
67                                                 GParamSpec               *pspec);
68static void   gnome_canvas_hacktext_update      (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
69static void   gnome_canvas_hacktext_realize     (GnomeCanvasItem *item);
70static void   gnome_canvas_hacktext_unrealize   (GnomeCanvasItem *item);
71static double gnome_canvas_hacktext_point       (GnomeCanvasItem *item, double x, double y,
72                                                int cx, int cy, GnomeCanvasItem **actual_item);
73static void   gnome_canvas_hacktext_bounds      (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
74static void   gnome_canvas_hacktext_render      (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
75static void   gnome_canvas_hacktext_req_repaint (GnomeCanvasHacktext *hacktext, ArtIRect *bbox);
76
77
78static GnomeCanvasItemClass *parent_class;
79
80struct _GnomeCanvasHacktextPriv {
81        GnomeFont * font;
82
83        GnomeGlyphList * glyphlist;
84        GnomePosGlyphList * pgl;
85        double affine[6]; /* the text to world transform (NB! mirrored Y) */
86};
87
88GType
89gnome_canvas_hacktext_get_type (void)
90{
91        static GType type = 0;
92        if (!type) {
93                GTypeInfo info = {
94                        sizeof (GnomeCanvasHacktextClass),
95                        NULL, NULL,
96                        (GClassInitFunc) gnome_canvas_hacktext_class_init,
97                        NULL, NULL,
98                        sizeof (GnomeCanvasHacktext),
99                        0,
100                        (GInstanceInitFunc) gnome_canvas_hacktext_init,
101                        NULL
102                };
103                type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM, "GnomeCanvasHacktext", &info, 0);
104        }
105        return type;
106}
107
108static void
109gnome_canvas_hacktext_class_init (GnomeCanvasHacktextClass *class)
110{
111        GObjectClass *gobject_class;
112        GtkObjectClass *object_class;
113        GnomeCanvasItemClass *item_class;
114
115        object_class = (GtkObjectClass *) class;
116        gobject_class = (GObjectClass *) class;
117        item_class = (GnomeCanvasItemClass *) class;
118
119        parent_class = g_type_class_peek_parent (class);
120
121        gobject_class->set_property = gnome_canvas_hacktext_set_property;
122        gobject_class->get_property = gnome_canvas_hacktext_get_property;
123
124        g_object_class_install_property
125                (gobject_class,
126                 PROP_TEXT,
127                 g_param_spec_string ("text",
128                                      _("Text"),
129                                      _("Text to render"),
130                                      NULL,
131                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
132        g_object_class_install_property
133                (gobject_class,
134                 PROP_X,
135                 g_param_spec_double ("x", NULL, NULL,
136                                      -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
137                                      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
138        g_object_class_install_property
139                (gobject_class,
140                 PROP_Y,
141                 g_param_spec_double ("y", NULL, NULL,
142                                      -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
143                                      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
144         g_object_class_install_property
145                (gobject_class,
146                 PROP_GLYPHLIST,
147                 g_param_spec_pointer ("glyphlist",
148                                       _("Glyphlist"),
149                                       _("Glyphlist"),
150                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
151         g_object_class_install_property
152                (gobject_class,
153                 PROP_FILL_COLOR,
154                 g_param_spec_string ("fill_color",
155                                      _("Color"),
156                                      _("Text color, as string"),
157                                      NULL,
158                                      G_PARAM_WRITABLE));
159         g_object_class_install_property
160                (gobject_class,
161                 PROP_FILL_COLOR_RGBA,
162                 g_param_spec_uint ("fill_color_rgba",
163                                    _("Color"),
164                                    _("Text color, as an R/G/B/A combined integer"),
165                                    0, G_MAXUINT, 0,
166                                    (G_PARAM_READABLE | G_PARAM_WRITABLE)));
167         g_object_class_install_property
168                 (gobject_class,
169                  PROP_FONT,
170                  g_param_spec_object ("font",
171                                       _("Font"),
172                                       _("Font as a GnomeFont struct"),
173                                       GNOME_TYPE_FONT,
174                                       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
175
176        object_class->destroy = gnome_canvas_hacktext_destroy;
177
178        item_class->update    = gnome_canvas_hacktext_update;
179        item_class->realize   = gnome_canvas_hacktext_realize;
180        item_class->unrealize = gnome_canvas_hacktext_unrealize;
181        item_class->point     = gnome_canvas_hacktext_point;
182        item_class->bounds    = gnome_canvas_hacktext_bounds;
183        item_class->render    = gnome_canvas_hacktext_render;
184}
185
186static void
187gnome_canvas_hacktext_init (GnomeCanvasHacktext *hacktext)
188{
189        hacktext->text = NULL;
190        hacktext->priv = g_new (GnomeCanvasHacktextPriv, 1);
191        hacktext->priv->pgl = NULL;
192        hacktext->priv->font = NULL;
193        hacktext->priv->glyphlist = NULL;
194
195        art_affine_identity (hacktext->priv->affine);
196}
197
198static void
199gnome_canvas_hacktext_destroy (GtkObject *object)
200{
201        GnomeCanvasHacktext *hacktext;
202
203        g_return_if_fail (object != NULL);
204        g_return_if_fail (GNOME_IS_CANVAS_HACKTEXT (object));
205
206        hacktext = GNOME_CANVAS_HACKTEXT (object);
207
208        if (hacktext->text) {
209                g_free (hacktext->text);
210                hacktext->text = NULL;
211        }
212
213        if (hacktext->priv) {
214                if (hacktext->priv->font)
215                        gnome_font_unref (hacktext->priv->font);
216                if (hacktext->priv->glyphlist)
217                        gnome_glyphlist_unref (hacktext->priv->glyphlist);
218                if (hacktext->priv->pgl)
219                        gnome_pgl_destroy (hacktext->priv->pgl);
220                g_free (hacktext->priv);
221                hacktext->priv = NULL;
222        }
223
224        if (GTK_OBJECT_CLASS (parent_class)->destroy)
225                (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
226}
227
228static void
229art_drect_hacktext (ArtDRect *bbox, GnomeCanvasHacktext *hacktext)
230{
231        g_assert (bbox != NULL);
232        g_assert (hacktext != NULL);
233
234        g_return_if_fail (hacktext->priv);
235
236        if (GTK_OBJECT_FLAGS (hacktext) & GNOME_CANVAS_UPDATE_REQUESTED) {
237                gnome_canvas_update_now (GNOME_CANVAS_ITEM (hacktext)->canvas);
238        }
239
240        if (!hacktext->priv->pgl)
241                return;
242
243        gnome_pgl_bbox (hacktext->priv->pgl, bbox);
244}
245
246/* Computes the bounding box of the hacktext.  Assumes that the number of points in the hacktext is
247 * not zero.
248 */
249static void
250get_bounds (GnomeCanvasHacktext *hacktext, double *bx1, double *by1, double *bx2, double *by2)
251{
252        ArtDRect bbox;
253
254        /* Compute bounds of hacktext */
255        art_drect_hacktext (&bbox, hacktext);
256
257        /* Done */
258
259        *bx1 = bbox.x0;
260        *by1 = bbox.y0;
261        *bx2 = bbox.x1;
262        *by2 = bbox.y1;
263}
264
265static void
266gnome_canvas_hacktext_set_property (GObject               *object,
267                                    guint                 param_id,
268                                    const GValue          *value,
269                                    GParamSpec            *pspec)
270{
271        GnomeCanvasItem *item;
272        GnomeCanvasHacktext *bp;
273        GnomeGlyphList * gl;
274        GdkColor color;
275        GnomeFont * font;
276
277        item = GNOME_CANVAS_ITEM (object);
278        bp = GNOME_CANVAS_HACKTEXT (object);
279
280        switch (param_id) {
281        case PROP_TEXT:
282                if (bp->text) {
283                        g_free (bp->text);
284                        bp->text = NULL;
285                }
286
287                if (bp->priv->glyphlist) {
288                        gnome_glyphlist_unref (bp->priv->glyphlist);
289                        bp->priv->glyphlist = NULL;
290                }
291
292                bp->text = g_value_dup_string (value);
293
294                gnome_canvas_item_request_update (item);
295                break;
296
297        case PROP_GLYPHLIST:
298                gl = g_value_get_pointer (value);
299
300                if (bp->text) {
301                        g_free (bp->text);
302                        bp->text = NULL;
303                }
304
305                if (bp->priv->glyphlist) {
306                        gnome_glyphlist_unref (bp->priv->glyphlist);
307                        bp->priv->glyphlist = NULL;
308                }
309
310                /* FIXME: should be duplicate() (Lauris) */
311                if (gl)
312                        gnome_glyphlist_ref (gl);
313
314                bp->priv->glyphlist = gl;
315
316                gnome_canvas_item_request_update (item);
317
318                break;
319
320        case PROP_FILL_COLOR:
321                if (gnome_canvas_get_color (item->canvas, g_value_get_string (value), &color)) {
322                        bp->fill_set = TRUE;
323                        bp->fill_pixel = color.pixel;
324                        bp->fill_rgba =
325                                ((color.red & 0xff00) << 16) |
326                                ((color.green & 0xff00) << 8) |
327                                (color.blue & 0xff00) |
328                                0xff;
329                } else {
330                        bp->fill_set = FALSE;
331                        bp->fill_rgba = 0;
332                }
333
334                gnome_canvas_item_request_update (item);
335                break;
336
337        case PROP_FILL_COLOR_RGBA:
338                bp->fill_set = TRUE;
339                bp->fill_rgba = g_value_get_uint (value);
340
341                /* should probably request repaint on the fill_svp */
342                gnome_canvas_item_request_update (item);
343
344                break;
345
346        case PROP_FONT:
347                font = g_value_get_object (value);
348                if (font)
349                        gnome_font_ref (font);
350                if (bp->priv->font)
351                        gnome_font_unref (bp->priv->font);
352                bp->priv->font = font;
353                bp->size = gnome_font_get_size (bp->priv->font);
354                gnome_canvas_item_request_update (item);
355                break;
356
357        case PROP_X:
358                bp->x = g_value_get_double (value);
359                gnome_canvas_item_request_update (item);
360                break;
361
362        case PROP_Y:
363                bp->y = g_value_get_double (value);
364                gnome_canvas_item_request_update (item);
365                break;
366
367        default:
368                break;
369        }
370}
371
372static void
373gnome_canvas_hacktext_get_property (GObject               *object,
374                                    guint                 param_id,
375                                    GValue                *value,
376                                    GParamSpec            *pspec)
377{
378        GnomeCanvasHacktextPriv *priv;
379        GnomeCanvasHacktext *bp;
380
381        bp = GNOME_CANVAS_HACKTEXT (object);
382        priv = (GnomeCanvasHacktextPriv *) bp->priv;
383
384        switch (param_id) {
385        case PROP_TEXT:
386                g_value_set_string (value, bp->text);
387                break;
388        case PROP_GLYPHLIST:
389                g_value_set_pointer (value, priv->glyphlist);
390                break;         
391        case PROP_FILL_COLOR_RGBA:
392                g_value_set_uint (value, bp->fill_color);
393                break;
394        case PROP_FONT:
395                g_value_set_object (value, bp->priv->font);
396                break;
397        case PROP_X:
398                g_value_set_double (value, bp->x);
399                break;
400        case PROP_Y:
401                g_value_set_double (value, bp->y);
402                break;
403        default:
404                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
405                break;
406        }
407}
408
409static void
410gnome_canvas_hacktext_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
411{
412        GnomeCanvasHacktext *hacktext;
413        ArtIRect ibbox = {0, 0, 0, 0};
414
415        hacktext = (GnomeCanvasHacktext *) item;
416
417        if (parent_class->update)
418                (* parent_class->update) (item, affine, clip_path, flags);
419
420        if (hacktext->priv->pgl)
421                gnome_canvas_hacktext_req_repaint (hacktext, NULL);
422
423        gnome_canvas_item_reset_bounds (item);
424
425        hacktext->priv->affine[0] = affine[0];
426        hacktext->priv->affine[1] = affine[1];
427        hacktext->priv->affine[2] = -affine[2];
428        hacktext->priv->affine[3] = -affine[3];
429        hacktext->priv->affine[4] = affine[4] + hacktext->x * affine[0] + hacktext->y * affine[2];
430        hacktext->priv->affine[5] = affine[5] + hacktext->x * affine[1] + hacktext->y * affine[3];
431
432        if (hacktext->text) {
433                if (hacktext->priv->glyphlist) {
434                        gnome_glyphlist_unref (hacktext->priv->glyphlist);
435                        hacktext->priv->glyphlist = NULL;
436                }
437
438                if (!hacktext->priv->font)
439                        return;
440
441                hacktext->priv->glyphlist = gnome_glyphlist_from_text_dumb (hacktext->priv->font, hacktext->fill_rgba,
442                                                                            0.0, 0.0,
443                                                                            hacktext->text);
444        }
445
446        if (hacktext->priv->glyphlist) {
447                GnomePosGlyphList * pgl;
448
449                pgl = gnome_pgl_from_gl (hacktext->priv->glyphlist, hacktext->priv->affine, GNOME_PGL_RENDER_DEFAULT);
450
451                if (hacktext->priv->pgl)
452                        gnome_pgl_destroy (hacktext->priv->pgl);
453
454                hacktext->priv->pgl = pgl;
455        }
456               
457        gnome_canvas_hacktext_req_repaint (hacktext, &ibbox);
458
459        hacktext->item.x1 = ibbox.x0;
460        hacktext->item.y1 = ibbox.y0;
461        hacktext->item.x2 = ibbox.x1;
462        hacktext->item.y2 = ibbox.y1;
463}
464
465static void
466gnome_canvas_hacktext_realize (GnomeCanvasItem *item)
467{
468        GnomeCanvasHacktext *hacktext;
469
470        hacktext = (GnomeCanvasHacktext *) item;
471
472        if (parent_class->realize)
473                (* parent_class->realize) (item);
474}
475
476static void
477gnome_canvas_hacktext_unrealize (GnomeCanvasItem *item)
478{
479        GnomeCanvasHacktext *hacktext;
480
481        hacktext = (GnomeCanvasHacktext *) item;
482
483        if (parent_class->unrealize)
484                (* parent_class->unrealize) (item);
485}
486
487static double
488gnome_canvas_hacktext_point (GnomeCanvasItem *item, double mx, double my,
489                            int cx, int cy, GnomeCanvasItem **actual_item)
490{
491        GnomeCanvasHacktext * hacktext;
492
493        hacktext = (GnomeCanvasHacktext *) item;
494
495        if (!hacktext->priv->pgl)
496                return 1e18;
497
498        *actual_item = item;
499
500        if (gnome_pgl_test_point (hacktext->priv->pgl, cx, cy))
501                return 0.0;
502
503        return 1e18;
504}
505
506static void
507gnome_canvas_hacktext_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
508{
509        GnomeCanvasHacktext *hacktext;
510
511        g_return_if_fail (item != NULL);
512        g_return_if_fail (GNOME_IS_CANVAS_HACKTEXT (item));
513
514        hacktext = GNOME_CANVAS_HACKTEXT (item);
515
516        if (hacktext->text == NULL) {
517                *x1 = *y1 = *x2 = *y2 = 0.0;
518                return;
519        }
520
521        get_bounds (hacktext, x1, y1, x2, y2);
522}
523
524static void
525gnome_canvas_hacktext_req_repaint (GnomeCanvasHacktext *hacktext,
526                                   ArtIRect *bbox)
527{
528        ArtDRect gbbox;
529
530        g_return_if_fail (hacktext->priv);
531
532        if (!hacktext->priv->pgl)
533                return;
534
535        if (gnome_pgl_bbox (hacktext->priv->pgl, &gbbox)) {
536                ArtIRect ibox;
537                art_drect_to_irect (&ibox, &gbbox);
538                gnome_canvas_request_redraw (hacktext->item.canvas, ibox.x0, ibox.y0, ibox.x1, ibox.y1);
539                if (bbox) art_irect_union (bbox, bbox, &ibox);
540        }
541}
542
543static void
544gnome_canvas_hacktext_render (GnomeCanvasItem *item,
545                              GnomeCanvasBuf *buf)
546{
547        GnomeCanvasHacktext * hacktext;
548
549        hacktext = (GnomeCanvasHacktext *) item;
550
551        g_return_if_fail (hacktext->priv);
552
553        if (!hacktext->priv->pgl)
554                return;
555
556        gnome_canvas_buf_ensure_buf (buf);
557        buf->is_buf = TRUE;
558        buf->is_bg = FALSE;
559
560        gnome_rfont_render_pgl_rgb8 (hacktext->priv->pgl,
561                                     -buf->rect.x0, -buf->rect.y0,
562                                     buf->buf,
563                                     buf->rect.x1 - buf->rect.x0,
564                                     buf->rect.y1 - buf->rect.y0,
565                                     buf->buf_rowstride,
566                                     GNOME_RFONT_RENDER_DEFAULT);
567}
568
569
570
571
572
573
574
575
576
577
578
579
Note: See TracBrowser for help on using the repository browser.