Re: pango_layout_set_width() versus measured widths

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

 



I've now pushed a fix to pango master. I'll put in the next stable release also if/when that happens.


http://git.gnome.org/browse/pango/commit/?id=2cd9c4b416cbe55dd68106003f360e861a6722be


Thanks,
behdad

On 12/22/2009 11:13 PM, Ben Pfaff wrote:
In working with Pango I found an oddity that I do not understand.
It may be a bug, or it might just be my misunderstanding.

As part of a table layout procedure for printing, my code wishes
to find out the width of the longest word in a Pango layout, so
it sets the width of the layout to 1, turns on word wrapping, and
measures the width of the layout, something like this:

         pango_layout_set_width (layout, 1);
         pango_layout_set_wrap (layout, PANGO_WRAP_WORD);
         pango_layout_get_size (layout,&width, NULL);

Later on, the width of the table column might have been adjusted
upward or downward for other reasons, so it renders it with
PANGO_WRAP_WORD_CHAR to prevent overflowing the column
boundary.  I was surprised to discover that, when the layout
width is set to the same value returned by
pango_layout_get_size(), this caused some words to wrap anyhow.

I'm enclosing a simple example program.  You can invoke it to
measure the size of rendering "A string of text" with a width of
1 and word-wrapping, as above, e.g. showing input, output, and
an ASCII rendering of the produced foo.pdf:

         # ./a.out "A string of text" 1 word
         size: width=47032
         extents: ink width=45416, logical width=47032
         pixel extents: ink width=45, logical width=46

         +------+
         |A     |
         |string|
         |of    |
         |text  |
         +------+

Then giving the exact width reported by this run, plus word-char,
yields:

         # ./a.out "A string of text" 47032 word-char
         size: width=36632
         extents: ink width=35112, logical width=36632
         pixel extents: ink width=35, logical width=36

         +-----+
         |A    |
         |strin|
         |g of |
         |text |
         +-----+

To get word-char to produce the results that I expect, I have to
add 5208, which is the reported width of " ":

         # ./a.out "A string of text" 52240 word-char
         size: width=47032
         extents: ink width=45416, logical width=47032
         pixel extents: ink width=45, logical width=46

         +------+
         |A     |
         |string|
         |of    |
         |text  |
         +------+

Any guidance would be appreciated.  I can always add the width of
a space myself, but I don't understand why it is necessary.

Here is my test program:

#include<pango/pangocairo.h>
#include<cairo/cairo-pdf.h>
#include<cairo/cairo.h>
#include<stdlib.h>
#include<string.h>

int
main (int argc, char **argv)
{
   cairo_t *cr;
   char *filename;
   cairo_status_t status;
   cairo_surface_t *surface;
   PangoLayout *layout;
   PangoFontDescription *desc;
   PangoRectangle ink, logical;
   int width;

   if (argc != 4)
     {
       g_printerr ("Usage: pangocairo STRING WIDTH WRAP_MODE\n");
       return 1;
     }

   /* Create surface and clear to all-white. */
   surface = cairo_pdf_surface_create ("foo.pdf", 200, 200);
   cr = cairo_create (surface);
   cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
   cairo_paint (cr);

   /* Create Pango layout. */
   layout = pango_cairo_create_layout (cr);
   desc = pango_font_description_from_string ("Sans 12");
   pango_layout_set_font_description (layout, desc);
   pango_font_description_free (desc);
   pango_layout_set_text (layout, argv[1], -1);

   /* Set Pango options according to command line. */
   pango_layout_set_width (layout, atoi (argv[2]));
   if (!strcmp (argv[3], "word"))
     pango_layout_set_wrap (layout, PANGO_WRAP_WORD);
   else if (!strcmp (argv[3], "char"))
     pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
   else if (!strcmp (argv[3], "word-char"))
     pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
   else
     {
       g_printerr ("WRAP_MODE must be 'word' or 'char' or 'word-char'");
       return 1;
     }

   /* Draw layout. */
   cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
   cairo_move_to (cr, 0, 0);
   pango_cairo_show_layout (cr, layout);

   /* Print various sizes. */
   pango_layout_get_size (layout,&width, NULL);
   printf ("size: width=%d\n", width);

   pango_layout_get_extents (layout,&ink,&logical);
   printf ("extents: ink width=%d, logical width=%d\n",
           ink.width, logical.width);

   pango_layout_get_pixel_extents (layout,&ink,&logical);
   printf ("pixel extents: ink width=%d, logical width=%d\n",
           ink.width, logical.width);

   /* Clean up. */
   g_object_unref (layout);

   cairo_destroy (cr);

   cairo_surface_finish (surface);
   status = cairo_surface_status (surface);
   cairo_surface_destroy (surface);

   if (status != CAIRO_STATUS_SUCCESS)
     {
       g_printerr ("Could not save pdf to '%s'\n", filename);
       return 1;
     }

   return 0;
}
--
Ben Pfaff
http://benpfaff.org

_______________________________________________
gtk-list mailing list
gtk-list@xxxxxxxxx
http://mail.gnome.org/mailman/listinfo/gtk-list

_______________________________________________
gtk-list mailing list
gtk-list@xxxxxxxxx
http://mail.gnome.org/mailman/listinfo/gtk-list

[Index of Archives]     [Touch Screen Library]     [GIMP Users]     [Gnome]     [KDE]     [Yosemite News]     [Steve's Art]

  Powered by Linux