GNOME Bugzilla – Bug 671895
gtk_print_context_get_hard_margins needs to take into account page orientation
Last modified: 2018-05-02 15:21:22 UTC
Created attachment 209475 [details] [review] rotate hard margins to match page orientation Patch to fix attached.
Review of attachment 209475 [details] [review]: Thank you for the patch. I tested the patch and it seems to me that you need to fix returned width in gtk_page_setup_get_page_width() and height in gtk_page_setup_get_page_height() yet (make the used margins aware of the orientation). Another problem is the translation in _gtk_print_context_reverse_according_to_orientation(). This needs to accommodate the orientation too. I'll attach the mentioned changes soon. Could you merge them to your patch, fix the indentation and attach it here? I'll review it soon (I promise). ::: gtk/gtkprintcontext.c @@ +502,3 @@ + *right = context->hard_margin_bottom / context->pixels_per_unit_y; + break; + } Fix the indentation of the switch please.
Created attachment 292001 [details] [review] the modifications
Thinking more about this, gtk_print_context_get_hard_margins() returns hardware printer margins and not context margins. We shouldn't change this. Instead, we can add new function gtk_print_context_get_margins() which would return oriented margins (margins of the context).
As it has been a long time since I last looked at his so I spent some time studying how the hard margins code works. The first thing I noticed is that the PPD file lists the printable area for each page size using *ImageableArea eg *ImageableArea Letter/Letter: "12.24 12.06 599.76 780.06" *ImageableArea LetterSmall/Letter (Small): "30.00 31.00 582.00 761.00" *ImageableArea Legal/Legal: "12.24 12.06 599.76 996.06" *ImageableArea LegalSmall/Legal (Small): "64.00 54.00 548.00 954.00" *ImageableArea Executive/Executive: "13.32 12.06 508.68 744.06" *ImageableArea A4/A4: "13.44 12.06 581.76 829.74" *ImageableArea A4Small/A4 (Small): "28.00 30.00 566.00 811.00" and lists the hard margins for custom pages sizes with *HWMargins. eg *HWMargins: 16 16 16 16 Looking a the code it seems the margins returned bv gtk_printer_list_papers() is the imageable area and gtk_printer_get_hard_margins() returns the custom page size non printable area (HWMargins). This should be better documented. In gtk_print_context on unix the hard margins are always using the HWMargins values. This should be fixed to use the imageable area for the selected page size or HWMargins if it is a custom page sizes. The gtk_print_context hard margins should take into account the print context. eg if the margins on the print context are larger than the non printable area, the print context hard margins should return 0. If the context is set to full page the hard margins returned should match the gtkprinter values. So we should probably add a new gtk_print_context function that implements this correctly.
(In reply to comment #4) > In gtk_print_context on unix the hard margins are always using the HWMargins > values. This should be fixed to use the imageable area for the selected page > size or HWMargins if it is a custom page sizes. The problem here is that if you select a PageSetup of a printer and then select another printer, the used PageSetup will be the selected one with imageable area of the previous printer (I'll check GtkPrintContext for this eventuality and use context->hard_margin_* / gtk_page_setup_get_* as needed). Since PPD spec says that ImageableArea provides the same information as HWMargins but in different form, it should be ok to use it the way gtk+ use it.
Created attachment 292688 [details] [review] add gtk_print_context_get_printable_margins If the hard margins vary by paper size, HWMargins provides largest margin required by the printer which may be larger than necessary for some page sizes. I've attached a new patch. In addition to including the previous patch + fixes, I have added a new function gtk_print_context_get_printable_margins() that returns the hard margins of the print context. ie it is oriented to the context and if full page is disabled, the hard margins exclude the context margins. I've also fixed an bug in the gtkprintoperation-win32. The hard margins in win32 are already oriented to the context so this needs to be undone. I have not tested the win32 changes as I don't currently have a win32 build environment setup for gtk.
Review of attachment 292688 [details] [review]: I'm sorry for my late response, I was thinking about the best solution for this. (In reply to comment #5) > The problem here is that if you select a PageSetup of a printer and then select > another printer, the used PageSetup will be the selected one with imageable > area of the previous printer (I'll check GtkPrintContext for this eventuality > and use context->hard_margin_* / gtk_page_setup_get_* as needed). This is a bug. My intention was to change the GtkPageSetup to the one provided by the newly selected printer if it is compatible (the same one or at least the same paper size). I'll file a bug for this with a patch. ::: gtk/gtkpagesetup.c @@ +524,3 @@ + else + height -= setup->left_margin + setup->right_margin; + I've pushed this to master already since it is obvious that GtkPageSetup margins are not oriented while results of gtk_page_setup_get_paper_*() are. ::: gtk/gtkprintcontext.c @@ +347,3 @@ cairo_translate (context->cr, + dx * context->surface_dpi_x / context->pixels_per_unit_x, + dy * context->surface_dpi_y / context->pixels_per_unit_y); I've pushed this one to master too. @@ +353,3 @@ _gtk_print_context_set_page_setup (GtkPrintContext *context, + GtkPageSetup *page_setup, + gboolean full_page) You don't need this since you can use "context->op->priv->use_full_page" if needed. @@ +555,3 @@ + page_bottom = gtk_page_setup_get_bottom_margin (context->page_setup, GTK_UNIT_INCH) * xscale; + page_left = gtk_page_setup_get_left_margin (context->page_setup, GTK_UNIT_INCH) * yscale; + page_right = gtk_page_setup_get_right_margin (context->page_setup, GTK_UNIT_INCH) * yscale; Margins of GtkPageSetup are not oriented. @@ +593,3 @@ + } + + return context->has_hard_margins; I don't quite understand what is the purpose of this function. I thought that we would just create a function gtk_print_context_get_margins() which would return oriented margins taken from the page setup to easier work for those developers which need the information (especially to save their time with finding out which margins they need for which orientation). What is practical application of the function? ::: gtk/gtkprinter.c @@ +994,3 @@ * @right: (out): a location to store the right margin in * + * Retrieve the hard margins of @printer in points, i.e. the margins that define We should move this to a separate patch. ::: gtk/gtkprintoperation-unix.c @@ +154,3 @@ + + _gtk_print_context_set_hard_margins (print_context, top, bottom, left, right); + } I think that we shouldn't change this here. We should keep the setting of hard margins in finish_print(). What we can do is to improve documentation to say that if an application changes page setup in "request-page-setup" signal then the page setup's margins have to be acceptable by the printer (they can always get the hard margins and modify the page setup according to that). The page setup's margins are used when doing transformation of the context not the hard margins (e.g. in _gtk_print_context_translate_into_margin()). ::: gtk/gtkprintoperation-win32.c @@ +466,3 @@ + _gtk_print_context_set_hard_margins (op->priv->print_context, right, left, top, bottom); + break; + } This should be another patch. Lets do this later once we have a testing environment for it.
(In reply to comment #7) > @@ +555,3 @@ > + page_bottom = gtk_page_setup_get_bottom_margin (context->page_setup, > GTK_UNIT_INCH) * xscale; > + page_left = gtk_page_setup_get_left_margin (context->page_setup, > GTK_UNIT_INCH) * yscale; > + page_right = gtk_page_setup_get_right_margin (context->page_setup, > GTK_UNIT_INCH) * yscale; > > Margins of GtkPageSetup are not oriented. > > @@ +593,3 @@ > + } > + > + return context->has_hard_margins; > > I don't quite understand what is the purpose of this function. I thought that > we would just create a function gtk_print_context_get_margins() which would > return oriented margins taken from the page setup to easier work for those > developers which need the information (especially to save their time with > finding out which margins they need for which orientation). > What is practical application of the function? If this function returns zero for each printable margin, the return value allows the user to know if the output device actually has no unprintable area (eg print to pdf or a printer that can print to the edge of the paper) or if it is because the backend does not have any information about the unprintable area. > ::: gtk/gtkprintoperation-unix.c > @@ +154,3 @@ > + > + _gtk_print_context_set_hard_margins (print_context, top, bottom, left, > right); > + } > > I think that we shouldn't change this here. We should keep the setting of hard > margins in finish_print(). What we can do is to improve documentation to say > that if an application changes page setup in "request-page-setup" signal then > the page setup's margins have to be acceptable by the printer (they can always > get the hard margins and modify the page setup according to that). > The page setup's margins are used when doing transformation of the context not > the hard margins (e.g. in _gtk_print_context_translate_into_margin()). I don't understand how this is useful. The problem is the hard margins can vary by paper size. gtk_printer_get_hard_margins returns *HWMargins which is the printable margins that are guaranteed to work for any page size. For some printer/paper combinations this can be significantly worse than using the paper size specific hard margins provided by *ImageableArea. For applications like evince that provide a "shrink to fit" option it is useful to be able to get the largest printable area available for the selected paper size. On win32 the hard margins are already set in start_page as on win32 the hard margins are only available from the device context once the page size has been set. This means on win32 the print context already has the paper size specific hard margins. We should make the unix side work the same way. The intent of the gtk_print_context_get_printable_margins function is to allow the application to find out if there is any unprintable area on the print context. The main use case is when using a full page context to find the actual printable area eg evince "shrink to fit". But it is also useful when using page setup margins since as far as I can see there is no guarantee that that all of the print context is printable, particularly as the page setup margins can be changed by the user with the gtk_page_setup_set_*_margin functions.
What about function gtk_print_context_get_margins() which would always return correct margins? It would return oriented hard margins if set page setup is not of any size of selected printer or margins taken from imageable area if the page setup is compatible (equal or at least same size) to an imageable area of the selected printer. The margins could be different from page setup which was set by developer but that is something which would be mentioned in comment for the function so the developer can take this into account.
We're moving to gitlab! As part of this move, we are moving bugs to NEEDINFO if they haven't seen activity in more than a year. If this issue is still important to you and still relevant with GTK+ 3.22 or master, please reopen it and we will migrate it to gitlab.
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gtk/issues/386.