Pango layout performance with set_height



I'm one of the developers for Miro (getmiro.com) and I'm trying to
work on performance issues.  I think I've identified one issue, which
is that pango seems to be slow when laying out text that goes below
the bottom of its height.

For example, suppose I have a very large portion of text, but I want
to render it in a 50px tall area.  I call pango_layout_set_text() with
the long text, then pango_layout_set_height()
pango_layout_set_width(), and pango_layout_set_ellipsize().  Then when
I call pango_cairo_show_layout(), pango_layout_get_lines(), or any
other function that requires pango to lay out the text, it seems to
take a long time, even if the width and height are very small.  I'm
not sure what's happening, but it seems that pango is layout out text
and/or generating glyphs that won't be shown.

Attached is a small C program that gets at what I'm saying.  Whether I
use the long text or the short text, the performance should be
similar, since pango only needs to render 1 line of it in either case.
 However, rendering the long text takes significantly longer than the
short text (5-7 times longer).

Is there anyway that I can speed up rendering when much of my text is
below the bottom of the PangoLayout height?

Ben
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <pango/pango.h>
#include <string.h>

static int first_expose = 1;

static char long_text[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
    "Proin congue magna a libero tincidunt porttitor. Suspendisse tellus "
    "urna, suscipit ut venenatis quis, feugiat a diam. Phasellus venenatis "
    "sagittis nisl, vitae molestie mi faucibus sit amet. In luctus neque "
    "quis nisi condimentum id scelerisque enim commodo. Phasellus neque "
    "risus, porttitor sed venenatis ut, viverra ac ante. Phasellus magna "
    "diam, posuere vitae vehicula vel, accumsan eget lectus. Phasellus in "
    "lectus in risus dapibus convallis laoreet accumsan odio. Morbi eu nisi "
    "sed magna convallis imperdiet. Curabitur at elementum urna. Etiam in "
    "erat vitae neque lacinia ornare. Curabitur a semper nisi. Quisque "
    "volutpat dui et augue congue in interdum nunc ullamcorper. Cum sociis "
    "natoque penatibus et magnis dis parturient montes, nascetur ridiculus "
    "mus. Fusce luctus erat a nulla suscipit commodo. Sed sem tellus, "
    "vehicula quis pharetra eget, rhoncus accumsan justo. Aliquam fringilla "
    "sapien adipiscing sem varius adipiscing. Vestibulum iaculis est id "
    "augue ullamcorper et fringilla lorem ultrices. Donec at faucibus purus. "
    "\n\n"
    "Mauris dapibus, arcu vel consequat ultricies, lectus nisi porta nunc, "
    "iaculis sagittis elit diam ut felis. Integer nec sagittis libero. "
    "Mauris semper, enim et porttitor sodales, massa diam convallis ipsum, "
    "sed tincidunt libero dui at eros. Etiam id nulla in dolor lobortis "
    "fermentum vel et arcu. Praesent eu nisi quis lorem auctor gravida eget "
    "quis ante.  Mauris condimentum, eros sit amet eleifend pretium, ipsum "
    "purus suscipit metus, vel ullamcorper ipsum est sed velit.  Vestibulum "
    "ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia "
    "Curae; Suspendisse ac rhoncus magna. Fusce at nisl libero, quis viverra "
    "nibh. Aliquam gravida odio id arcu viverra id luctus velit facilisis. "
    "Mauris dictum consectetur nunc eget sagittis.  Suspendisse et enim ac "
    "mi hendrerit scelerisque ut eu quam. "
    "\n\n"
    "Aenean id felis risus. Proin aliquet mollis vulputate. Aliquam rhoncus "
    "convallis risus, sed commodo diam dictum et. Fusce mattis pellentesque "
    "metus sit amet ultricies. Phasellus turpis dolor, commodo et dignissim "
    "quis, posuere quis turpis. Nulla faucibus, dui vel aliquam ullamcorper, "
    "tellus odio semper mi, pretium molestie orci arcu in diam. Nam in metus "
    "felis. Nunc interdum, urna sed ullamcorper elementum, augue mauris "
    "hendrerit quam, at sagittis nibh magna molestie sapien. Mauris feugiat "
    "commodo auctor. Sed et ipsum ut neque consequat cursus vel et urna. "
    "Phasellus in mauris metus, sit amet rhoncus est. Phasellus blandit, "
    "eros vel iaculis ornare, neque augue dignissim lectus, at semper dui "
    "ligula ut eros. In hac habitasse platea dictumst. Proin accumsan mauris "
    "id turpis laoreet eget tempor elit semper. Pellentesque porttitor "
    "sapien sit amet magna fringilla pulvinar. Pellentesque in dignissim "
    "nibh. Donec nulla augue, luctus id euismod id, interdum ornare nunc. ";

char short_text[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
    "Proin congue magna a libero tincidunt porttitor. Suspendisse tellus ";

// uncomment one of the following lines to switch between long/short text
// char *the_text = short_text;
char *the_text = long_text;

void timeit(gpointer data)
{
    int i;
    GtkWidget* widget = GTK_WIDGET(data);

    for(i = 0; i < 500; i++) {
        the_text[0] = 'a' + (i % 26);
        the_text[1] = 'A' + ((i / 26) % 26);
        gtk_widget_queue_draw(widget);
        gdk_window_process_updates(widget->window, TRUE);
    }
    gtk_main_quit();
}

gboolean on_expose (GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
    PangoContext* context;
    PangoLayout* layout;
    cairo_t* cr;

    cr = gdk_cairo_create(event->window);
    context = pango_cairo_create_context(cr);
    layout = pango_layout_new(context);
    pango_layout_set_width(layout, 200 * PANGO_SCALE);
    pango_layout_set_height(layout, 20 * PANGO_SCALE);
    pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
    pango_layout_set_text(layout, the_text, strlen(the_text));

    cairo_move_to(cr, 0.0, 0.0);
    pango_cairo_show_layout (cr, layout);

    if(first_expose) {
        g_idle_add((GSourceFunc) timeit, widget);
        first_expose = 0;
    }

    return TRUE;
}


int main(int argc, char** argv)
{
  gtk_init (&argc, &argv);

  GtkWidget *drawing_area = gtk_drawing_area_new();
  gtk_widget_set_size_request (drawing_area, 200, 200);
  g_signal_connect (G_OBJECT (drawing_area), "expose_event",
                    G_CALLBACK (on_expose), NULL);

  GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_container_add(GTK_CONTAINER(window), drawing_area);

  gtk_widget_show_all(GTK_WIDGET(window));


  gtk_main();
  return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]