PLplot
5.10.0
|
00001 // -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 00002 // 00003 // plplotcanvas-hacktext.c: Hacktext CanvasItem, cloned from the 00004 // gnome-print project 00005 // 00006 // This program is free software; you can redistribute it and/or 00007 // modify it under the terms of the GNU Library General Public License 00008 // as published by the Free Software Foundation; either version 2 of 00009 // the License, or (at your option) any later version. 00010 // 00011 // This program is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU Library General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Library General Public 00017 // License along with this program; if not, write to the Free Software 00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 // 00020 // Authors: 00021 // Federico Mena <federico@nuclecu.unam.mx> 00022 // Raph Levien <raph@acm.org> 00023 // Lauris Kaplinski <lauris@helixcode.com> 00024 // 00025 // Copyright (C) 1998-1999 The Free Software Foundation 00026 // Copyright (C) 2000-2002 Ximian Inc. 00027 // 00028 // 00029 00030 // 00031 // FIXME: TODO: Clipping 00032 // 00033 00034 #include <plplot_config.h> 00035 00036 #include <math.h> 00037 #include <string.h> 00038 00039 #include <libgnomeprint/gnome-pgl.h> 00040 #include <libgnomeprint/gnome-font.h> 00041 #include <libgnomeprint/gnome-rfont.h> 00042 00043 #include "plplotcanvas-hacktext.h" 00044 00045 00046 // 00047 // Macros from gnome-print-i18n.h in gnome-print 00048 // 00049 00050 #ifndef __GNOME_PRINT_I18N_H__ 00051 #define __GNOME_PRINT_I18N_H__ 00052 # define textdomain( String ) ( String ) 00053 # define gettext( String ) ( String ) 00054 # define dgettext( Domain, Message ) ( Message ) 00055 # define dcgettext( Domain, Message, Type ) ( Message ) 00056 # define bindtextdomain( Domain, Directory ) ( Domain ) 00057 # define _( String ) ( String ) 00058 # define N_( String ) ( String ) 00059 #endif // __GNOME_PRINT_I18N_H__ 00060 00061 00062 // 00063 // Continue with hacktext code 00064 // 00065 00066 enum 00067 { 00068 PROP_0, 00069 PROP_TEXT, 00070 PROP_GLYPHLIST, 00071 PROP_FILL_COLOR, 00072 PROP_FILL_COLOR_RGBA, 00073 PROP_FONT, 00074 PROP_X, 00075 PROP_Y 00076 }; 00077 00078 00079 static void plplot_canvas_hacktext_class_init( PlplotCanvasHacktextClass *class ); 00080 static void plplot_canvas_hacktext_init( PlplotCanvasHacktext *hacktext ); 00081 static void plplot_canvas_hacktext_destroy( GtkObject *object ); 00082 static void plplot_canvas_hacktext_set_property( GObject *object, 00083 guint param_id, 00084 const GValue *value, 00085 GParamSpec *pspec ); 00086 static void plplot_canvas_hacktext_get_property( GObject *object, 00087 guint param_id, 00088 GValue *value, 00089 GParamSpec *pspec ); 00090 static void plplot_canvas_hacktext_update( GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags ); 00091 static void plplot_canvas_hacktext_realize( GnomeCanvasItem *item ); 00092 static void plplot_canvas_hacktext_unrealize( GnomeCanvasItem *item ); 00093 static double plplot_canvas_hacktext_point( GnomeCanvasItem *item, double x, double y, 00094 int cx, int cy, GnomeCanvasItem **actual_item ); 00095 static void plplot_canvas_hacktext_bounds( GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2 ); 00096 static void plplot_canvas_hacktext_render( GnomeCanvasItem *item, GnomeCanvasBuf *buf ); 00097 static void plplot_canvas_hacktext_req_repaint( PlplotCanvasHacktext *hacktext, ArtIRect *bbox ); 00098 00099 00100 static GnomeCanvasItemClass *parent_class; 00101 00102 struct _PlplotCanvasHacktextPriv 00103 { 00104 GnomeFont * font; 00105 00106 GnomeGlyphList * glyphlist; 00107 GnomePosGlyphList * pgl; 00108 double affine[6]; // the text to world transform (NB! mirrored Y) 00109 }; 00110 00111 GType 00112 plplot_canvas_hacktext_get_type( void ) 00113 { 00114 static GType type = 0; 00115 if ( !type ) 00116 { 00117 GTypeInfo info = { 00118 sizeof ( PlplotCanvasHacktextClass ), 00119 NULL, NULL, 00120 (GClassInitFunc) plplot_canvas_hacktext_class_init, 00121 NULL, NULL, 00122 sizeof ( PlplotCanvasHacktext ), 00123 0, 00124 (GInstanceInitFunc) plplot_canvas_hacktext_init, 00125 NULL 00126 }; 00127 type = g_type_register_static( GNOME_TYPE_CANVAS_ITEM, "PlplotCanvasHacktext", &info, 0 ); 00128 } 00129 return type; 00130 } 00131 00132 static void 00133 plplot_canvas_hacktext_class_init( PlplotCanvasHacktextClass *class ) 00134 { 00135 GObjectClass *gobject_class; 00136 GtkObjectClass *object_class; 00137 GnomeCanvasItemClass *item_class; 00138 00139 object_class = (GtkObjectClass *) class; 00140 gobject_class = (GObjectClass *) class; 00141 item_class = (GnomeCanvasItemClass *) class; 00142 00143 parent_class = g_type_class_peek_parent( class ); 00144 00145 gobject_class->set_property = plplot_canvas_hacktext_set_property; 00146 gobject_class->get_property = plplot_canvas_hacktext_get_property; 00147 00148 g_object_class_install_property 00149 ( gobject_class, 00150 PROP_TEXT, 00151 g_param_spec_string( "text", 00152 _( "Text" ), 00153 _( "Text to render" ), 00154 NULL, 00155 G_PARAM_READABLE | G_PARAM_WRITABLE ) ); 00156 g_object_class_install_property 00157 ( gobject_class, 00158 PROP_X, 00159 g_param_spec_double( "x", NULL, NULL, 00160 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, 00161 ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) ); 00162 g_object_class_install_property 00163 ( gobject_class, 00164 PROP_Y, 00165 g_param_spec_double( "y", NULL, NULL, 00166 -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, 00167 ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) ); 00168 g_object_class_install_property 00169 ( gobject_class, 00170 PROP_GLYPHLIST, 00171 g_param_spec_pointer( "glyphlist", 00172 _( "Glyphlist" ), 00173 _( "Glyphlist" ), 00174 ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) ); 00175 g_object_class_install_property 00176 ( gobject_class, 00177 PROP_FILL_COLOR, 00178 g_param_spec_string( "fill_color", 00179 _( "Color" ), 00180 _( "Text color, as string" ), 00181 NULL, 00182 G_PARAM_WRITABLE ) ); 00183 g_object_class_install_property 00184 ( gobject_class, 00185 PROP_FILL_COLOR_RGBA, 00186 g_param_spec_uint( "fill_color_rgba", 00187 _( "Color" ), 00188 _( "Text color, as an R/G/B/A combined integer" ), 00189 0, G_MAXUINT, 0, 00190 ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) ); 00191 g_object_class_install_property 00192 ( gobject_class, 00193 PROP_FONT, 00194 g_param_spec_object( "font", 00195 _( "Font" ), 00196 _( "Font as a GnomeFont struct" ), 00197 GNOME_TYPE_FONT, 00198 ( G_PARAM_READABLE | G_PARAM_WRITABLE ) ) ); 00199 00200 object_class->destroy = plplot_canvas_hacktext_destroy; 00201 00202 item_class->update = plplot_canvas_hacktext_update; 00203 item_class->realize = plplot_canvas_hacktext_realize; 00204 item_class->unrealize = plplot_canvas_hacktext_unrealize; 00205 item_class->point = plplot_canvas_hacktext_point; 00206 item_class->bounds = plplot_canvas_hacktext_bounds; 00207 item_class->render = plplot_canvas_hacktext_render; 00208 } 00209 00210 static void 00211 plplot_canvas_hacktext_init( PlplotCanvasHacktext *hacktext ) 00212 { 00213 hacktext->text = NULL; 00214 hacktext->priv = g_new( PlplotCanvasHacktextPriv, 1 ); 00215 hacktext->priv->pgl = NULL; 00216 hacktext->priv->font = NULL; 00217 hacktext->priv->glyphlist = NULL; 00218 00219 art_affine_identity( hacktext->priv->affine ); 00220 } 00221 00222 static void 00223 plplot_canvas_hacktext_destroy( GtkObject *object ) 00224 { 00225 PlplotCanvasHacktext *hacktext; 00226 00227 g_return_if_fail( object != NULL ); 00228 g_return_if_fail( PLPLOT_IS_CANVAS_HACKTEXT( object ) ); 00229 00230 hacktext = PLPLOT_CANVAS_HACKTEXT( object ); 00231 00232 if ( hacktext->text ) 00233 { 00234 g_free( hacktext->text ); 00235 hacktext->text = NULL; 00236 } 00237 00238 if ( hacktext->priv ) 00239 { 00240 if ( hacktext->priv->font ) 00241 gnome_font_unref( hacktext->priv->font ); 00242 if ( hacktext->priv->glyphlist ) 00243 gnome_glyphlist_unref( hacktext->priv->glyphlist ); 00244 if ( hacktext->priv->pgl ) 00245 gnome_pgl_destroy( hacktext->priv->pgl ); 00246 g_free( hacktext->priv ); 00247 hacktext->priv = NULL; 00248 } 00249 00250 if ( GTK_OBJECT_CLASS( parent_class )->destroy ) 00251 ( *GTK_OBJECT_CLASS( parent_class )->destroy )( object ); 00252 } 00253 00254 static void 00255 art_drect_hacktext( ArtDRect *bbox, PlplotCanvasHacktext *hacktext ) 00256 { 00257 g_assert( bbox != NULL ); 00258 g_assert( hacktext != NULL ); 00259 00260 g_return_if_fail( hacktext->priv ); 00261 00262 if ( GTK_OBJECT_FLAGS( hacktext ) & GNOME_CANVAS_UPDATE_REQUESTED ) 00263 { 00264 gnome_canvas_update_now( GNOME_CANVAS_ITEM( hacktext )->canvas ); 00265 } 00266 00267 if ( !hacktext->priv->pgl ) 00268 return; 00269 00270 gnome_pgl_bbox( hacktext->priv->pgl, bbox ); 00271 } 00272 00273 // Computes the bounding box of the hacktext. Assumes that the number of points in the hacktext is 00274 // not zero. 00275 // 00276 static void 00277 get_bounds( PlplotCanvasHacktext *hacktext, double *bx1, double *by1, double *bx2, double *by2 ) 00278 { 00279 ArtDRect bbox; 00280 00281 // Compute bounds of hacktext 00282 art_drect_hacktext( &bbox, hacktext ); 00283 00284 // Done 00285 00286 *bx1 = bbox.x0; 00287 *by1 = bbox.y0; 00288 *bx2 = bbox.x1; 00289 *by2 = bbox.y1; 00290 } 00291 00292 static void 00293 plplot_canvas_hacktext_set_property( GObject *object, 00294 guint param_id, 00295 const GValue *value, 00296 GParamSpec *pspec ) 00297 { 00298 GnomeCanvasItem *item; 00299 PlplotCanvasHacktext *bp; 00300 GnomeGlyphList * gl; 00301 GdkColor color; 00302 GnomeFont * font; 00303 00304 item = GNOME_CANVAS_ITEM( object ); 00305 bp = PLPLOT_CANVAS_HACKTEXT( object ); 00306 00307 switch ( param_id ) 00308 { 00309 case PROP_TEXT: 00310 if ( bp->text ) 00311 { 00312 g_free( bp->text ); 00313 bp->text = NULL; 00314 } 00315 00316 if ( bp->priv->glyphlist ) 00317 { 00318 gnome_glyphlist_unref( bp->priv->glyphlist ); 00319 bp->priv->glyphlist = NULL; 00320 } 00321 00322 bp->text = g_value_dup_string( value ); 00323 00324 gnome_canvas_item_request_update( item ); 00325 break; 00326 00327 case PROP_GLYPHLIST: 00328 gl = g_value_get_pointer( value ); 00329 00330 if ( bp->text ) 00331 { 00332 g_free( bp->text ); 00333 bp->text = NULL; 00334 } 00335 00336 if ( bp->priv->glyphlist ) 00337 { 00338 gnome_glyphlist_unref( bp->priv->glyphlist ); 00339 bp->priv->glyphlist = NULL; 00340 } 00341 00342 // FIXME: should be duplicate() (Lauris) 00343 if ( gl ) 00344 gnome_glyphlist_ref( gl ); 00345 00346 bp->priv->glyphlist = gl; 00347 00348 gnome_canvas_item_request_update( item ); 00349 00350 break; 00351 00352 case PROP_FILL_COLOR: 00353 if ( gnome_canvas_get_color( item->canvas, g_value_get_string( value ), &color ) ) 00354 { 00355 bp->fill_set = TRUE; 00356 bp->fill_pixel = color.pixel; 00357 bp->fill_rgba = 00358 ( ( color.red & 0xff00 ) << 16 ) | 00359 ( ( color.green & 0xff00 ) << 8 ) | 00360 ( color.blue & 0xff00 ) | 00361 0xff; 00362 } 00363 else 00364 { 00365 bp->fill_set = FALSE; 00366 bp->fill_rgba = 0; 00367 } 00368 00369 gnome_canvas_item_request_update( item ); 00370 break; 00371 00372 case PROP_FILL_COLOR_RGBA: 00373 bp->fill_set = TRUE; 00374 bp->fill_rgba = g_value_get_uint( value ); 00375 00376 // should probably request repaint on the fill_svp 00377 gnome_canvas_item_request_update( item ); 00378 00379 break; 00380 00381 case PROP_FONT: 00382 font = g_value_get_object( value ); 00383 if ( font ) 00384 gnome_font_ref( font ); 00385 if ( bp->priv->font ) 00386 gnome_font_unref( bp->priv->font ); 00387 bp->priv->font = font; 00388 bp->size = gnome_font_get_size( bp->priv->font ); 00389 gnome_canvas_item_request_update( item ); 00390 break; 00391 00392 case PROP_X: 00393 bp->x = g_value_get_double( value ); 00394 gnome_canvas_item_request_update( item ); 00395 break; 00396 00397 case PROP_Y: 00398 bp->y = g_value_get_double( value ); 00399 gnome_canvas_item_request_update( item ); 00400 break; 00401 00402 default: 00403 break; 00404 } 00405 } 00406 00407 static void 00408 plplot_canvas_hacktext_get_property( GObject *object, 00409 guint param_id, 00410 GValue *value, 00411 GParamSpec *pspec ) 00412 { 00413 PlplotCanvasHacktextPriv *priv; 00414 PlplotCanvasHacktext *bp; 00415 00416 bp = PLPLOT_CANVAS_HACKTEXT( object ); 00417 priv = (PlplotCanvasHacktextPriv *) bp->priv; 00418 00419 switch ( param_id ) 00420 { 00421 case PROP_TEXT: 00422 g_value_set_string( value, bp->text ); 00423 break; 00424 case PROP_GLYPHLIST: 00425 g_value_set_pointer( value, priv->glyphlist ); 00426 break; 00427 case PROP_FILL_COLOR_RGBA: 00428 g_value_set_uint( value, bp->fill_color ); 00429 break; 00430 case PROP_FONT: 00431 g_value_set_object( value, bp->priv->font ); 00432 break; 00433 case PROP_X: 00434 g_value_set_double( value, bp->x ); 00435 break; 00436 case PROP_Y: 00437 g_value_set_double( value, bp->y ); 00438 break; 00439 default: 00440 G_OBJECT_WARN_INVALID_PROPERTY_ID( object, param_id, pspec ); 00441 break; 00442 } 00443 } 00444 00445 static void 00446 plplot_canvas_hacktext_update( GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags ) 00447 { 00448 PlplotCanvasHacktext *hacktext; 00449 ArtIRect ibbox = { 0, 0, 0, 0 }; 00450 00451 hacktext = (PlplotCanvasHacktext *) item; 00452 00453 if ( parent_class->update ) 00454 ( *parent_class->update )( item, affine, clip_path, flags ); 00455 00456 if ( hacktext->priv->pgl ) 00457 plplot_canvas_hacktext_req_repaint( hacktext, NULL ); 00458 00459 gnome_canvas_item_reset_bounds( item ); 00460 00461 hacktext->priv->affine[0] = affine[0]; 00462 hacktext->priv->affine[1] = affine[1]; 00463 hacktext->priv->affine[2] = -affine[2]; 00464 hacktext->priv->affine[3] = -affine[3]; 00465 hacktext->priv->affine[4] = affine[4] + hacktext->x * affine[0] + hacktext->y * affine[2]; 00466 hacktext->priv->affine[5] = affine[5] + hacktext->x * affine[1] + hacktext->y * affine[3]; 00467 00468 if ( hacktext->text ) 00469 { 00470 if ( hacktext->priv->glyphlist ) 00471 { 00472 gnome_glyphlist_unref( hacktext->priv->glyphlist ); 00473 hacktext->priv->glyphlist = NULL; 00474 } 00475 00476 if ( !hacktext->priv->font ) 00477 return; 00478 00479 hacktext->priv->glyphlist = gnome_glyphlist_from_text_dumb( hacktext->priv->font, hacktext->fill_rgba, 00480 0.0, 0.0, 00481 hacktext->text ); 00482 } 00483 00484 if ( hacktext->priv->glyphlist ) 00485 { 00486 GnomePosGlyphList * pgl; 00487 00488 pgl = gnome_pgl_from_gl( hacktext->priv->glyphlist, hacktext->priv->affine, GNOME_PGL_RENDER_DEFAULT ); 00489 00490 if ( hacktext->priv->pgl ) 00491 gnome_pgl_destroy( hacktext->priv->pgl ); 00492 00493 hacktext->priv->pgl = pgl; 00494 } 00495 00496 plplot_canvas_hacktext_req_repaint( hacktext, &ibbox ); 00497 00498 hacktext->item.x1 = ibbox.x0; 00499 hacktext->item.y1 = ibbox.y0; 00500 hacktext->item.x2 = ibbox.x1; 00501 hacktext->item.y2 = ibbox.y1; 00502 } 00503 00504 static void 00505 plplot_canvas_hacktext_realize( GnomeCanvasItem *item ) 00506 { 00507 PlplotCanvasHacktext *hacktext; 00508 00509 hacktext = (PlplotCanvasHacktext *) item; 00510 00511 if ( parent_class->realize ) 00512 ( *parent_class->realize )( item ); 00513 } 00514 00515 static void 00516 plplot_canvas_hacktext_unrealize( GnomeCanvasItem *item ) 00517 { 00518 PlplotCanvasHacktext *hacktext; 00519 00520 hacktext = (PlplotCanvasHacktext *) item; 00521 00522 if ( parent_class->unrealize ) 00523 ( *parent_class->unrealize )( item ); 00524 } 00525 00526 static double 00527 plplot_canvas_hacktext_point( GnomeCanvasItem *item, double mx, double my, 00528 int cx, int cy, GnomeCanvasItem **actual_item ) 00529 { 00530 PlplotCanvasHacktext * hacktext; 00531 00532 hacktext = (PlplotCanvasHacktext *) item; 00533 00534 if ( !hacktext->priv->pgl ) 00535 return 1e18; 00536 00537 *actual_item = item; 00538 00539 if ( gnome_pgl_test_point( hacktext->priv->pgl, cx, cy ) ) 00540 return 0.0; 00541 00542 return 1e18; 00543 } 00544 00545 static void 00546 plplot_canvas_hacktext_bounds( GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2 ) 00547 { 00548 PlplotCanvasHacktext *hacktext; 00549 00550 g_return_if_fail( item != NULL ); 00551 g_return_if_fail( PLPLOT_IS_CANVAS_HACKTEXT( item ) ); 00552 00553 hacktext = PLPLOT_CANVAS_HACKTEXT( item ); 00554 00555 if ( hacktext->text == NULL ) 00556 { 00557 *x1 = *y1 = *x2 = *y2 = 0.0; 00558 return; 00559 } 00560 00561 get_bounds( hacktext, x1, y1, x2, y2 ); 00562 } 00563 00564 static void 00565 plplot_canvas_hacktext_req_repaint( PlplotCanvasHacktext *hacktext, 00566 ArtIRect *bbox ) 00567 { 00568 ArtDRect gbbox; 00569 00570 g_return_if_fail( hacktext->priv ); 00571 00572 if ( !hacktext->priv->pgl ) 00573 return; 00574 00575 if ( gnome_pgl_bbox( hacktext->priv->pgl, &gbbox ) ) 00576 { 00577 ArtIRect ibox; 00578 art_drect_to_irect( &ibox, &gbbox ); 00579 gnome_canvas_request_redraw( hacktext->item.canvas, ibox.x0, ibox.y0, ibox.x1, ibox.y1 ); 00580 if ( bbox ) 00581 art_irect_union( bbox, bbox, &ibox ); 00582 } 00583 } 00584 00585 static void 00586 plplot_canvas_hacktext_render( GnomeCanvasItem *item, 00587 GnomeCanvasBuf *buf ) 00588 { 00589 PlplotCanvasHacktext * hacktext; 00590 00591 hacktext = (PlplotCanvasHacktext *) item; 00592 00593 g_return_if_fail( hacktext->priv ); 00594 00595 if ( !hacktext->priv->pgl ) 00596 return; 00597 00598 gnome_canvas_buf_ensure_buf( buf ); 00599 buf->is_buf = TRUE; 00600 buf->is_bg = FALSE; 00601 00602 gnome_rfont_render_pgl_rgb8( hacktext->priv->pgl, 00603 -buf->rect.x0, -buf->rect.y0, 00604 buf->buf, 00605 buf->rect.x1 - buf->rect.x0, 00606 buf->rect.y1 - buf->rect.y0, 00607 buf->buf_rowstride, 00608 GNOME_RFONT_RENDER_DEFAULT ); 00609 } 00610 00611 00612 00613 00614 00615 00616 00617 00618 00619 00620 00621