GNOME Bugzilla – Bug 642655
Printing a wide PangoLayoutLine, words at the end of the line are dropped
Last modified: 2011-02-23 01:06:39 UTC
This problem happens only in Windows - in Linux the same app prints the full line properly. I have an app that prints a page in landscape format and with narrow margins. I set the margins to 0.25" via gtk_page_setup_set_top_margin() etc. I then draw the grid up to those margins and it all prints fine, all the way up to the margins. But when I print text onto the page, words at the right side are dropped and not printed, even though they are well inside the right 0.25" margin. It looks like words that would end within about 0.75" of the right-edge don't get printed. My "draw-page" signal handler needs to print each line individually so it uses pango_layout_get_line_readonly() to pull the lines out of the layout one by one, and pango_cairo_show_layout_line() to draw each. Some debug g_print statements show that the PangoLayoutLine passed to pango_cairo_show_layout_line() does contain the full text, but pango_cairo_show_layout_line() does not print all of it, dropping words from the end of the longer lines. I wondered if the problem could be due to word-wrap since it seems to drop entire words, but adding a call to pango_layout_set_width to make sure wrap is off (width=-1) and setting the layout wrap mode to PANGO_WRAP_CHAR had no effect.
Created attachment 181193 [details] Test program that shows the problem I've attached a small test program that shows the problem. It prints a page to the printer in landscape format with 0.25" margins and draws lines in a border just inside the margins. Then it prints the word "Test" 5 times at tab stops every 2.5", so the 5th word should print 10" across the 10.5" printable width. Compiling and running it in Linux all 5 words are printed. Doing the same in Windows only the first 4 are printed and the last is dropped. Printing on paper and measuring with a ruler shows the words printed at exactly the correct positions and there is space to print the 5th one within the margin.
I've just spent some time debugging this and it turns out to be a Cairo bug. The bug is in function cairo_win32_printing_surface_create() in cairo_win32_printing_surface.c which sets up surface->extents.width and surface->extents.height from a call to the Windows API GetClipBox() function. That returns the extents correct for portrait orientation, but does not swap them around when printing in landscape (GetClipBox returns the same in both cases). So when printing to an 8.5" x 11" sheet in landscape mode _cairo_gstate_transform_glyphs_to_backend() gets the width as 8.5" and drops glyphs outside that (plus a safety margin). What I'm not sure of is how to fix it. I think that cairo_win32_printing_surface_create() needs to swap the width/height when the printer mode is landscape, but I can't find a way to get at that. I think it is provided by the Windows API DocumentProperties() function, but DocumentProperties is not supported in the GNU Win32 API. This should probably be closed and entered as a Cairo bug, but unless we can find a way to Cairo to get at the printer orientation it could require a call from GTK to Cairo to set that, so I would leave it open here for now.
This turned out to be caused by an error in my app which is duplicated in the attached test program. It needs to set landscape printing and does so in the "begin-print" handler. That is not the correct place to do it and by this time the Windows hDC has already been created with the print settings from the printer dialog, which sets portrait orientation unless the user changes it. Hence we end up with GTK/Cairo printing in landscape format onto an hDC that was created for portrait orientation. Changing the attached test program (and my app) to set landscape orientation in its startPrint() function before calling gtk_print_operation_run() fixes it to work properly. Closing this as not a bug.