Is there any way to print the rendered html without creating a file? Something like using pycairo to integrate with GTKs printing dialog (I couldn't find out how should I do this)?
Good question!
I've tried, but it seems to be hard: WeasyPrint uses CairoCFFI objects while GTK uses Cairo's introspection objects. Here's what I wrote, I think that it would work if the two Cairo backends were compatible:
import sys
from gi.repository import Gtk, GLib
from weasyprint import HTML
class Printo:
def __init__(self, url):
self.operation = Gtk.PrintOperation()
document = HTML(url).render()
self.operation.connect('begin-print', self.begin_print, document)
self.operation.connect('draw-page', self.draw_page, document)
self.operation.set_use_full_page(False)
self.operation.set_unit(Gtk.Unit.POINTS)
self.operation.set_embed_page_setup(True)
settings = Gtk.PrintSettings()
directory = GLib.get_user_special_dir(
GLib.UserDirectory.DIRECTORY_DOCUMENTS) or GLib.get_home_dir()
ext = settings.get(Gtk.PRINT_SETTINGS_OUTPUT_FILE_FORMAT) or 'pdf'
uri = 'file://%s/weasyprint.%s' % (directory, ext)
settings.set(Gtk.PRINT_SETTINGS_OUTPUT_URI, uri)
self.operation.set_print_settings(settings)
def run(self):
self.operation.run(Gtk.PrintOperationAction.PRINT_DIALOG)
Gtk.main_quit()
def begin_print(self, operation, print_ctx, document):
operation.set_n_pages(len(document.pages))
def draw_page(self, operation, print_ctx, page_num, document):
page = document.pages[page_num]
context = print_ctx.get_cairo_context()
page.paint(context)
def main():
url = sys.argv[1] if len(sys.argv) > 1 else 'https://weasyprint.org'
Printo(url).run()
if __name__ == '__main__':
main()
(Highly inspired by https://gitlab.gnome.org/GNOME/pygobject/blob/3.13.3/demos/gtk-demo/demos/printing.py)
I'd be happy to have a solution!
Thanks for your solution and your great engine.
When I run this code the following error occurred:
Traceback (most recent call last):
File "tt.py", line 39, in draw_page
page.paint(context)
File "/usr/local/lib/python2.7/dist-packages/weasyprint/document.py", line 238, in paint
draw_page(self._page_box, cairo_context, self._enable_hinting)
File "/usr/local/lib/python2.7/dist-packages/weasyprint/draw.py", line 158, in draw_page
clip_box=False, bleed=bleed, marks=marks)
File "/usr/local/lib/python2.7/dist-packages/weasyprint/draw.py", line 405, in draw_background
draw_background_image(context, layer, bg.image_rendering)
File "/usr/local/lib/python2.7/dist-packages/weasyprint/draw.py", line 481, in draw_background_image
context.set_source(pattern)
TypeError: Context.set_source() argument 1 must be cairo.Pattern, not SurfacePattern
And a blank pdf created. Can you help me to make the two Cairo backend compatible (if it's the problem)?
Anyway, we are working on https://github.com/Jooyeshgar/amir/tree/gtk3 and your engine saved our life!
Can you help me to make the two Cairo backend compatible (if it's the problem)?
Yes, that's the problem. And seriously, converting a cairocffi context into a cairo-with-introspection is crazy, nobody would ever want to do this… Oh, wait! Here's what we want!
Nice!
import cairocffi
[…]
def draw_page(self, operation, print_ctx, page_num, document):
page = document.pages[page_num]
cairo_context = print_ctx.get_cairo_context()
cairocffi_context = cairocffi.Context._from_pointer(
cairocffi.ffi.cast(
'cairo_t **', id(cairo_context) + object.__basicsize__)[0],
incref=True)
page.paint(cairocffi_context, left_x=0, top_y=0, scale=0.75)
It works!
You'll have to play with left_x, top_y and scale in order to make the document size fit into the printable area (that depends on the printer settings). The current scale should work when the document has the same size as the paper (0.75 = 72 PDF point (cairo units) per inch / 96 CSS pixel per inch).
But that's your part of the work! You'll probably need to read Gtk PrintSettings documentation.
Most helpful comment
Yes, that's the problem. And seriously, converting a cairocffi context into a cairo-with-introspection is crazy, nobody would ever want to do this… Oh, wait! Here's what we want!
Nice!
It works!
You'll have to play with
left_x,top_yandscalein order to make the document size fit into the printable area (that depends on the printer settings). The current scale should work when the document has the same size as the paper (0.75 = 72 PDF point (cairo units) per inch / 96 CSS pixel per inch).But that's your part of the work! You'll probably need to read Gtk PrintSettings documentation.