PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plplotcanvas-hacktext.c
Go to the documentation of this file.
1 // -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 //
3 // plplotcanvas-hacktext.c: Hacktext CanvasItem, cloned from the
4 // gnome-print project
5 //
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.
10 //
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.
15 //
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // Authors:
21 // Federico Mena <federico@nuclecu.unam.mx>
22 // Raph Levien <raph@acm.org>
23 // Lauris Kaplinski <lauris@helixcode.com>
24 //
25 // Copyright (C) 1998-1999 The Free Software Foundation
26 // Copyright (C) 2000-2002 Ximian Inc.
27 //
28 //
29 
30 //
31 // FIXME: TODO: Clipping
32 //
33 
34 #include <plplot_config.h>
35 
36 #include <math.h>
37 #include <string.h>
38 
39 #include <libgnomeprint/gnome-pgl.h>
40 #include <libgnomeprint/gnome-font.h>
41 #include <libgnomeprint/gnome-rfont.h>
42 
43 #include "plplotcanvas-hacktext.h"
44 
45 
46 //
47 // Macros from gnome-print-i18n.h in gnome-print
48 //
49 
50 #ifndef __GNOME_PRINT_I18N_H__
51 #define __GNOME_PRINT_I18N_H__
52 # define textdomain( String ) ( String )
53 # define gettext( String ) ( String )
54 # define dgettext( Domain, Message ) ( Message )
55 # define dcgettext( Domain, Message, Type ) ( Message )
56 # define bindtextdomain( Domain, Directory ) ( Domain )
57 # define _( String ) ( String )
58 # define N_( String ) ( String )
59 #endif // __GNOME_PRINT_I18N_H__
60 
61 
62 //
63 // Continue with hacktext code
64 //
65 
66 enum
67 {
76 };
77 
78 
80 static void plplot_canvas_hacktext_init( PlplotCanvasHacktext *hacktext );
81 static void plplot_canvas_hacktext_destroy( GtkObject *object );
82 static void plplot_canvas_hacktext_set_property( GObject *object,
83  guint param_id,
84  const GValue *value,
85  GParamSpec *pspec );
86 static void plplot_canvas_hacktext_get_property( GObject *object,
87  guint param_id,
88  GValue *value,
89  GParamSpec *pspec );
90 static void plplot_canvas_hacktext_update( GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags );
91 static void plplot_canvas_hacktext_realize( GnomeCanvasItem *item );
92 static void plplot_canvas_hacktext_unrealize( GnomeCanvasItem *item );
93 static double plplot_canvas_hacktext_point( GnomeCanvasItem *item, double x, double y,
94  int cx, int cy, GnomeCanvasItem **actual_item );
95 static void plplot_canvas_hacktext_bounds( GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2 );
96 static void plplot_canvas_hacktext_render( GnomeCanvasItem *item, GnomeCanvasBuf *buf );
97 static void plplot_canvas_hacktext_req_repaint( PlplotCanvasHacktext *hacktext, ArtIRect *bbox );
98 
99 
100 static GnomeCanvasItemClass *parent_class;
101 
103 {
104  GnomeFont * font;
105 
106  GnomeGlyphList * glyphlist;
107  GnomePosGlyphList * pgl;
108  double affine[6]; // the text to world transform (NB! mirrored Y)
109 };
110 
111 GType
113 {
114  static GType type = 0;
115  if ( !type )
116  {
117  GTypeInfo info = {
118  sizeof ( PlplotCanvasHacktextClass ),
119  NULL, NULL,
120  (GClassInitFunc) plplot_canvas_hacktext_class_init,
121  NULL, NULL,
122  sizeof ( PlplotCanvasHacktext ),
123  0,
124  (GInstanceInitFunc) plplot_canvas_hacktext_init,
125  NULL
126  };
127  type = g_type_register_static( GNOME_TYPE_CANVAS_ITEM, "PlplotCanvasHacktext", &info, 0 );
128  }
129  return type;
130 }
131 
132 static void
134 {
135  GObjectClass *gobject_class;
136  GtkObjectClass *object_class;
137  GnomeCanvasItemClass *item_class;
138 
139  object_class = (GtkObjectClass *) class;
140  gobject_class = (GObjectClass *) class;
141  item_class = (GnomeCanvasItemClass *) class;
142 
143  parent_class = g_type_class_peek_parent( class );
144 
145  gobject_class->set_property = plplot_canvas_hacktext_set_property;
146  gobject_class->get_property = plplot_canvas_hacktext_get_property;
147 
148  g_object_class_install_property
149  ( gobject_class,
150  PROP_TEXT,
151  g_param_spec_string( "text",
152  _( "Text" ),
153  _( "Text to render" ),
154  NULL,
155  G_PARAM_READABLE | G_PARAM_WRITABLE ) );
156  g_object_class_install_property
157  ( gobject_class,
158  PROP_X,
159  g_param_spec_double( "x", NULL, NULL,
160  -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
161  ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) );
162  g_object_class_install_property
163  ( gobject_class,
164  PROP_Y,
165  g_param_spec_double( "y", NULL, NULL,
166  -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
167  ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) );
168  g_object_class_install_property
169  ( gobject_class,
171  g_param_spec_pointer( "glyphlist",
172  _( "Glyphlist" ),
173  _( "Glyphlist" ),
174  ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) );
175  g_object_class_install_property
176  ( gobject_class,
178  g_param_spec_string( "fill_color",
179  _( "Color" ),
180  _( "Text color, as string" ),
181  NULL,
182  G_PARAM_WRITABLE ) );
183  g_object_class_install_property
184  ( gobject_class,
186  g_param_spec_uint( "fill_color_rgba",
187  _( "Color" ),
188  _( "Text color, as an R/G/B/A combined integer" ),
189  0, G_MAXUINT, 0,
190  ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) );
191  g_object_class_install_property
192  ( gobject_class,
193  PROP_FONT,
194  g_param_spec_object( "font",
195  _( "Font" ),
196  _( "Font as a GnomeFont struct" ),
197  GNOME_TYPE_FONT,
198  ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) );
199 
200  object_class->destroy = plplot_canvas_hacktext_destroy;
201 
202  item_class->update = plplot_canvas_hacktext_update;
203  item_class->realize = plplot_canvas_hacktext_realize;
204  item_class->unrealize = plplot_canvas_hacktext_unrealize;
205  item_class->point = plplot_canvas_hacktext_point;
206  item_class->bounds = plplot_canvas_hacktext_bounds;
207  item_class->render = plplot_canvas_hacktext_render;
208 }
209 
210 static void
212 {
213  hacktext->text = NULL;
214  hacktext->priv = g_new( PlplotCanvasHacktextPriv, 1 );
215  hacktext->priv->pgl = NULL;
216  hacktext->priv->font = NULL;
217  hacktext->priv->glyphlist = NULL;
218 
219  art_affine_identity( hacktext->priv->affine );
220 }
221 
222 static void
223 plplot_canvas_hacktext_destroy( GtkObject *object )
224 {
225  PlplotCanvasHacktext *hacktext;
226 
227  g_return_if_fail( object != NULL );
228  g_return_if_fail( PLPLOT_IS_CANVAS_HACKTEXT( object ) );
229 
230  hacktext = PLPLOT_CANVAS_HACKTEXT( object );
231 
232  if ( hacktext->text )
233  {
234  g_free( hacktext->text );
235  hacktext->text = NULL;
236  }
237 
238  if ( hacktext->priv )
239  {
240  if ( hacktext->priv->font )
241  gnome_font_unref( hacktext->priv->font );
242  if ( hacktext->priv->glyphlist )
243  gnome_glyphlist_unref( hacktext->priv->glyphlist );
244  if ( hacktext->priv->pgl )
245  gnome_pgl_destroy( hacktext->priv->pgl );
246  g_free( hacktext->priv );
247  hacktext->priv = NULL;
248  }
249 
250  if ( GTK_OBJECT_CLASS( parent_class )->destroy )
251  ( *GTK_OBJECT_CLASS( parent_class )->destroy )( object );
252 }
253 
254 static void
255 art_drect_hacktext( ArtDRect *bbox, PlplotCanvasHacktext *hacktext )
256 {
257  g_assert( bbox != NULL );
258  g_assert( hacktext != NULL );
259 
260  g_return_if_fail( hacktext->priv );
261 
262  if ( GTK_OBJECT_FLAGS( hacktext ) & GNOME_CANVAS_UPDATE_REQUESTED )
263  {
264  gnome_canvas_update_now( GNOME_CANVAS_ITEM( hacktext )->canvas );
265  }
266 
267  if ( !hacktext->priv->pgl )
268  return;
269 
270  gnome_pgl_bbox( hacktext->priv->pgl, bbox );
271 }
272 
273 // Computes the bounding box of the hacktext. Assumes that the number of points in the hacktext is
274 // not zero.
275 //
276 static void
277 get_bounds( PlplotCanvasHacktext *hacktext, double *bx1, double *by1, double *bx2, double *by2 )
278 {
279  ArtDRect bbox;
280 
281  // Compute bounds of hacktext
282  art_drect_hacktext( &bbox, hacktext );
283 
284  // Done
285 
286  *bx1 = bbox.x0;
287  *by1 = bbox.y0;
288  *bx2 = bbox.x1;
289  *by2 = bbox.y1;
290 }
291 
292 static void
294  guint param_id,
295  const GValue *value,
296  GParamSpec *pspec )
297 {
298  GnomeCanvasItem *item;
300  GnomeGlyphList * gl;
301  GdkColor color;
302  GnomeFont * font;
303 
304  item = GNOME_CANVAS_ITEM( object );
305  bp = PLPLOT_CANVAS_HACKTEXT( object );
306 
307  switch ( param_id )
308  {
309  case PROP_TEXT:
310  if ( bp->text )
311  {
312  g_free( bp->text );
313  bp->text = NULL;
314  }
315 
316  if ( bp->priv->glyphlist )
317  {
318  gnome_glyphlist_unref( bp->priv->glyphlist );
319  bp->priv->glyphlist = NULL;
320  }
321 
322  bp->text = g_value_dup_string( value );
323 
324  gnome_canvas_item_request_update( item );
325  break;
326 
327  case PROP_GLYPHLIST:
328  gl = g_value_get_pointer( value );
329 
330  if ( bp->text )
331  {
332  g_free( bp->text );
333  bp->text = NULL;
334  }
335 
336  if ( bp->priv->glyphlist )
337  {
338  gnome_glyphlist_unref( bp->priv->glyphlist );
339  bp->priv->glyphlist = NULL;
340  }
341 
342  // FIXME: should be duplicate() (Lauris)
343  if ( gl )
344  gnome_glyphlist_ref( gl );
345 
346  bp->priv->glyphlist = gl;
347 
348  gnome_canvas_item_request_update( item );
349 
350  break;
351 
352  case PROP_FILL_COLOR:
353  if ( gnome_canvas_get_color( item->canvas, g_value_get_string( value ), &color ) )
354  {
355  bp->fill_set = TRUE;
356  bp->fill_pixel = color.pixel;
357  bp->fill_rgba =
358  ( ( color.red & 0xff00 ) << 16 ) |
359  ( ( color.green & 0xff00 ) << 8 ) |
360  ( color.blue & 0xff00 ) |
361  0xff;
362  }
363  else
364  {
365  bp->fill_set = FALSE;
366  bp->fill_rgba = 0;
367  }
368 
369  gnome_canvas_item_request_update( item );
370  break;
371 
373  bp->fill_set = TRUE;
374  bp->fill_rgba = g_value_get_uint( value );
375 
376  // should probably request repaint on the fill_svp
377  gnome_canvas_item_request_update( item );
378 
379  break;
380 
381  case PROP_FONT:
382  font = g_value_get_object( value );
383  if ( font )
384  gnome_font_ref( font );
385  if ( bp->priv->font )
386  gnome_font_unref( bp->priv->font );
387  bp->priv->font = font;
388  bp->size = gnome_font_get_size( bp->priv->font );
389  gnome_canvas_item_request_update( item );
390  break;
391 
392  case PROP_X:
393  bp->x = g_value_get_double( value );
394  gnome_canvas_item_request_update( item );
395  break;
396 
397  case PROP_Y:
398  bp->y = g_value_get_double( value );
399  gnome_canvas_item_request_update( item );
400  break;
401 
402  default:
403  break;
404  }
405 }
406 
407 static void
409  guint param_id,
410  GValue *value,
411  GParamSpec *pspec )
412 {
415 
416  bp = PLPLOT_CANVAS_HACKTEXT( object );
417  priv = (PlplotCanvasHacktextPriv *) bp->priv;
418 
419  switch ( param_id )
420  {
421  case PROP_TEXT:
422  g_value_set_string( value, bp->text );
423  break;
424  case PROP_GLYPHLIST:
425  g_value_set_pointer( value, priv->glyphlist );
426  break;
428  g_value_set_uint( value, bp->fill_color );
429  break;
430  case PROP_FONT:
431  g_value_set_object( value, bp->priv->font );
432  break;
433  case PROP_X:
434  g_value_set_double( value, bp->x );
435  break;
436  case PROP_Y:
437  g_value_set_double( value, bp->y );
438  break;
439  default:
440  G_OBJECT_WARN_INVALID_PROPERTY_ID( object, param_id, pspec );
441  break;
442  }
443 }
444 
445 static void
446 plplot_canvas_hacktext_update( GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags )
447 {
448  PlplotCanvasHacktext *hacktext;
449  ArtIRect ibbox = { 0, 0, 0, 0 };
450 
451  hacktext = (PlplotCanvasHacktext *) item;
452 
453  if ( parent_class->update )
454  ( *parent_class->update )( item, affine, clip_path, flags );
455 
456  if ( hacktext->priv->pgl )
457  plplot_canvas_hacktext_req_repaint( hacktext, NULL );
458 
459  gnome_canvas_item_reset_bounds( item );
460 
461  hacktext->priv->affine[0] = affine[0];
462  hacktext->priv->affine[1] = affine[1];
463  hacktext->priv->affine[2] = -affine[2];
464  hacktext->priv->affine[3] = -affine[3];
465  hacktext->priv->affine[4] = affine[4] + hacktext->x * affine[0] + hacktext->y * affine[2];
466  hacktext->priv->affine[5] = affine[5] + hacktext->x * affine[1] + hacktext->y * affine[3];
467 
468  if ( hacktext->text )
469  {
470  if ( hacktext->priv->glyphlist )
471  {
472  gnome_glyphlist_unref( hacktext->priv->glyphlist );
473  hacktext->priv->glyphlist = NULL;
474  }
475 
476  if ( !hacktext->priv->font )
477  return;
478 
479  hacktext->priv->glyphlist = gnome_glyphlist_from_text_dumb( hacktext->priv->font, hacktext->fill_rgba,
480  0.0, 0.0,
481  hacktext->text );
482  }
483 
484  if ( hacktext->priv->glyphlist )
485  {
486  GnomePosGlyphList * pgl;
487 
488  pgl = gnome_pgl_from_gl( hacktext->priv->glyphlist, hacktext->priv->affine, GNOME_PGL_RENDER_DEFAULT );
489 
490  if ( hacktext->priv->pgl )
491  gnome_pgl_destroy( hacktext->priv->pgl );
492 
493  hacktext->priv->pgl = pgl;
494  }
495 
496  plplot_canvas_hacktext_req_repaint( hacktext, &ibbox );
497 
498  hacktext->item.x1 = ibbox.x0;
499  hacktext->item.y1 = ibbox.y0;
500  hacktext->item.x2 = ibbox.x1;
501  hacktext->item.y2 = ibbox.y1;
502 }
503 
504 static void
505 plplot_canvas_hacktext_realize( GnomeCanvasItem *item )
506 {
507  PlplotCanvasHacktext *hacktext;
508 
509  hacktext = (PlplotCanvasHacktext *) item;
510 
511  if ( parent_class->realize )
512  ( *parent_class->realize )( item );
513 }
514 
515 static void
516 plplot_canvas_hacktext_unrealize( GnomeCanvasItem *item )
517 {
518  PlplotCanvasHacktext *hacktext;
519 
520  hacktext = (PlplotCanvasHacktext *) item;
521 
522  if ( parent_class->unrealize )
523  ( *parent_class->unrealize )( item );
524 }
525 
526 static double
527 plplot_canvas_hacktext_point( GnomeCanvasItem *item, double mx, double my,
528  int cx, int cy, GnomeCanvasItem **actual_item )
529 {
530  PlplotCanvasHacktext * hacktext;
531 
532  hacktext = (PlplotCanvasHacktext *) item;
533 
534  if ( !hacktext->priv->pgl )
535  return 1e18;
536 
537  *actual_item = item;
538 
539  if ( gnome_pgl_test_point( hacktext->priv->pgl, cx, cy ) )
540  return 0.0;
541 
542  return 1e18;
543 }
544 
545 static void
546 plplot_canvas_hacktext_bounds( GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2 )
547 {
548  PlplotCanvasHacktext *hacktext;
549 
550  g_return_if_fail( item != NULL );
551  g_return_if_fail( PLPLOT_IS_CANVAS_HACKTEXT( item ) );
552 
553  hacktext = PLPLOT_CANVAS_HACKTEXT( item );
554 
555  if ( hacktext->text == NULL )
556  {
557  *x1 = *y1 = *x2 = *y2 = 0.0;
558  return;
559  }
560 
561  get_bounds( hacktext, x1, y1, x2, y2 );
562 }
563 
564 static void
566  ArtIRect *bbox )
567 {
568  ArtDRect gbbox;
569 
570  g_return_if_fail( hacktext->priv );
571 
572  if ( !hacktext->priv->pgl )
573  return;
574 
575  if ( gnome_pgl_bbox( hacktext->priv->pgl, &gbbox ) )
576  {
577  ArtIRect ibox;
578  art_drect_to_irect( &ibox, &gbbox );
579  gnome_canvas_request_redraw( hacktext->item.canvas, ibox.x0, ibox.y0, ibox.x1, ibox.y1 );
580  if ( bbox )
581  art_irect_union( bbox, bbox, &ibox );
582  }
583 }
584 
585 static void
586 plplot_canvas_hacktext_render( GnomeCanvasItem *item,
587  GnomeCanvasBuf *buf )
588 {
589  PlplotCanvasHacktext * hacktext;
590 
591  hacktext = (PlplotCanvasHacktext *) item;
592 
593  g_return_if_fail( hacktext->priv );
594 
595  if ( !hacktext->priv->pgl )
596  return;
597 
598  gnome_canvas_buf_ensure_buf( buf );
599  buf->is_buf = TRUE;
600  buf->is_bg = FALSE;
601 
602  gnome_rfont_render_pgl_rgb8( hacktext->priv->pgl,
603  -buf->rect.x0, -buf->rect.y0,
604  buf->buf,
605  buf->rect.x1 - buf->rect.x0,
606  buf->rect.y1 - buf->rect.y0,
607  buf->buf_rowstride,
608  GNOME_RFONT_RENDER_DEFAULT );
609 }
610 
611 
612 
613 
614 
615 
616 
617 
618 
619 
620 
621