1741 lines
44 KiB
C
1741 lines
44 KiB
C
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|||
|
/*
|
|||
|
* $Id$
|
|||
|
* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
|
|||
|
* All rights reserved.
|
|||
|
*
|
|||
|
* This file is part of the Gnome Library.
|
|||
|
*
|
|||
|
* The Gnome Library is free software; you can redistribute it and/or
|
|||
|
* modify it under the terms of the GNU Library General Public License as
|
|||
|
* published by the Free Software Foundation; either version 2 of the
|
|||
|
* License, or (at your option) any later version.
|
|||
|
*
|
|||
|
* The Gnome Library is distributed in the hope that it will be useful,
|
|||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|||
|
* Library General Public License for more details.
|
|||
|
*
|
|||
|
* You should have received a copy of the GNU Library General Public
|
|||
|
* License along with the Gnome Library; see the file COPYING.LIB. If not,
|
|||
|
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|||
|
* Boston, MA 02111-1307, USA.
|
|||
|
*/
|
|||
|
/*
|
|||
|
@NOTATION@
|
|||
|
*/
|
|||
|
/* Text item type for GnomeCanvas widget
|
|||
|
*
|
|||
|
* GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas
|
|||
|
* widget. Tk is copyrighted by the Regents of the University of California,
|
|||
|
* Sun Microsystems, and other parties.
|
|||
|
*
|
|||
|
*
|
|||
|
* Author: Federico Mena <federico@nuclecu.unam.mx>
|
|||
|
* Port to Pango co-done by Gerg<EFBFBD> <EFBFBD>rdi <cactus@cactus.rulez.org>
|
|||
|
*/
|
|||
|
|
|||
|
#include <config.h>
|
|||
|
#include <math.h>
|
|||
|
#include <string.h>
|
|||
|
#include "gnome-canvas-text.h"
|
|||
|
#include <pango/pangoft2.h>
|
|||
|
|
|||
|
#include "libart_lgpl/art_affine.h"
|
|||
|
#include "libart_lgpl/art_rgb_a_affine.h"
|
|||
|
#include "libart_lgpl/art_rgb.h"
|
|||
|
#include "libart_lgpl/art_rgb_bitmap_affine.h"
|
|||
|
#include "gnome-canvas-util.h"
|
|||
|
#include "gnome-canvas-i18n.h"
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* Object argument IDs */
|
|||
|
enum {
|
|||
|
PROP_0,
|
|||
|
|
|||
|
/* Text contents */
|
|||
|
PROP_TEXT,
|
|||
|
PROP_MARKUP,
|
|||
|
|
|||
|
/* Position */
|
|||
|
PROP_X,
|
|||
|
PROP_Y,
|
|||
|
|
|||
|
/* Font */
|
|||
|
PROP_FONT,
|
|||
|
PROP_FONT_DESC,
|
|||
|
PROP_FAMILY, PROP_FAMILY_SET,
|
|||
|
|
|||
|
/* Style */
|
|||
|
PROP_ATTRIBUTES,
|
|||
|
PROP_STYLE, PROP_STYLE_SET,
|
|||
|
PROP_VARIANT, PROP_VARIANT_SET,
|
|||
|
PROP_WEIGHT, PROP_WEIGHT_SET,
|
|||
|
PROP_STRETCH, PROP_STRETCH_SET,
|
|||
|
PROP_SIZE, PROP_SIZE_SET,
|
|||
|
PROP_SIZE_POINTS,
|
|||
|
PROP_STRIKETHROUGH, PROP_STRIKETHROUGH_SET,
|
|||
|
PROP_UNDERLINE, PROP_UNDERLINE_SET,
|
|||
|
PROP_RISE, PROP_RISE_SET,
|
|||
|
PROP_SCALE, PROP_SCALE_SET,
|
|||
|
|
|||
|
/* Clipping */
|
|||
|
PROP_ANCHOR,
|
|||
|
PROP_JUSTIFICATION,
|
|||
|
PROP_CLIP_WIDTH,
|
|||
|
PROP_CLIP_HEIGHT,
|
|||
|
PROP_CLIP,
|
|||
|
PROP_X_OFFSET,
|
|||
|
PROP_Y_OFFSET,
|
|||
|
|
|||
|
/* Coloring */
|
|||
|
PROP_FILL_COLOR,
|
|||
|
PROP_FILL_COLOR_GDK,
|
|||
|
PROP_FILL_COLOR_RGBA,
|
|||
|
PROP_FILL_STIPPLE,
|
|||
|
|
|||
|
/* Rendered size accessors */
|
|||
|
PROP_TEXT_WIDTH,
|
|||
|
PROP_TEXT_HEIGHT
|
|||
|
};
|
|||
|
|
|||
|
struct _GnomeCanvasTextPrivate {
|
|||
|
guint render_dirty : 1;
|
|||
|
FT_Bitmap bitmap;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
static void gnome_canvas_text_class_init (GnomeCanvasTextClass *class);
|
|||
|
static void gnome_canvas_text_init (GnomeCanvasText *text);
|
|||
|
static void gnome_canvas_text_destroy (GtkObject *object);
|
|||
|
static void gnome_canvas_text_set_property (GObject *object,
|
|||
|
guint param_id,
|
|||
|
const GValue *value,
|
|||
|
GParamSpec *pspec);
|
|||
|
static void gnome_canvas_text_get_property (GObject *object,
|
|||
|
guint param_id,
|
|||
|
GValue *value,
|
|||
|
GParamSpec *pspec);
|
|||
|
|
|||
|
static void gnome_canvas_text_update (GnomeCanvasItem *item, double *affine,
|
|||
|
ArtSVP *clip_path, int flags);
|
|||
|
static void gnome_canvas_text_realize (GnomeCanvasItem *item);
|
|||
|
static void gnome_canvas_text_unrealize (GnomeCanvasItem *item);
|
|||
|
static void gnome_canvas_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
|||
|
int x, int y, int width, int height);
|
|||
|
static double gnome_canvas_text_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
|
|||
|
GnomeCanvasItem **actual_item);
|
|||
|
static void gnome_canvas_text_bounds (GnomeCanvasItem *item,
|
|||
|
double *x1, double *y1, double *x2, double *y2);
|
|||
|
static void gnome_canvas_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
|
|||
|
|
|||
|
static void gnome_canvas_text_set_markup (GnomeCanvasText *textitem,
|
|||
|
const gchar *markup);
|
|||
|
|
|||
|
static void gnome_canvas_text_set_font_desc (GnomeCanvasText *textitem,
|
|||
|
PangoFontDescription *font_desc);
|
|||
|
|
|||
|
static void gnome_canvas_text_apply_font_desc (GnomeCanvasText *textitem);
|
|||
|
static void gnome_canvas_text_apply_attributes (GnomeCanvasText *textitem);
|
|||
|
|
|||
|
static void add_attr (PangoAttrList *attr_list,
|
|||
|
PangoAttribute *attr);
|
|||
|
|
|||
|
static GnomeCanvasItemClass *parent_class;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* gnome_canvas_text_get_type:
|
|||
|
* @void:
|
|||
|
*
|
|||
|
* Registers the &GnomeCanvasText class if necessary, and returns the type ID
|
|||
|
* associated to it.
|
|||
|
*
|
|||
|
* Return value: The type ID of the &GnomeCanvasText class.
|
|||
|
**/
|
|||
|
GType
|
|||
|
gnome_canvas_text_get_type (void)
|
|||
|
{
|
|||
|
static GType text_type;
|
|||
|
|
|||
|
if (!text_type) {
|
|||
|
const GTypeInfo object_info = {
|
|||
|
sizeof (GnomeCanvasTextClass),
|
|||
|
(GBaseInitFunc) NULL,
|
|||
|
(GBaseFinalizeFunc) NULL,
|
|||
|
(GClassInitFunc) gnome_canvas_text_class_init,
|
|||
|
(GClassFinalizeFunc) NULL,
|
|||
|
NULL, /* class_data */
|
|||
|
sizeof (GnomeCanvasText),
|
|||
|
0, /* n_preallocs */
|
|||
|
(GInstanceInitFunc) gnome_canvas_text_init,
|
|||
|
NULL /* value_table */
|
|||
|
};
|
|||
|
|
|||
|
text_type = g_type_register_static (GNOME_TYPE_CANVAS_ITEM, "GnomeCanvasText",
|
|||
|
&object_info, 0);
|
|||
|
}
|
|||
|
|
|||
|
return text_type;
|
|||
|
}
|
|||
|
|
|||
|
/* Class initialization function for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_class_init (GnomeCanvasTextClass *class)
|
|||
|
{
|
|||
|
GObjectClass *gobject_class;
|
|||
|
GtkObjectClass *object_class;
|
|||
|
GnomeCanvasItemClass *item_class;
|
|||
|
|
|||
|
gobject_class = (GObjectClass *) class;
|
|||
|
object_class = (GtkObjectClass *) class;
|
|||
|
item_class = (GnomeCanvasItemClass *) class;
|
|||
|
|
|||
|
parent_class = g_type_class_peek_parent (class);
|
|||
|
|
|||
|
gobject_class->set_property = gnome_canvas_text_set_property;
|
|||
|
gobject_class->get_property = gnome_canvas_text_get_property;
|
|||
|
|
|||
|
/* Text */
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_TEXT,
|
|||
|
g_param_spec_string ("text",
|
|||
|
_("Text"),
|
|||
|
_("Text to render"),
|
|||
|
NULL,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_MARKUP,
|
|||
|
g_param_spec_string ("markup",
|
|||
|
_("Markup"),
|
|||
|
_("Marked up text to render"),
|
|||
|
NULL,
|
|||
|
(G_PARAM_WRITABLE)));
|
|||
|
|
|||
|
/* Position */
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_X,
|
|||
|
g_param_spec_double ("x", NULL, NULL,
|
|||
|
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_Y,
|
|||
|
g_param_spec_double ("y", NULL, NULL,
|
|||
|
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
|
|||
|
|
|||
|
/* Font */
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_FONT,
|
|||
|
g_param_spec_string ("font",
|
|||
|
_("Font"),
|
|||
|
_("Font description as a string"),
|
|||
|
NULL,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_FONT_DESC,
|
|||
|
g_param_spec_boxed ("font_desc",
|
|||
|
_("Font description"),
|
|||
|
_("Font description as a PangoFontDescription struct"),
|
|||
|
PANGO_TYPE_FONT_DESCRIPTION,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_FAMILY,
|
|||
|
g_param_spec_string ("family",
|
|||
|
_("Font family"),
|
|||
|
_("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
|
|||
|
NULL,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
|
|||
|
/* Style */
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_ATTRIBUTES,
|
|||
|
g_param_spec_boxed ("attributes", NULL, NULL,
|
|||
|
PANGO_TYPE_ATTR_LIST,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_STYLE,
|
|||
|
g_param_spec_enum ("style",
|
|||
|
_("Font style"),
|
|||
|
_("Font style"),
|
|||
|
PANGO_TYPE_STYLE,
|
|||
|
PANGO_STYLE_NORMAL,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_VARIANT,
|
|||
|
g_param_spec_enum ("variant",
|
|||
|
_("Font variant"),
|
|||
|
_("Font variant"),
|
|||
|
PANGO_TYPE_VARIANT,
|
|||
|
PANGO_VARIANT_NORMAL,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_WEIGHT,
|
|||
|
g_param_spec_int ("weight",
|
|||
|
_("Font weight"),
|
|||
|
_("Font weight"),
|
|||
|
0,
|
|||
|
G_MAXINT,
|
|||
|
PANGO_WEIGHT_NORMAL,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_STRETCH,
|
|||
|
g_param_spec_enum ("stretch",
|
|||
|
_("Font stretch"),
|
|||
|
_("Font stretch"),
|
|||
|
PANGO_TYPE_STRETCH,
|
|||
|
PANGO_STRETCH_NORMAL,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_SIZE,
|
|||
|
g_param_spec_int ("size",
|
|||
|
_("Font size"),
|
|||
|
_("Font size (as a multiple of PANGO_SCALE, eg. 12*PANGO_SCALE for a 12pt font size)"),
|
|||
|
0,
|
|||
|
G_MAXINT,
|
|||
|
0,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_SIZE_POINTS,
|
|||
|
g_param_spec_double ("size_points",
|
|||
|
_("Font points"),
|
|||
|
_("Font size in points (eg. 12 for a 12pt font size)"),
|
|||
|
0.0,
|
|||
|
G_MAXDOUBLE,
|
|||
|
0.0,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_RISE,
|
|||
|
g_param_spec_int ("rise",
|
|||
|
_("Rise"),
|
|||
|
_("Offset of text above the baseline (below the baseline if rise is negative)"),
|
|||
|
-G_MAXINT,
|
|||
|
G_MAXINT,
|
|||
|
0,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_STRIKETHROUGH,
|
|||
|
g_param_spec_boolean ("strikethrough",
|
|||
|
_("Strikethrough"),
|
|||
|
_("Whether to strike through the text"),
|
|||
|
FALSE,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_UNDERLINE,
|
|||
|
g_param_spec_enum ("underline",
|
|||
|
_("Underline"),
|
|||
|
_("Style of underline for this text"),
|
|||
|
PANGO_TYPE_UNDERLINE,
|
|||
|
PANGO_UNDERLINE_NONE,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_SCALE,
|
|||
|
g_param_spec_double ("scale",
|
|||
|
_("Scale"),
|
|||
|
_("Size of font, relative to default size"),
|
|||
|
0.0,
|
|||
|
G_MAXDOUBLE,
|
|||
|
1.0,
|
|||
|
G_PARAM_READABLE | G_PARAM_WRITABLE));
|
|||
|
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_ANCHOR,
|
|||
|
g_param_spec_enum ("anchor", NULL, NULL,
|
|||
|
GTK_TYPE_ANCHOR_TYPE,
|
|||
|
GTK_ANCHOR_CENTER,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_JUSTIFICATION,
|
|||
|
g_param_spec_enum ("justification", NULL, NULL,
|
|||
|
GTK_TYPE_JUSTIFICATION,
|
|||
|
GTK_JUSTIFY_LEFT,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_CLIP_WIDTH,
|
|||
|
g_param_spec_double ("clip_width", NULL, NULL,
|
|||
|
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_CLIP_HEIGHT,
|
|||
|
g_param_spec_double ("clip_height", NULL, NULL,
|
|||
|
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_CLIP,
|
|||
|
g_param_spec_boolean ("clip", NULL, NULL,
|
|||
|
FALSE,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_X_OFFSET,
|
|||
|
g_param_spec_double ("x_offset", NULL, NULL,
|
|||
|
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_Y_OFFSET,
|
|||
|
g_param_spec_double ("y_offset", NULL, NULL,
|
|||
|
-G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_FILL_COLOR,
|
|||
|
g_param_spec_string ("fill_color",
|
|||
|
_("Color"),
|
|||
|
_("Text color, as string"),
|
|||
|
NULL,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_FILL_COLOR_GDK,
|
|||
|
g_param_spec_boxed ("fill_color_gdk",
|
|||
|
_("Color"),
|
|||
|
_("Text color, as a GdkColor"),
|
|||
|
GDK_TYPE_COLOR,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_FILL_COLOR_RGBA,
|
|||
|
g_param_spec_uint ("fill_color_rgba",
|
|||
|
_("Color"),
|
|||
|
_("Text color, as an R/G/B/A combined integer"),
|
|||
|
0, G_MAXUINT, 0,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_FILL_STIPPLE,
|
|||
|
g_param_spec_object ("fill_stipple", NULL, NULL,
|
|||
|
GDK_TYPE_DRAWABLE,
|
|||
|
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_TEXT_WIDTH,
|
|||
|
g_param_spec_double ("text_width",
|
|||
|
_("Text width"),
|
|||
|
_("Width of the rendered text"),
|
|||
|
0.0, G_MAXDOUBLE, 0.0,
|
|||
|
G_PARAM_READABLE));
|
|||
|
g_object_class_install_property
|
|||
|
(gobject_class,
|
|||
|
PROP_TEXT_HEIGHT,
|
|||
|
g_param_spec_double ("text_height",
|
|||
|
_("Text height"),
|
|||
|
_("Height of the rendered text"),
|
|||
|
0.0, G_MAXDOUBLE, 0.0,
|
|||
|
G_PARAM_READABLE));
|
|||
|
|
|||
|
/* Style props are set (explicitly applied) or not */
|
|||
|
#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))
|
|||
|
|
|||
|
ADD_SET_PROP ("family_set", PROP_FAMILY_SET,
|
|||
|
_("Font family set"),
|
|||
|
_("Whether this tag affects the font family"));
|
|||
|
|
|||
|
ADD_SET_PROP ("style_set", PROP_STYLE_SET,
|
|||
|
_("Font style set"),
|
|||
|
_("Whether this tag affects the font style"));
|
|||
|
|
|||
|
ADD_SET_PROP ("variant_set", PROP_VARIANT_SET,
|
|||
|
_("Font variant set"),
|
|||
|
_("Whether this tag affects the font variant"));
|
|||
|
|
|||
|
ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET,
|
|||
|
_("Font weight set"),
|
|||
|
_("Whether this tag affects the font weight"));
|
|||
|
|
|||
|
ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET,
|
|||
|
_("Font stretch set"),
|
|||
|
_("Whether this tag affects the font stretch"));
|
|||
|
|
|||
|
ADD_SET_PROP ("size_set", PROP_SIZE_SET,
|
|||
|
_("Font size set"),
|
|||
|
_("Whether this tag affects the font size"));
|
|||
|
|
|||
|
ADD_SET_PROP ("rise_set", PROP_RISE_SET,
|
|||
|
_("Rise set"),
|
|||
|
_("Whether this tag affects the rise"));
|
|||
|
|
|||
|
ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET,
|
|||
|
_("Strikethrough set"),
|
|||
|
_("Whether this tag affects strikethrough"));
|
|||
|
|
|||
|
ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET,
|
|||
|
_("Underline set"),
|
|||
|
_("Whether this tag affects underlining"));
|
|||
|
|
|||
|
ADD_SET_PROP ("scale_set", PROP_SCALE_SET,
|
|||
|
_("Scale set"),
|
|||
|
_("Whether this tag affects font scaling"));
|
|||
|
#undef ADD_SET_PROP
|
|||
|
|
|||
|
object_class->destroy = gnome_canvas_text_destroy;
|
|||
|
|
|||
|
item_class->update = gnome_canvas_text_update;
|
|||
|
item_class->realize = gnome_canvas_text_realize;
|
|||
|
item_class->unrealize = gnome_canvas_text_unrealize;
|
|||
|
item_class->draw = gnome_canvas_text_draw;
|
|||
|
item_class->point = gnome_canvas_text_point;
|
|||
|
item_class->bounds = gnome_canvas_text_bounds;
|
|||
|
item_class->render = gnome_canvas_text_render;
|
|||
|
}
|
|||
|
|
|||
|
/* Object initialization function for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_init (GnomeCanvasText *text)
|
|||
|
{
|
|||
|
text->x = 0.0;
|
|||
|
text->y = 0.0;
|
|||
|
text->anchor = GTK_ANCHOR_CENTER;
|
|||
|
text->justification = GTK_JUSTIFY_LEFT;
|
|||
|
text->clip_width = 0.0;
|
|||
|
text->clip_height = 0.0;
|
|||
|
text->xofs = 0.0;
|
|||
|
text->yofs = 0.0;
|
|||
|
text->layout = NULL;
|
|||
|
|
|||
|
text->font_desc = NULL;
|
|||
|
|
|||
|
text->underline = PANGO_UNDERLINE_NONE;
|
|||
|
text->strikethrough = FALSE;
|
|||
|
text->rise = 0;
|
|||
|
|
|||
|
text->underline_set = FALSE;
|
|||
|
text->strike_set = FALSE;
|
|||
|
text->rise_set = FALSE;
|
|||
|
|
|||
|
text->priv = g_new (GnomeCanvasTextPrivate, 1);
|
|||
|
text->priv->bitmap.buffer = NULL;
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
}
|
|||
|
|
|||
|
/* Destroy handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_destroy (GtkObject *object)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
|
|||
|
g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (object);
|
|||
|
|
|||
|
/* remember, destroy can be run multiple times! */
|
|||
|
|
|||
|
g_free (text->text);
|
|||
|
text->text = NULL;
|
|||
|
|
|||
|
if (text->layout)
|
|||
|
g_object_unref (G_OBJECT (text->layout));
|
|||
|
text->layout = NULL;
|
|||
|
|
|||
|
if (text->font_desc) {
|
|||
|
pango_font_description_free (text->font_desc);
|
|||
|
text->font_desc = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (text->attr_list)
|
|||
|
pango_attr_list_unref (text->attr_list);
|
|||
|
text->attr_list = NULL;
|
|||
|
|
|||
|
if (text->stipple)
|
|||
|
g_object_unref (text->stipple);
|
|||
|
text->stipple = NULL;
|
|||
|
|
|||
|
if (text->priv && text->priv->bitmap.buffer) {
|
|||
|
g_free (text->priv->bitmap.buffer);
|
|||
|
}
|
|||
|
g_free (text->priv);
|
|||
|
text->priv = NULL;
|
|||
|
|
|||
|
if (GTK_OBJECT_CLASS (parent_class)->destroy)
|
|||
|
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
get_bounds (GnomeCanvasText *text, double *px1, double *py1, double *px2, double *py2)
|
|||
|
{
|
|||
|
GnomeCanvasItem *item;
|
|||
|
double wx, wy;
|
|||
|
|
|||
|
item = GNOME_CANVAS_ITEM (text);
|
|||
|
|
|||
|
/* Get canvas pixel coordinates for text position */
|
|||
|
|
|||
|
|
|||
|
wx = text->x;
|
|||
|
wy = text->y;
|
|||
|
gnome_canvas_item_i2w (item, &wx, &wy);
|
|||
|
gnome_canvas_w2c (item->canvas, wx + text->xofs, wy + text->yofs, &text->cx, &text->cy);
|
|||
|
|
|||
|
/* Get canvas pixel coordinates for clip rectangle position */
|
|||
|
|
|||
|
gnome_canvas_w2c (item->canvas, wx, wy, &text->clip_cx, &text->clip_cy);
|
|||
|
text->clip_cwidth = text->clip_width * item->canvas->pixels_per_unit;
|
|||
|
text->clip_cheight = text->clip_height * item->canvas->pixels_per_unit;
|
|||
|
|
|||
|
/* Anchor text */
|
|||
|
|
|||
|
switch (text->anchor) {
|
|||
|
case GTK_ANCHOR_NW:
|
|||
|
case GTK_ANCHOR_W:
|
|||
|
case GTK_ANCHOR_SW:
|
|||
|
break;
|
|||
|
|
|||
|
case GTK_ANCHOR_N:
|
|||
|
case GTK_ANCHOR_CENTER:
|
|||
|
case GTK_ANCHOR_S:
|
|||
|
text->cx -= text->max_width / 2;
|
|||
|
text->clip_cx -= text->clip_cwidth / 2;
|
|||
|
break;
|
|||
|
|
|||
|
case GTK_ANCHOR_NE:
|
|||
|
case GTK_ANCHOR_E:
|
|||
|
case GTK_ANCHOR_SE:
|
|||
|
text->cx -= text->max_width;
|
|||
|
text->clip_cx -= text->clip_cwidth;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
switch (text->anchor) {
|
|||
|
case GTK_ANCHOR_NW:
|
|||
|
case GTK_ANCHOR_N:
|
|||
|
case GTK_ANCHOR_NE:
|
|||
|
break;
|
|||
|
|
|||
|
case GTK_ANCHOR_W:
|
|||
|
case GTK_ANCHOR_CENTER:
|
|||
|
case GTK_ANCHOR_E:
|
|||
|
text->cy -= text->height / 2;
|
|||
|
text->clip_cy -= text->clip_cheight / 2;
|
|||
|
break;
|
|||
|
|
|||
|
case GTK_ANCHOR_SW:
|
|||
|
case GTK_ANCHOR_S:
|
|||
|
case GTK_ANCHOR_SE:
|
|||
|
text->cy -= text->height;
|
|||
|
text->clip_cy -= text->clip_cheight;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
/* Bounds */
|
|||
|
|
|||
|
if (text->clip) {
|
|||
|
*px1 = text->clip_cx;
|
|||
|
*py1 = text->clip_cy;
|
|||
|
*px2 = text->clip_cx + text->clip_cwidth;
|
|||
|
*py2 = text->clip_cy + text->clip_cheight;
|
|||
|
} else {
|
|||
|
*px1 = text->cx;
|
|||
|
*py1 = text->cy;
|
|||
|
*px2 = text->cx + text->max_width;
|
|||
|
*py2 = text->cy + text->height;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* Convenience function to set the text's GC's foreground color */
|
|||
|
static void
|
|||
|
set_text_gc_foreground (GnomeCanvasText *text)
|
|||
|
{
|
|||
|
GdkColor c;
|
|||
|
|
|||
|
if (!text->gc)
|
|||
|
return;
|
|||
|
|
|||
|
c.pixel = text->pixel;
|
|||
|
gdk_gc_set_foreground (text->gc, &c);
|
|||
|
}
|
|||
|
|
|||
|
/* Sets the stipple pattern for the text */
|
|||
|
static void
|
|||
|
set_stipple (GnomeCanvasText *text, GdkBitmap *stipple, int reconfigure)
|
|||
|
{
|
|||
|
if (text->stipple && !reconfigure)
|
|||
|
g_object_unref (text->stipple);
|
|||
|
|
|||
|
text->stipple = stipple;
|
|||
|
if (stipple && !reconfigure)
|
|||
|
g_object_ref (stipple);
|
|||
|
|
|||
|
if (text->gc) {
|
|||
|
if (stipple) {
|
|||
|
gdk_gc_set_stipple (text->gc, stipple);
|
|||
|
gdk_gc_set_fill (text->gc, GDK_STIPPLED);
|
|||
|
} else
|
|||
|
gdk_gc_set_fill (text->gc, GDK_SOLID);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static PangoFontMask
|
|||
|
get_property_font_set_mask (guint prop_id)
|
|||
|
{
|
|||
|
switch (prop_id)
|
|||
|
{
|
|||
|
case PROP_FAMILY_SET:
|
|||
|
return PANGO_FONT_MASK_FAMILY;
|
|||
|
case PROP_STYLE_SET:
|
|||
|
return PANGO_FONT_MASK_STYLE;
|
|||
|
case PROP_VARIANT_SET:
|
|||
|
return PANGO_FONT_MASK_VARIANT;
|
|||
|
case PROP_WEIGHT_SET:
|
|||
|
return PANGO_FONT_MASK_WEIGHT;
|
|||
|
case PROP_STRETCH_SET:
|
|||
|
return PANGO_FONT_MASK_STRETCH;
|
|||
|
case PROP_SIZE_SET:
|
|||
|
return PANGO_FONT_MASK_SIZE;
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
ensure_font (GnomeCanvasText *text)
|
|||
|
{
|
|||
|
if (!text->font_desc)
|
|||
|
text->font_desc = pango_font_description_new ();
|
|||
|
}
|
|||
|
|
|||
|
/* Set_arg handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_set_property (GObject *object,
|
|||
|
guint param_id,
|
|||
|
const GValue *value,
|
|||
|
GParamSpec *pspec)
|
|||
|
{
|
|||
|
GnomeCanvasItem *item;
|
|||
|
GnomeCanvasText *text;
|
|||
|
GdkColor color = { 0, 0, 0, 0, };
|
|||
|
GdkColor *pcolor;
|
|||
|
gboolean color_changed;
|
|||
|
int have_pixel;
|
|||
|
PangoAlignment align;
|
|||
|
|
|||
|
g_return_if_fail (object != NULL);
|
|||
|
g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
|
|||
|
|
|||
|
item = GNOME_CANVAS_ITEM (object);
|
|||
|
text = GNOME_CANVAS_TEXT (object);
|
|||
|
|
|||
|
color_changed = FALSE;
|
|||
|
have_pixel = FALSE;
|
|||
|
|
|||
|
|
|||
|
if (!text->layout) {
|
|||
|
|
|||
|
PangoContext *gtk_context, *context;
|
|||
|
gtk_context = gtk_widget_get_pango_context (GTK_WIDGET (item->canvas));
|
|||
|
|
|||
|
if (item->canvas->aa) {
|
|||
|
PangoLanguage *language;
|
|||
|
gint pixels, mm;
|
|||
|
double dpi_x;
|
|||
|
double dpi_y;
|
|||
|
|
|||
|
pixels = gdk_screen_width ();
|
|||
|
mm = gdk_screen_width_mm ();
|
|||
|
dpi_x = (((double) pixels * 25.4) / (double) mm);
|
|||
|
|
|||
|
pixels = gdk_screen_height ();
|
|||
|
mm = gdk_screen_height_mm ();
|
|||
|
dpi_y = (((double) pixels * 25.4) / (double) mm);
|
|||
|
|
|||
|
context = pango_ft2_get_context (dpi_x, dpi_y);
|
|||
|
language = pango_context_get_language (gtk_context);
|
|||
|
pango_context_set_language (context, language);
|
|||
|
pango_context_set_base_dir (context,
|
|||
|
pango_context_get_base_dir (gtk_context));
|
|||
|
pango_context_set_font_description (context,
|
|||
|
pango_context_get_font_description (gtk_context));
|
|||
|
|
|||
|
} else
|
|||
|
context = gtk_context;
|
|||
|
|
|||
|
|
|||
|
text->layout = pango_layout_new (context);
|
|||
|
|
|||
|
if (item->canvas->aa)
|
|||
|
g_object_unref (G_OBJECT (context));
|
|||
|
}
|
|||
|
|
|||
|
switch (param_id) {
|
|||
|
case PROP_TEXT:
|
|||
|
g_free (text->text);
|
|||
|
|
|||
|
text->text = g_value_dup_string (value);
|
|||
|
pango_layout_set_text (text->layout, text->text, -1);
|
|||
|
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_MARKUP:
|
|||
|
gnome_canvas_text_set_markup (text,
|
|||
|
g_value_get_string (value));
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_X:
|
|||
|
text->x = g_value_get_double (value);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_Y:
|
|||
|
text->y = g_value_get_double (value);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FONT: {
|
|||
|
const char *font_name;
|
|||
|
PangoFontDescription *font_desc;
|
|||
|
|
|||
|
font_name = g_value_get_string (value);
|
|||
|
if (font_name)
|
|||
|
font_desc = pango_font_description_from_string (font_name);
|
|||
|
else
|
|||
|
font_desc = NULL;
|
|||
|
|
|||
|
gnome_canvas_text_set_font_desc (text, font_desc);
|
|||
|
if (font_desc)
|
|||
|
pango_font_description_free (font_desc);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case PROP_FONT_DESC:
|
|||
|
gnome_canvas_text_set_font_desc (text, g_value_peek_pointer (value));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FAMILY:
|
|||
|
case PROP_STYLE:
|
|||
|
case PROP_VARIANT:
|
|||
|
case PROP_WEIGHT:
|
|||
|
case PROP_STRETCH:
|
|||
|
case PROP_SIZE:
|
|||
|
case PROP_SIZE_POINTS:
|
|||
|
ensure_font (text);
|
|||
|
|
|||
|
switch (param_id) {
|
|||
|
case PROP_FAMILY:
|
|||
|
pango_font_description_set_family (text->font_desc,
|
|||
|
g_value_get_string (value));
|
|||
|
break;
|
|||
|
case PROP_STYLE:
|
|||
|
pango_font_description_set_style (text->font_desc,
|
|||
|
g_value_get_enum (value));
|
|||
|
break;
|
|||
|
case PROP_VARIANT:
|
|||
|
pango_font_description_set_variant (text->font_desc,
|
|||
|
g_value_get_enum (value));
|
|||
|
break;
|
|||
|
case PROP_WEIGHT:
|
|||
|
pango_font_description_set_weight (text->font_desc,
|
|||
|
g_value_get_int (value));
|
|||
|
break;
|
|||
|
case PROP_STRETCH:
|
|||
|
pango_font_description_set_stretch (text->font_desc,
|
|||
|
g_value_get_enum (value));
|
|||
|
break;
|
|||
|
case PROP_SIZE:
|
|||
|
/* FIXME: This is bogus! It should be pixels, not points/PANGO_SCALE! */
|
|||
|
pango_font_description_set_size (text->font_desc,
|
|||
|
g_value_get_int (value));
|
|||
|
break;
|
|||
|
case PROP_SIZE_POINTS:
|
|||
|
pango_font_description_set_size (text->font_desc,
|
|||
|
g_value_get_double (value) * PANGO_SCALE);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
gnome_canvas_text_apply_font_desc (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FAMILY_SET:
|
|||
|
case PROP_STYLE_SET:
|
|||
|
case PROP_VARIANT_SET:
|
|||
|
case PROP_WEIGHT_SET:
|
|||
|
case PROP_STRETCH_SET:
|
|||
|
case PROP_SIZE_SET:
|
|||
|
if (!g_value_get_boolean (value) && text->font_desc)
|
|||
|
pango_font_description_unset_fields (text->font_desc,
|
|||
|
get_property_font_set_mask (param_id));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_SCALE:
|
|||
|
text->scale = g_value_get_double (value);
|
|||
|
text->scale_set = TRUE;
|
|||
|
|
|||
|
gnome_canvas_text_apply_font_desc (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_SCALE_SET:
|
|||
|
text->scale_set = g_value_get_boolean (value);
|
|||
|
|
|||
|
gnome_canvas_text_apply_font_desc (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_UNDERLINE:
|
|||
|
text->underline = g_value_get_enum (value);
|
|||
|
text->underline_set = TRUE;
|
|||
|
|
|||
|
gnome_canvas_text_apply_attributes (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_UNDERLINE_SET:
|
|||
|
text->underline_set = g_value_get_boolean (value);
|
|||
|
|
|||
|
gnome_canvas_text_apply_attributes (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_STRIKETHROUGH:
|
|||
|
text->strikethrough = g_value_get_boolean (value);
|
|||
|
text->strike_set = TRUE;
|
|||
|
|
|||
|
gnome_canvas_text_apply_attributes (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_STRIKETHROUGH_SET:
|
|||
|
text->strike_set = g_value_get_boolean (value);
|
|||
|
|
|||
|
gnome_canvas_text_apply_attributes (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_RISE:
|
|||
|
text->rise = g_value_get_int (value);
|
|||
|
text->rise_set = TRUE;
|
|||
|
|
|||
|
gnome_canvas_text_apply_attributes (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_RISE_SET:
|
|||
|
text->rise_set = TRUE;
|
|||
|
|
|||
|
gnome_canvas_text_apply_attributes (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_ATTRIBUTES:
|
|||
|
if (text->attr_list)
|
|||
|
pango_attr_list_unref (text->attr_list);
|
|||
|
|
|||
|
text->attr_list = g_value_peek_pointer (value);
|
|||
|
pango_attr_list_ref (text->attr_list);
|
|||
|
|
|||
|
gnome_canvas_text_apply_attributes (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_ANCHOR:
|
|||
|
text->anchor = g_value_get_enum (value);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_JUSTIFICATION:
|
|||
|
text->justification = g_value_get_enum (value);
|
|||
|
|
|||
|
switch (text->justification) {
|
|||
|
case GTK_JUSTIFY_LEFT:
|
|||
|
align = PANGO_ALIGN_LEFT;
|
|||
|
break;
|
|||
|
case GTK_JUSTIFY_CENTER:
|
|||
|
align = PANGO_ALIGN_CENTER;
|
|||
|
break;
|
|||
|
case GTK_JUSTIFY_RIGHT:
|
|||
|
align = PANGO_ALIGN_RIGHT;
|
|||
|
break;
|
|||
|
default:
|
|||
|
/* GTK_JUSTIFY_FILL isn't supported yet. */
|
|||
|
align = PANGO_ALIGN_LEFT;
|
|||
|
break;
|
|||
|
}
|
|||
|
pango_layout_set_alignment (text->layout, align);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_CLIP_WIDTH:
|
|||
|
text->clip_width = fabs (g_value_get_double (value));
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_CLIP_HEIGHT:
|
|||
|
text->clip_height = fabs (g_value_get_double (value));
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_CLIP:
|
|||
|
text->clip = g_value_get_boolean (value);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_X_OFFSET:
|
|||
|
text->xofs = g_value_get_double (value);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_Y_OFFSET:
|
|||
|
text->yofs = g_value_get_double (value);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FILL_COLOR: {
|
|||
|
const char *color_name;
|
|||
|
|
|||
|
color_name = g_value_get_string (value);
|
|||
|
if (color_name) {
|
|||
|
gdk_color_parse (color_name, &color);
|
|||
|
|
|||
|
text->rgba = ((color.red & 0xff00) << 16 |
|
|||
|
(color.green & 0xff00) << 8 |
|
|||
|
(color.blue & 0xff00) |
|
|||
|
0xff);
|
|||
|
color_changed = TRUE;
|
|||
|
}
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case PROP_FILL_COLOR_GDK:
|
|||
|
pcolor = g_value_get_boxed (value);
|
|||
|
if (pcolor) {
|
|||
|
GdkColormap *colormap;
|
|||
|
|
|||
|
color = *pcolor;
|
|||
|
colormap = gtk_widget_get_colormap (GTK_WIDGET (item->canvas));
|
|||
|
gdk_rgb_find_color (colormap, &color);
|
|||
|
have_pixel = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
text->rgba = ((color.red & 0xff00) << 16 |
|
|||
|
(color.green & 0xff00) << 8|
|
|||
|
(color.blue & 0xff00) |
|
|||
|
0xff);
|
|||
|
color_changed = TRUE;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FILL_COLOR_RGBA:
|
|||
|
text->rgba = g_value_get_uint (value);
|
|||
|
color_changed = TRUE;
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FILL_STIPPLE:
|
|||
|
set_stipple (text, (GdkBitmap *)g_value_get_object (value), FALSE);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (color_changed) {
|
|||
|
if (have_pixel)
|
|||
|
text->pixel = color.pixel;
|
|||
|
else
|
|||
|
text->pixel = gnome_canvas_get_color_pixel (item->canvas, text->rgba);
|
|||
|
|
|||
|
if (!item->canvas->aa)
|
|||
|
set_text_gc_foreground (text);
|
|||
|
}
|
|||
|
|
|||
|
/* Calculate text dimensions */
|
|||
|
|
|||
|
if (text->layout)
|
|||
|
pango_layout_get_pixel_size (text->layout,
|
|||
|
&text->max_width,
|
|||
|
&text->height);
|
|||
|
else {
|
|||
|
text->max_width = 0;
|
|||
|
text->height = 0;
|
|||
|
}
|
|||
|
|
|||
|
gnome_canvas_item_request_update (item);
|
|||
|
}
|
|||
|
|
|||
|
/* Get_arg handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_get_property (GObject *object,
|
|||
|
guint param_id,
|
|||
|
GValue *value,
|
|||
|
GParamSpec *pspec)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
|
|||
|
g_return_if_fail (object != NULL);
|
|||
|
g_return_if_fail (GNOME_IS_CANVAS_TEXT (object));
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (object);
|
|||
|
|
|||
|
switch (param_id) {
|
|||
|
case PROP_TEXT:
|
|||
|
g_value_set_string (value, text->text);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_X:
|
|||
|
g_value_set_double (value, text->x);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_Y:
|
|||
|
g_value_set_double (value, text->y);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FONT:
|
|||
|
case PROP_FONT_DESC:
|
|||
|
case PROP_FAMILY:
|
|||
|
case PROP_STYLE:
|
|||
|
case PROP_VARIANT:
|
|||
|
case PROP_WEIGHT:
|
|||
|
case PROP_STRETCH:
|
|||
|
case PROP_SIZE:
|
|||
|
case PROP_SIZE_POINTS:
|
|||
|
ensure_font (text);
|
|||
|
|
|||
|
switch (param_id) {
|
|||
|
case PROP_FONT:
|
|||
|
{
|
|||
|
/* FIXME GValue imposes a totally gratuitous string copy
|
|||
|
* here, we could just hand off string ownership
|
|||
|
*/
|
|||
|
gchar *str;
|
|||
|
|
|||
|
str = pango_font_description_to_string (text->font_desc);
|
|||
|
g_value_set_string (value, str);
|
|||
|
g_free (str);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case PROP_FONT_DESC:
|
|||
|
g_value_set_boxed (value, text->font_desc);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FAMILY:
|
|||
|
g_value_set_string (value, pango_font_description_get_family (text->font_desc));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_STYLE:
|
|||
|
g_value_set_enum (value, pango_font_description_get_style (text->font_desc));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_VARIANT:
|
|||
|
g_value_set_enum (value, pango_font_description_get_variant (text->font_desc));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_WEIGHT:
|
|||
|
g_value_set_int (value, pango_font_description_get_weight (text->font_desc));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_STRETCH:
|
|||
|
g_value_set_enum (value, pango_font_description_get_stretch (text->font_desc));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_SIZE:
|
|||
|
g_value_set_int (value, pango_font_description_get_size (text->font_desc));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_SIZE_POINTS:
|
|||
|
g_value_set_double (value, ((double)pango_font_description_get_size (text->font_desc)) / (double)PANGO_SCALE);
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FAMILY_SET:
|
|||
|
case PROP_STYLE_SET:
|
|||
|
case PROP_VARIANT_SET:
|
|||
|
case PROP_WEIGHT_SET:
|
|||
|
case PROP_STRETCH_SET:
|
|||
|
case PROP_SIZE_SET:
|
|||
|
{
|
|||
|
PangoFontMask set_mask = text->font_desc ? pango_font_description_get_set_fields (text->font_desc) : 0;
|
|||
|
PangoFontMask test_mask = get_property_font_set_mask (param_id);
|
|||
|
g_value_set_boolean (value, (set_mask & test_mask) != 0);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case PROP_SCALE:
|
|||
|
g_value_set_double (value, text->scale);
|
|||
|
break;
|
|||
|
case PROP_SCALE_SET:
|
|||
|
g_value_set_boolean (value, text->scale_set);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_UNDERLINE:
|
|||
|
g_value_set_enum (value, text->underline);
|
|||
|
break;
|
|||
|
case PROP_UNDERLINE_SET:
|
|||
|
g_value_set_boolean (value, text->underline_set);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_STRIKETHROUGH:
|
|||
|
g_value_set_boolean (value, text->strikethrough);
|
|||
|
break;
|
|||
|
case PROP_STRIKETHROUGH_SET:
|
|||
|
g_value_set_boolean (value, text->strike_set);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_RISE:
|
|||
|
g_value_set_int (value, text->rise);
|
|||
|
break;
|
|||
|
case PROP_RISE_SET:
|
|||
|
g_value_set_boolean (value, text->rise_set);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_ATTRIBUTES:
|
|||
|
g_value_set_boxed (value, text->attr_list);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_ANCHOR:
|
|||
|
g_value_set_enum (value, text->anchor);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_JUSTIFICATION:
|
|||
|
g_value_set_enum (value, text->justification);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_CLIP_WIDTH:
|
|||
|
g_value_set_double (value, text->clip_width);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_CLIP_HEIGHT:
|
|||
|
g_value_set_double (value, text->clip_height);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_CLIP:
|
|||
|
g_value_set_boolean (value, text->clip);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_X_OFFSET:
|
|||
|
g_value_set_double (value, text->xofs);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_Y_OFFSET:
|
|||
|
g_value_set_double (value, text->yofs);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FILL_COLOR:
|
|||
|
g_value_take_string (value,
|
|||
|
g_strdup_printf ("#%02x%02x%02x",
|
|||
|
text->rgba >> 24,
|
|||
|
(text->rgba >> 16) & 0xff,
|
|||
|
(text->rgba >> 8) & 0xff));
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FILL_COLOR_GDK: {
|
|||
|
GnomeCanvas *canvas = GNOME_CANVAS_ITEM (text)->canvas;
|
|||
|
GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (canvas));
|
|||
|
GdkColor color;
|
|||
|
|
|||
|
gdk_colormap_query_color (colormap, text->pixel, &color);
|
|||
|
g_value_set_boxed (value, &color);
|
|||
|
break;
|
|||
|
}
|
|||
|
case PROP_FILL_COLOR_RGBA:
|
|||
|
g_value_set_uint (value, text->rgba);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_FILL_STIPPLE:
|
|||
|
g_value_set_object (value, text->stipple);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_TEXT_WIDTH:
|
|||
|
g_value_set_double (value, text->max_width / text->item.canvas->pixels_per_unit);
|
|||
|
break;
|
|||
|
|
|||
|
case PROP_TEXT_HEIGHT:
|
|||
|
g_value_set_double (value, text->height / text->item.canvas->pixels_per_unit);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* */
|
|||
|
static void
|
|||
|
gnome_canvas_text_apply_font_desc (GnomeCanvasText *text)
|
|||
|
{
|
|||
|
PangoFontDescription *font_desc =
|
|||
|
pango_font_description_copy (
|
|||
|
GTK_WIDGET (GNOME_CANVAS_ITEM (text)->canvas)->style->font_desc);
|
|||
|
|
|||
|
if (text->font_desc)
|
|||
|
pango_font_description_merge (font_desc, text->font_desc, TRUE);
|
|||
|
|
|||
|
pango_layout_set_font_description (text->layout, font_desc);
|
|||
|
pango_font_description_free (font_desc);
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
add_attr (PangoAttrList *attr_list,
|
|||
|
PangoAttribute *attr)
|
|||
|
{
|
|||
|
attr->start_index = 0;
|
|||
|
attr->end_index = G_MAXINT;
|
|||
|
|
|||
|
pango_attr_list_insert (attr_list, attr);
|
|||
|
}
|
|||
|
|
|||
|
/* */
|
|||
|
static void
|
|||
|
gnome_canvas_text_apply_attributes (GnomeCanvasText *text)
|
|||
|
{
|
|||
|
PangoAttrList *attr_list;
|
|||
|
|
|||
|
if (text->attr_list)
|
|||
|
attr_list = pango_attr_list_copy (text->attr_list);
|
|||
|
else
|
|||
|
attr_list = pango_attr_list_new ();
|
|||
|
|
|||
|
if (text->underline_set)
|
|||
|
add_attr (attr_list, pango_attr_underline_new (text->underline));
|
|||
|
if (text->strike_set)
|
|||
|
add_attr (attr_list, pango_attr_strikethrough_new (text->strikethrough));
|
|||
|
if (text->rise_set)
|
|||
|
add_attr (attr_list, pango_attr_rise_new (text->rise));
|
|||
|
|
|||
|
pango_layout_set_attributes (text->layout, attr_list);
|
|||
|
pango_attr_list_unref (attr_list);
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
gnome_canvas_text_set_font_desc (GnomeCanvasText *text,
|
|||
|
PangoFontDescription *font_desc)
|
|||
|
{
|
|||
|
if (text->font_desc)
|
|||
|
pango_font_description_free (text->font_desc);
|
|||
|
|
|||
|
if (font_desc)
|
|||
|
text->font_desc = pango_font_description_copy (font_desc);
|
|||
|
else
|
|||
|
text->font_desc = NULL;
|
|||
|
|
|||
|
gnome_canvas_text_apply_font_desc (text);
|
|||
|
text->priv->render_dirty = 1;
|
|||
|
}
|
|||
|
|
|||
|
/* Setting the text from a Pango markup string */
|
|||
|
static void
|
|||
|
gnome_canvas_text_set_markup (GnomeCanvasText *textitem,
|
|||
|
const gchar *markup)
|
|||
|
{
|
|||
|
PangoAttrList *attr_list = NULL;
|
|||
|
gchar *text = NULL;
|
|||
|
GError *error = NULL;
|
|||
|
|
|||
|
if (markup && !pango_parse_markup (markup, -1,
|
|||
|
0,
|
|||
|
&attr_list, &text, NULL,
|
|||
|
&error))
|
|||
|
{
|
|||
|
g_warning ("Failed to set cell text from markup due to error parsing markup: %s",
|
|||
|
error->message);
|
|||
|
g_error_free (error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
g_free (textitem->text);
|
|||
|
if (textitem->attr_list)
|
|||
|
pango_attr_list_unref (textitem->attr_list);
|
|||
|
|
|||
|
textitem->text = text;
|
|||
|
textitem->attr_list = attr_list;
|
|||
|
|
|||
|
pango_layout_set_text (textitem->layout, text, -1);
|
|||
|
|
|||
|
gnome_canvas_text_apply_attributes (textitem);
|
|||
|
}
|
|||
|
|
|||
|
/* Update handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
double x1, y1, x2, y2;
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (item);
|
|||
|
|
|||
|
if (parent_class->update)
|
|||
|
(* parent_class->update) (item, affine, clip_path, flags);
|
|||
|
|
|||
|
set_text_gc_foreground (text);
|
|||
|
set_stipple (text, text->stipple, TRUE);
|
|||
|
get_bounds (text, &x1, &y1, &x2, &y2);
|
|||
|
|
|||
|
gnome_canvas_update_bbox (item,
|
|||
|
floor (x1), floor (y1),
|
|||
|
ceil (x2), ceil (y2));
|
|||
|
}
|
|||
|
|
|||
|
/* Realize handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_realize (GnomeCanvasItem *item)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (item);
|
|||
|
|
|||
|
if (parent_class->realize)
|
|||
|
(* parent_class->realize) (item);
|
|||
|
|
|||
|
text->gc = gdk_gc_new (item->canvas->layout.bin_window);
|
|||
|
}
|
|||
|
|
|||
|
/* Unrealize handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_unrealize (GnomeCanvasItem *item)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (item);
|
|||
|
|
|||
|
g_object_unref (text->gc);
|
|||
|
text->gc = NULL;
|
|||
|
|
|||
|
if (parent_class->unrealize)
|
|||
|
(* parent_class->unrealize) (item);
|
|||
|
}
|
|||
|
|
|||
|
/* Draw handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
|||
|
int x, int y, int width, int height)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
GdkRectangle rect;
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (item);
|
|||
|
|
|||
|
if (!text->text)
|
|||
|
return;
|
|||
|
|
|||
|
if (text->clip) {
|
|||
|
rect.x = text->clip_cx - x;
|
|||
|
rect.y = text->clip_cy - y;
|
|||
|
rect.width = text->clip_cwidth;
|
|||
|
rect.height = text->clip_cheight;
|
|||
|
|
|||
|
gdk_gc_set_clip_rectangle (text->gc, &rect);
|
|||
|
}
|
|||
|
|
|||
|
if (text->stipple)
|
|||
|
gnome_canvas_set_stipple_origin (item->canvas, text->gc);
|
|||
|
|
|||
|
|
|||
|
gdk_draw_layout (drawable, text->gc, text->cx - x, text->cy - y, text->layout);
|
|||
|
|
|||
|
if (text->clip)
|
|||
|
gdk_gc_set_clip_rectangle (text->gc, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* Render handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
guint32 fg_color;
|
|||
|
int render_x = 0, render_y = 0; /* offsets for text rendering,
|
|||
|
* for clipping rectangles */
|
|||
|
int x, y;
|
|||
|
int w, h;
|
|||
|
guchar *dst, *src;
|
|||
|
int src_dx, src_dy;
|
|||
|
int i, alpha;
|
|||
|
int bm_rows, bm_width;
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (item);
|
|||
|
|
|||
|
if (!text->text)
|
|||
|
return;
|
|||
|
|
|||
|
fg_color = text->rgba;
|
|||
|
|
|||
|
gnome_canvas_buf_ensure_buf (buf);
|
|||
|
|
|||
|
bm_rows = (text->clip) ? text->clip_cheight : text->height;
|
|||
|
bm_width = (text->clip) ? text->clip_cwidth : text->max_width;
|
|||
|
if(text->priv->render_dirty ||
|
|||
|
bm_rows != text->priv->bitmap.rows ||
|
|||
|
bm_width != text->priv->bitmap.width) {
|
|||
|
if(text->priv->bitmap.buffer) {
|
|||
|
g_free(text->priv->bitmap.buffer);
|
|||
|
}
|
|||
|
text->priv->bitmap.rows = bm_rows;
|
|||
|
text->priv->bitmap.width = bm_width;
|
|||
|
text->priv->bitmap.pitch = (text->priv->bitmap.width+3)&~3;
|
|||
|
text->priv->bitmap.buffer = g_malloc0 (text->priv->bitmap.rows * text->priv->bitmap.pitch);
|
|||
|
text->priv->bitmap.num_grays = 256;
|
|||
|
text->priv->bitmap.pixel_mode = ft_pixel_mode_grays;
|
|||
|
|
|||
|
/* What this does is when a clipping rectangle is
|
|||
|
being used shift the rendering of the text by the
|
|||
|
correct amount so that the correct result is
|
|||
|
obtained as if all text was rendered, then clipped.
|
|||
|
In this sense we can use smaller buffers and less
|
|||
|
rendeirng since hopefully FreeType2 checks to see
|
|||
|
if the glyph falls in the bounding box before
|
|||
|
rasterizing it. */
|
|||
|
|
|||
|
if(text->clip) {
|
|||
|
render_x = text->cx - text->clip_cx;
|
|||
|
render_y = text->cy - text->clip_cy;
|
|||
|
}
|
|||
|
|
|||
|
pango_ft2_render_layout (&text->priv->bitmap, text->layout, render_x, render_y);
|
|||
|
|
|||
|
text->priv->render_dirty = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (text->clip) {
|
|||
|
x = text->clip_cx - buf->rect.x0;
|
|||
|
y = text->clip_cy - buf->rect.y0;
|
|||
|
} else {
|
|||
|
x = text->cx - buf->rect.x0;
|
|||
|
y = text->cy - buf->rect.y0;
|
|||
|
}
|
|||
|
|
|||
|
w = text->priv->bitmap.width;
|
|||
|
h = text->priv->bitmap.rows;
|
|||
|
|
|||
|
src_dx = src_dy = 0;
|
|||
|
|
|||
|
if (x + w > buf->rect.x1 - buf->rect.x0) {
|
|||
|
w = buf->rect.x1 - buf->rect.x0 - x;
|
|||
|
}
|
|||
|
|
|||
|
if (y + h > buf->rect.y1 - buf->rect.y0) {
|
|||
|
h = buf->rect.y1 - buf->rect.y0 - y;
|
|||
|
}
|
|||
|
|
|||
|
if (x < 0) {
|
|||
|
w -= - x;
|
|||
|
src_dx += - x;
|
|||
|
x = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (y < 0) {
|
|||
|
h -= -y;
|
|||
|
src_dy += - y;
|
|||
|
y = 0;
|
|||
|
}
|
|||
|
|
|||
|
dst = buf->buf + y * buf->buf_rowstride + x * 3;
|
|||
|
src = text->priv->bitmap.buffer +
|
|||
|
src_dy * text->priv->bitmap.pitch + src_dx;
|
|||
|
while (h-- > 0) {
|
|||
|
i = w;
|
|||
|
while (i-- > 0) {
|
|||
|
/* FIXME: Do the libart thing instead of divide by 255 */
|
|||
|
alpha = ((fg_color & 0xff) * (*src)) / 255;
|
|||
|
dst[0] = (dst[0] * (255 - alpha) + ((fg_color >> 24) & 0xff) * alpha) / 255;
|
|||
|
dst[1] = (dst[1] * (255 - alpha) + ((fg_color >> 16) & 0xff) * alpha) / 255;
|
|||
|
dst[2] = (dst[2] * (255 - alpha) + ((fg_color >> 8) & 0xff) * alpha) / 255;
|
|||
|
dst += 3;
|
|||
|
src += 1;
|
|||
|
}
|
|||
|
dst += buf->buf_rowstride - w*3;
|
|||
|
src += text->priv->bitmap.pitch - w;
|
|||
|
}
|
|||
|
|
|||
|
buf->is_bg = 0;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/* Point handler for the text item */
|
|||
|
static double
|
|||
|
gnome_canvas_text_point (GnomeCanvasItem *item, double x, double y,
|
|||
|
int cx, int cy, GnomeCanvasItem **actual_item)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
PangoLayoutIter *iter;
|
|||
|
int x1, y1, x2, y2;
|
|||
|
int dx, dy;
|
|||
|
double dist, best;
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (item);
|
|||
|
|
|||
|
*actual_item = item;
|
|||
|
|
|||
|
/* The idea is to build bounding rectangles for each of the lines of
|
|||
|
* text (clipped by the clipping rectangle, if it is activated) and see
|
|||
|
* whether the point is inside any of these. If it is, we are done.
|
|||
|
* Otherwise, calculate the distance to the nearest rectangle.
|
|||
|
*/
|
|||
|
|
|||
|
best = 1.0e36;
|
|||
|
|
|||
|
iter = pango_layout_get_iter (text->layout);
|
|||
|
do {
|
|||
|
PangoRectangle log_rect;
|
|||
|
|
|||
|
pango_layout_iter_get_line_extents (iter, NULL, &log_rect);
|
|||
|
|
|||
|
x1 = text->cx + PANGO_PIXELS (log_rect.x);
|
|||
|
y1 = text->cy + PANGO_PIXELS (log_rect.y);
|
|||
|
x2 = x1 + PANGO_PIXELS (log_rect.width);
|
|||
|
y2 = y1 + PANGO_PIXELS (log_rect.height);
|
|||
|
|
|||
|
if (text->clip) {
|
|||
|
if (x1 < text->clip_cx)
|
|||
|
x1 = text->clip_cx;
|
|||
|
|
|||
|
if (y1 < text->clip_cy)
|
|||
|
y1 = text->clip_cy;
|
|||
|
|
|||
|
if (x2 > (text->clip_cx + text->clip_width))
|
|||
|
x2 = text->clip_cx + text->clip_width;
|
|||
|
|
|||
|
if (y2 > (text->clip_cy + text->clip_height))
|
|||
|
y2 = text->clip_cy + text->clip_height;
|
|||
|
|
|||
|
if ((x1 >= x2) || (y1 >= y2))
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
/* Calculate distance from point to rectangle */
|
|||
|
|
|||
|
if (cx < x1)
|
|||
|
dx = x1 - cx;
|
|||
|
else if (cx >= x2)
|
|||
|
dx = cx - x2 + 1;
|
|||
|
else
|
|||
|
dx = 0;
|
|||
|
|
|||
|
if (cy < y1)
|
|||
|
dy = y1 - cy;
|
|||
|
else if (cy >= y2)
|
|||
|
dy = cy - y2 + 1;
|
|||
|
else
|
|||
|
dy = 0;
|
|||
|
|
|||
|
if ((dx == 0) && (dy == 0)) {
|
|||
|
pango_layout_iter_free(iter);
|
|||
|
return 0.0;
|
|||
|
}
|
|||
|
|
|||
|
dist = sqrt (dx * dx + dy * dy);
|
|||
|
if (dist < best)
|
|||
|
best = dist;
|
|||
|
|
|||
|
} while (pango_layout_iter_next_line(iter));
|
|||
|
|
|||
|
pango_layout_iter_free(iter);
|
|||
|
|
|||
|
return best / item->canvas->pixels_per_unit;
|
|||
|
}
|
|||
|
|
|||
|
/* Bounds handler for the text item */
|
|||
|
static void
|
|||
|
gnome_canvas_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
|
|||
|
{
|
|||
|
GnomeCanvasText *text;
|
|||
|
double width, height;
|
|||
|
|
|||
|
text = GNOME_CANVAS_TEXT (item);
|
|||
|
|
|||
|
*x1 = text->x;
|
|||
|
*y1 = text->y;
|
|||
|
|
|||
|
if (text->clip) {
|
|||
|
width = text->clip_width;
|
|||
|
height = text->clip_height;
|
|||
|
} else {
|
|||
|
width = text->max_width / item->canvas->pixels_per_unit;
|
|||
|
height = text->height / item->canvas->pixels_per_unit;
|
|||
|
}
|
|||
|
|
|||
|
switch (text->anchor) {
|
|||
|
case GTK_ANCHOR_NW:
|
|||
|
case GTK_ANCHOR_W:
|
|||
|
case GTK_ANCHOR_SW:
|
|||
|
break;
|
|||
|
|
|||
|
case GTK_ANCHOR_N:
|
|||
|
case GTK_ANCHOR_CENTER:
|
|||
|
case GTK_ANCHOR_S:
|
|||
|
*x1 -= width / 2.0;
|
|||
|
break;
|
|||
|
|
|||
|
case GTK_ANCHOR_NE:
|
|||
|
case GTK_ANCHOR_E:
|
|||
|
case GTK_ANCHOR_SE:
|
|||
|
*x1 -= width;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
switch (text->anchor) {
|
|||
|
case GTK_ANCHOR_NW:
|
|||
|
case GTK_ANCHOR_N:
|
|||
|
case GTK_ANCHOR_NE:
|
|||
|
break;
|
|||
|
|
|||
|
case GTK_ANCHOR_W:
|
|||
|
case GTK_ANCHOR_CENTER:
|
|||
|
case GTK_ANCHOR_E:
|
|||
|
*y1 -= height / 2.0;
|
|||
|
break;
|
|||
|
|
|||
|
case GTK_ANCHOR_SW:
|
|||
|
case GTK_ANCHOR_S:
|
|||
|
case GTK_ANCHOR_SE:
|
|||
|
*y1 -= height;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
*x2 = *x1 + width;
|
|||
|
*y2 = *y1 + height;
|
|||
|
}
|