"Fossies" - the Fresh Open Source Software Archive

Member "gtkdatabox-1.0.0/gtk/gtkdatabox_markers.c" (31 Mar 2021, 20503 Bytes) of package /linux/privat/gtkdatabox-1.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gtkdatabox_markers.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.9.3.1_vs_1.0.0.

    1 /* $Id: gtkdatabox_markers.c 4 2008-06-22 09:19:11Z rbock $ */
    2 /* GtkDatabox - An extension to the gtk+ library
    3  * Copyright (C) 1998 - 2008  Dr. Roland Bock
    4  *
    5  * This program is free software; you can redistribute it and/or
    6  * modify it under the terms of the GNU Lesser General Public License
    7  * as published by the Free Software Foundation; either version 2.1
    8  * of 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 Lesser General Public License for more details.
   14  * 
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program; if not, write to the Free Software
   17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   18  */
   19 
   20 #include <gtkdatabox_markers.h>
   21 #include <pango/pango.h>
   22 
   23 static void gtk_databox_markers_real_draw (GtkDataboxGraph * markers,
   24                       GtkDatabox* box);
   25 static cairo_t* gtk_databox_markers_real_create_gc (GtkDataboxGraph * graph,
   26                            GtkDatabox* box);
   27 
   28 /* IDs of properties */
   29 enum
   30 {
   31    PROP_TYPE = 1
   32 };
   33 
   34 
   35 typedef struct
   36 {
   37    GtkDataboxMarkersPosition position;  /* relative to data point */
   38    gchar *text;
   39    PangoLayout *label;      /* the label for markers */
   40    GtkDataboxMarkersTextPosition label_position;    /* position relative to markers */
   41    gboolean boxed;      /* label in a box? */
   42 }
   43 GtkDataboxMarkersInfo;
   44 
   45 /**
   46  * GtkDataboxMarkersPrivate:
   47  *
   48  * A private data structure used by the #GtkDataboxMarkers. It shields all internal things
   49  * from developers who are just using the object.
   50  *
   51  **/
   52 typedef struct _GtkDataboxMarkersPrivate GtkDataboxMarkersPrivate;
   53 
   54 struct _GtkDataboxMarkersPrivate
   55 {
   56    GtkDataboxMarkersType type;
   57    GtkDataboxMarkersInfo *markers_info;
   58    gint16 *xpixels;
   59    gint16 *ypixels;
   60    guint pixelsalloc;
   61 };
   62 
   63 G_DEFINE_TYPE_WITH_PRIVATE(GtkDataboxMarkers, gtk_databox_markers,
   64     GTK_DATABOX_TYPE_XYC_GRAPH)
   65 
   66 static void
   67 gtk_databox_markers_set_mtype (GtkDataboxMarkers * markers, gint type)
   68 {
   69    g_return_if_fail (GTK_DATABOX_IS_MARKERS (markers));
   70    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
   71    priv->type = type;
   72 
   73    g_object_notify (G_OBJECT (markers), "markers-type");
   74 }
   75 
   76 static void
   77 gtk_databox_markers_set_property (GObject * object,
   78                  guint property_id,
   79                  const GValue * value, GParamSpec * pspec)
   80 {
   81    GtkDataboxMarkers *markers = GTK_DATABOX_MARKERS (object);
   82 
   83    switch (property_id)
   84    {
   85    case PROP_TYPE:
   86       {
   87      gtk_databox_markers_set_mtype (markers, g_value_get_int (value));
   88       }
   89       break;
   90    default:
   91       /* We don't have any other property... */
   92       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
   93       break;
   94    }
   95 }
   96 
   97 static gint
   98 gtk_databox_markers_get_mtype (GtkDataboxMarkers * markers)
   99 {
  100    g_return_val_if_fail (GTK_DATABOX_IS_MARKERS (markers), 0);
  101    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
  102    return priv->type;
  103 }
  104 
  105 static void
  106 gtk_databox_markers_get_property (GObject * object,
  107                  guint property_id,
  108                  GValue * value, GParamSpec * pspec)
  109 {
  110    GtkDataboxMarkers *markers = GTK_DATABOX_MARKERS (object);
  111 
  112    switch (property_id)
  113    {
  114    case PROP_TYPE:
  115       {
  116      g_value_set_int (value, gtk_databox_markers_get_mtype (markers));
  117       }
  118       break;
  119    default:
  120       /* We don't have any other property... */
  121       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  122       break;
  123    }
  124 }
  125 
  126 static void
  127 markers_finalize (GObject * object)
  128 {
  129    GtkDataboxMarkers *markers = GTK_DATABOX_MARKERS (object);
  130    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
  131    int i;
  132    int len;
  133 
  134    len = gtk_databox_xyc_graph_get_length (GTK_DATABOX_XYC_GRAPH (markers));
  135 
  136    for (i = 0; i < len; ++i)
  137    {
  138       if (priv->markers_info[i].label)
  139      g_object_unref (priv->markers_info[i].label);
  140       if (priv->markers_info[i].text)
  141      g_free (priv->markers_info[i].text);
  142    }
  143    g_free (priv->markers_info);
  144    g_free (priv->xpixels);
  145    g_free (priv->ypixels);
  146 
  147    /* Chain up to the parent class */
  148    G_OBJECT_CLASS (gtk_databox_markers_parent_class)->finalize (object);
  149 }
  150 
  151 static cairo_t *
  152 gtk_databox_markers_real_create_gc (GtkDataboxGraph * graph,
  153                    GtkDatabox* box)
  154 {
  155    GtkDataboxMarkers *markers = GTK_DATABOX_MARKERS (graph);
  156    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
  157    cairo_t *cr;
  158    static const double dash = 5.0f;
  159 
  160    g_return_val_if_fail (GTK_DATABOX_IS_MARKERS (graph), NULL);
  161 
  162    cr = GTK_DATABOX_GRAPH_CLASS (gtk_databox_markers_parent_class)->create_gc (graph, box);
  163 
  164    if (cr)
  165    {
  166       if (priv->type == GTK_DATABOX_MARKERS_DASHED_LINE)
  167          cairo_set_dash (cr, &dash, 1, 0.0);
  168    }
  169 
  170    return cr;
  171 }
  172 
  173 static void
  174 gtk_databox_markers_class_init (GtkDataboxMarkersClass *klass)
  175 {
  176    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  177    GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS (klass);
  178    GParamSpec *markers_param_spec;
  179 
  180    gobject_class->set_property = gtk_databox_markers_set_property;
  181    gobject_class->get_property = gtk_databox_markers_get_property;
  182    gobject_class->finalize = markers_finalize;
  183 
  184    markers_param_spec = g_param_spec_int ("markers-type", "Type of markers", "Type of markers for this graph, e.g. triangles or lines", G_MININT, G_MAXINT, 0,  /*  default value */
  185                      G_PARAM_CONSTRUCT |
  186                      G_PARAM_READWRITE);
  187 
  188    g_object_class_install_property (gobject_class,
  189                     PROP_TYPE, markers_param_spec);
  190    graph_class->draw = gtk_databox_markers_real_draw;
  191    graph_class->create_gc = gtk_databox_markers_real_create_gc;
  192 }
  193 
  194 static void
  195 complete (GtkDataboxMarkers * markers)
  196 {
  197    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
  198    priv->markers_info =
  199       g_new0 (GtkDataboxMarkersInfo,
  200           gtk_databox_xyc_graph_get_length
  201           (GTK_DATABOX_XYC_GRAPH (markers)));
  202 
  203 }
  204 
  205 static void
  206 gtk_databox_markers_init (GtkDataboxMarkers *markers)
  207 {
  208    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
  209    priv->markers_info = NULL;
  210    priv->xpixels = NULL;
  211    priv->ypixels = NULL;
  212    priv->pixelsalloc = 0;
  213 
  214    g_signal_connect (markers, "notify::length", G_CALLBACK (complete), NULL);
  215 }
  216 
  217 /**
  218  * gtk_databox_markers_new:
  219  * @len: length of @X and @Y
  220  * @X: array of horizontal position values of markers
  221  * @Y: array of vertical position values of markers
  222  * @color: color of the markers
  223  * @size: marker size or line width (depending on the @type)
  224  * @type: type of markers (e.g. triangle or circle)
  225  *
  226  * Creates a new #GtkDataboxMarkers object which can be added to a #GtkDatabox widget as nice decoration for other graphs.
  227  *
  228  * Return value: A new #GtkDataboxMarkers object
  229  **/
  230 GtkDataboxGraph *
  231 gtk_databox_markers_new (guint len, gfloat * X, gfloat * Y,
  232             GdkRGBA * color, guint size,
  233             GtkDataboxMarkersType type)
  234 {
  235    GtkDataboxMarkers *markers;
  236    g_return_val_if_fail (X, NULL);
  237    g_return_val_if_fail (Y, NULL);
  238    g_return_val_if_fail ((len > 0), NULL);
  239 
  240    markers = g_object_new (GTK_DATABOX_TYPE_MARKERS,
  241               "X-Values", X,
  242               "Y-Values", Y,
  243               "xstart", 0,
  244               "ystart", 0,
  245               "xstride", 1,
  246               "ystride", 1,
  247               "xtype", G_TYPE_FLOAT,
  248               "ytype", G_TYPE_FLOAT,
  249               "length", len,
  250               "maxlen", len,
  251               "color", color,
  252               "size", size, "markers-type", type, NULL);
  253 
  254    return GTK_DATABOX_GRAPH (markers);
  255 }
  256 
  257 /**
  258  * gtk_databox_markers_new_full:
  259  * @maxlen: maximum length of @X and @Y
  260  * @len: actual number of @X and @Y values to plot
  261  * @X: array of horizontal position values of markers
  262  * @Y: array of vertical position values of markers
  263  * @xstart: the first element in the X array to plot (usually 0)
  264  * @ystart: the first element in the Y array to plot (usually 0)
  265  * @xstride: successive elements in the X array are separated by this much (1 if array, ncols if matrix)
  266  * @ystride: successive elements in the Y array are separated by this much (1 if array, ncols if matrix)
  267  * @xtype: the GType of the X array elements.  G_TYPE_FLOAT, G_TYPE_DOUBLE, etc.
  268  * @ytype: the GType of the Y array elements.  G_TYPE_FLOAT, G_TYPE_DOUBLE, etc.
  269  * @color: color of the markers
  270  * @size: marker size or line width (depending on the @type)
  271  * @type: type of markers (e.g. triangle or circle)
  272  *
  273  * Creates a new #GtkDataboxMarkers object which can be added to a #GtkDatabox widget as nice decoration for other graphs.
  274  *
  275  * Return value: A new #GtkDataboxMarkers object
  276  **/
  277 GtkDataboxGraph *
  278 gtk_databox_markers_new_full (guint maxlen, guint len,
  279             void * X, guint xstart, guint xstride, GType xtype,
  280             void * Y, guint ystart, guint ystride, GType ytype,
  281             GdkRGBA * color, guint size,
  282             GtkDataboxMarkersType type)
  283 {
  284    GtkDataboxMarkers *markers;
  285    g_return_val_if_fail (X, NULL);
  286    g_return_val_if_fail (Y, NULL);
  287    g_return_val_if_fail ((len > 0), NULL);
  288 
  289    markers = g_object_new (GTK_DATABOX_TYPE_MARKERS,
  290               "X-Values", X,
  291               "Y-Values", Y,
  292               "xstart", xstart,
  293               "ystart", ystart,
  294               "xstride", xstride,
  295               "ystride", ystride,
  296               "xtype", xtype,
  297               "ytype", ytype,
  298               "length", len,
  299               "maxlen", maxlen,
  300               "color", color,
  301               "size", size, "markers-type", type, NULL);
  302 
  303    return GTK_DATABOX_GRAPH (markers);
  304 }
  305 
  306 static gint
  307 gtk_databox_label_write_at (cairo_t *cr,
  308                 PangoLayout * pl,
  309                 GdkPoint coord,
  310                 GtkDataboxMarkersTextPosition position,
  311                 gint distance, gboolean boxed)
  312 {
  313    gint hdist_text;
  314    gint vdist_text;
  315    gint hdist_box;
  316    gint vdist_box;
  317 
  318    gint width;
  319    gint height;
  320 
  321    gint offset = (boxed) ? 2 : 0;
  322 
  323    pango_layout_get_pixel_size (pl, &width, &height);
  324 
  325    switch (position)
  326    {
  327    case GTK_DATABOX_MARKERS_TEXT_N:
  328       hdist_text = -width / 2;
  329       vdist_text = -distance - offset - height;
  330       hdist_box = hdist_text - offset;
  331       vdist_box = vdist_text - offset;
  332       break;
  333    case GTK_DATABOX_MARKERS_TEXT_NE:
  334       hdist_text = +distance + offset;
  335       vdist_text = -distance - offset - height;
  336       hdist_box = hdist_text - offset;
  337       vdist_box = vdist_text - offset;
  338       break;
  339    case GTK_DATABOX_MARKERS_TEXT_E:
  340       hdist_text = +distance + offset;
  341       vdist_text = -height / 2;
  342       hdist_box = hdist_text - offset;
  343       vdist_box = vdist_text - offset;
  344       break;
  345    case GTK_DATABOX_MARKERS_TEXT_SE:
  346       hdist_text = +distance + offset;
  347       vdist_text = +distance + offset;
  348       hdist_box = hdist_text - offset;
  349       vdist_box = vdist_text - offset;
  350       break;
  351    case GTK_DATABOX_MARKERS_TEXT_S:
  352       hdist_text = -width / 2;
  353       vdist_text = +distance + offset;
  354       hdist_box = hdist_text - offset;
  355       vdist_box = vdist_text - offset;
  356       break;
  357    case GTK_DATABOX_MARKERS_TEXT_SW:
  358       hdist_text = -distance - offset - width;
  359       vdist_text = +distance + offset;
  360       hdist_box = hdist_text - offset;
  361       vdist_box = vdist_text - offset;
  362       break;
  363    case GTK_DATABOX_MARKERS_TEXT_W:
  364       hdist_text = -distance - offset - width;
  365       vdist_text = -height / 2;
  366       hdist_box = hdist_text - offset;
  367       vdist_box = vdist_text - offset;
  368       break;
  369    case GTK_DATABOX_MARKERS_TEXT_NW:
  370       hdist_text = -distance - offset - width;
  371       vdist_text = -distance - offset - height;
  372       hdist_box = hdist_text - offset;
  373       vdist_box = vdist_text - offset;
  374       break;
  375    default:
  376       hdist_text = -width / 2;
  377       vdist_text = -height / 2;
  378       hdist_box = hdist_text - offset;
  379       vdist_box = vdist_text - offset;
  380    }
  381 
  382 
  383    cairo_move_to(cr, coord.x + hdist_text, coord.y + vdist_text);
  384    pango_cairo_show_layout(cr, pl);
  385 
  386    if (boxed) {
  387       cairo_save (cr);
  388       cairo_set_line_width (cr, 1.0);
  389       cairo_set_dash (cr, NULL, 0, 0.0);
  390       cairo_rectangle (cr, coord.x + hdist_box - 0.5,
  391               coord.y + vdist_box - 0.5, width + 3.5, height + 3.5);
  392       cairo_stroke(cr);
  393       cairo_restore(cr);
  394     }
  395 
  396    return (0);
  397 }
  398 
  399 static void
  400 gtk_databox_markers_real_draw (GtkDataboxGraph * graph,
  401                   GtkDatabox* box)
  402 {
  403    GtkWidget *widget;
  404    GtkDataboxMarkers *markers = GTK_DATABOX_MARKERS (graph);
  405    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
  406    GdkPoint points[3];
  407    PangoContext *context;
  408    void *X;
  409    void *Y;
  410    guint len, maxlen;
  411    gint16 x;
  412    gint16 y;
  413    gint16 widget_width;
  414    gint16 widget_height;
  415    GdkPoint coord;
  416    gint size;
  417    guint i;
  418    cairo_t *cr;
  419    GtkAllocation allocation;
  420    gint16 *xpixels, *ypixels;
  421    guint xstart, xstride, ystart, ystride;
  422    GType xtype, ytype;
  423 
  424    g_return_if_fail (GTK_DATABOX_IS_MARKERS (markers));
  425    g_return_if_fail (GTK_IS_DATABOX (box));
  426 
  427    widget = GTK_WIDGET(box);
  428    gtk_widget_get_allocation(widget, &allocation);
  429 
  430    context = gtk_widget_get_pango_context(widget);
  431 
  432    len = gtk_databox_xyc_graph_get_length (GTK_DATABOX_XYC_GRAPH (graph));
  433    maxlen = gtk_databox_xyc_graph_get_maxlen (GTK_DATABOX_XYC_GRAPH (graph));
  434 
  435    if (priv->pixelsalloc < len)
  436    {
  437     priv->pixelsalloc = len;
  438     priv->xpixels = (gint16 *)g_realloc(priv->xpixels, len * sizeof(gint16));
  439     priv->ypixels = (gint16 *)g_realloc(priv->ypixels, len * sizeof(gint16));
  440    }
  441 
  442    xpixels = priv->xpixels;
  443    ypixels = priv->ypixels;
  444 
  445    X = gtk_databox_xyc_graph_get_X (GTK_DATABOX_XYC_GRAPH (graph));
  446    xstart = gtk_databox_xyc_graph_get_xstart (GTK_DATABOX_XYC_GRAPH (graph));
  447    xstride = gtk_databox_xyc_graph_get_xstride (GTK_DATABOX_XYC_GRAPH (graph));
  448    xtype = gtk_databox_xyc_graph_get_xtype (GTK_DATABOX_XYC_GRAPH (graph));
  449    gtk_databox_values_to_xpixels(box, xpixels, X, xtype, maxlen, xstart, xstride, len);
  450 
  451    Y = gtk_databox_xyc_graph_get_Y (GTK_DATABOX_XYC_GRAPH (graph));
  452    ystart = gtk_databox_xyc_graph_get_ystart (GTK_DATABOX_XYC_GRAPH (graph));
  453    ystride = gtk_databox_xyc_graph_get_ystride (GTK_DATABOX_XYC_GRAPH (graph));
  454    ytype = gtk_databox_xyc_graph_get_ytype (GTK_DATABOX_XYC_GRAPH (graph));
  455    gtk_databox_values_to_ypixels(box, ypixels, Y, ytype, maxlen, ystart, ystride, len);
  456 
  457    size = gtk_databox_graph_get_size (graph);
  458 
  459    widget_width = allocation.width;
  460    widget_height = allocation.height;
  461 
  462    cr = gtk_databox_graph_create_gc (graph, box);
  463 
  464     for (i = 0; i < len; ++i)
  465     {
  466         coord.x = x = xpixels[i];
  467         coord.y = y = ypixels[i];
  468 
  469         switch (priv->type)
  470         {
  471             case GTK_DATABOX_MARKERS_TRIANGLE:
  472                 switch (priv->markers_info[i].position)
  473                 {
  474                     case GTK_DATABOX_MARKERS_C:
  475                         y = y - size / 2;
  476                         points[0].x = x;
  477                         points[0].y = y;
  478                         points[1].x = x - size / 2;
  479                         points[1].y = y + size;
  480                         points[2].x = x + size / 2;
  481                         points[2].y = y + size;
  482                         break;
  483 
  484                     case GTK_DATABOX_MARKERS_N:
  485                         coord.y = y - 2 - size / 2;
  486                         y = y - 2;
  487                         points[0].x = x;
  488                         points[0].y = y;
  489                         points[1].x = x - size / 2;
  490                         points[1].y = y - size;
  491                         points[2].x = x + size / 2;
  492                         points[2].y = y - size;
  493                         break;
  494 
  495                     case GTK_DATABOX_MARKERS_E:
  496                         coord.x = x + 2 + size / 2;
  497                         x = x + 2;
  498                         points[0].x = x;
  499                         points[0].y = y;
  500                         points[1].x = x + size;
  501                         points[1].y = y + size / 2;
  502                         points[2].x = x + size;
  503                         points[2].y = y - size / 2;
  504                         break;
  505 
  506                     case GTK_DATABOX_MARKERS_S:
  507                         coord.y = y + 2 + size / 2;
  508                         y = y + 2;
  509                         points[0].x = x;
  510                         points[0].y = y;
  511                         points[1].x = x - size / 2;
  512                         points[1].y = y + size;
  513                         points[2].x = x + size / 2;
  514                         points[2].y = y + size;
  515                         break;
  516 
  517                     case GTK_DATABOX_MARKERS_W:
  518                     default:
  519                         coord.x = x - 2 - size / 2;
  520                         x = x - 2;
  521                         points[0].x = x;
  522                         points[0].y = y;
  523                         points[1].x = x - size;
  524                         points[1].y = y + size / 2;
  525                         points[2].x = x - size;
  526                         points[2].y = y - size / 2;
  527                         break;
  528                 }
  529                 cairo_move_to(cr, points[0].x + 0.5, points[0].y + 0.5);
  530                 cairo_line_to(cr, points[1].x + 0.5, points[1].y + 0.5);
  531                 cairo_line_to(cr, points[2].x + 0.5, points[2].y + 0.5);
  532                 cairo_close_path  (cr);
  533                 cairo_fill(cr);
  534                 break;
  535                 /* End of GTK_DATABOX_MARKERS_TRIANGLE */
  536 
  537                 case GTK_DATABOX_MARKERS_SOLID_LINE:
  538                 case GTK_DATABOX_MARKERS_DASHED_LINE:
  539                 switch (priv->markers_info[i].position)
  540                 {
  541                     case GTK_DATABOX_MARKERS_C:
  542                         points[0].x = x;
  543                         points[0].y = 0;
  544                         points[1].x = x;
  545                         points[1].y = widget_height;
  546                         break;
  547 
  548                     case GTK_DATABOX_MARKERS_N:
  549                         points[0].x = x;
  550                         points[0].y = 0;
  551                         points[1].x = x;
  552                         points[1].y = widget_height;
  553                         break;
  554 
  555                     case GTK_DATABOX_MARKERS_E:
  556                         points[0].x = 0;
  557                         points[0].y = y;
  558                         points[1].x = widget_width;
  559                         points[1].y = y;
  560                         break;
  561 
  562                     case GTK_DATABOX_MARKERS_S:
  563                         points[0].x = x;
  564                         points[0].y = 0;
  565                         points[1].x = x;
  566                         points[1].y = widget_height;
  567                         break;
  568 
  569                     case GTK_DATABOX_MARKERS_W:
  570                     default:
  571                         points[0].x = 0;
  572                         points[0].y = y;
  573                         points[1].x = widget_width;
  574                         points[1].y = y;
  575                         break;
  576                 }
  577                 cairo_move_to(cr, points[0].x + 0.5, points[0].y + 0.5);
  578                 cairo_line_to(cr, points[1].x + 0.5, points[1].y + 0.5);
  579                 cairo_stroke(cr);
  580 
  581                 break;
  582                 /* End of GTK_DATABOX_MARKERS_LINE */
  583 
  584                 case GTK_DATABOX_MARKERS_NONE:
  585                 default:
  586                     break;
  587         }
  588 
  589       if (priv->markers_info[i].text)
  590       {
  591         if (!priv->markers_info[i].label)
  592         {
  593             priv->markers_info[i].label =
  594             pango_layout_new (context);
  595             pango_layout_set_text (priv->markers_info[i].label,
  596             priv->markers_info[i].text, -1);
  597         }
  598 
  599      if (priv->type == GTK_DATABOX_MARKERS_SOLID_LINE
  600          || priv->type == GTK_DATABOX_MARKERS_DASHED_LINE)
  601      {
  602         gint width;
  603         gint height;
  604         pango_layout_get_pixel_size (priv->markers_info[i].label,
  605                      &width, &height);
  606 
  607         width = (width + 1) / 2 + 2;
  608         height = (height + 1) / 2 + 2;
  609         size = 0;
  610 
  611         switch (priv->markers_info[i].position)
  612         {
  613         case GTK_DATABOX_MARKERS_C:
  614            break;
  615         case GTK_DATABOX_MARKERS_N:
  616            coord.y = height;
  617            break;
  618         case GTK_DATABOX_MARKERS_E:
  619            coord.x = widget_width - width;
  620            break;
  621         case GTK_DATABOX_MARKERS_S:
  622            coord.y = widget_height - height;
  623            break;
  624         case GTK_DATABOX_MARKERS_W:
  625            coord.x = width;
  626            break;
  627         }
  628      }
  629 
  630      gtk_databox_label_write_at (cr,
  631                      priv->markers_info[i].label,
  632                      coord,
  633                      priv->markers_info[i].
  634                      label_position, (size + 1) / 2 + 2,
  635                      priv->markers_info[i].boxed);
  636       }
  637    }
  638 
  639    cairo_destroy(cr);
  640    return;
  641 }
  642 
  643 /**
  644  * gtk_databox_markers_set_position:
  645  * @markers: A #GtkDataboxMarkers object
  646  * @index: index within the array of X/Y values
  647  * @position: position of the marker (e.g. circle or triangle relative to their X/Y value
  648  *
  649  * Sets a position for one of the markers.
  650  **/
  651 void
  652 gtk_databox_markers_set_position (GtkDataboxMarkers * markers,
  653                  guint index,
  654                  GtkDataboxMarkersPosition position)
  655 {
  656    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
  657    guint len;
  658 
  659    g_return_if_fail (GTK_DATABOX_IS_MARKERS (markers));
  660    len = gtk_databox_xyc_graph_get_length (GTK_DATABOX_XYC_GRAPH (markers));
  661    g_return_if_fail (index < len);
  662 
  663    priv->markers_info[index].position = position;
  664 }
  665 
  666 /**
  667  * gtk_databox_markers_set_label:
  668  * @markers: A #GtkDataboxMarkers object
  669  * @index: index within the array of X/Y values
  670  * @label_position: position of the label relative to the marker
  671  * @text: text to be displayed in the label
  672  * @boxed: Whether the label is to be enclosed in a box (true) or not (false)
  673  *
  674  * Sets a label for one of the markers.
  675  **/
  676 void
  677 gtk_databox_markers_set_label (GtkDataboxMarkers * markers,
  678                   guint index,
  679                   GtkDataboxMarkersTextPosition label_position,
  680                   gchar * text, gboolean boxed)
  681 {
  682    GtkDataboxMarkersPrivate *priv = gtk_databox_markers_get_instance_private (markers);
  683    guint len;
  684 
  685    g_return_if_fail (GTK_DATABOX_IS_MARKERS (markers));
  686    len = gtk_databox_xyc_graph_get_length (GTK_DATABOX_XYC_GRAPH (markers));
  687    g_return_if_fail (index < len);
  688 
  689    priv->markers_info[index].label_position = label_position;
  690    if (priv->markers_info[index].text)
  691       g_free (priv->markers_info[index].text);
  692    priv->markers_info[index].text = g_strdup (text);
  693    priv->markers_info[index].boxed = boxed;
  694 
  695    if (priv->markers_info[index].label)
  696    {
  697       pango_layout_set_text (priv->markers_info[index].label,
  698                  priv->markers_info[index].text, -1);
  699    }
  700 }