Zobrazují se příspěvky se štítkempdf. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkempdf. Zobrazit všechny příspěvky

středa 20. května 2009

Cairo PDF - text vs. curves

When I started to use Cairo, I was at first surprised and then pleased by finding out that the text in PDF export was converted into curves. However, later I found that cairo also supports normal text and embedding of fonts in PDF. Because both can be useful in different situations, I would like to show in this post how both can be achieved in PyCairo (the Cairo bindings to Python).
The basic difference is in the PyCairo context object method you use to create the text. The two possibilities are:
  • show_text(text)
  • text_path(text)

The first one puts a normal text into the drawing (and embeds fonts), while the second creates a path for the text, which can later be filled (or stroked), thus converting the text into curves.
The following code demonstrates this feature:

import cairo
width, height = 200, 100
# create the surface and context
surface = cairo.PDFSurface( "output.pdf", width, height)
context = cairo.Context( surface)
# white background
context.set_source_rgb( 1, 1, 1)
context.rectangle( 0, 0, width, height)
context.fill()
# draw the text
context.set_font_size( 32)
context.select_font_face( "Arial")
context.move_to( 10, 40)
context.set_source_rgb( 0, 0, 0.5)
# text as curves
context.text_path( "Hello curves")
context.fill()
context.move_to( 30, 80)
# text as text
context.show_text( "Hello text")
# finalization
context.show_page()
surface.finish()

When you run this code, you will get a small PDF document called output.pdf in which part of the text will be selectable as normal text and part will not, because it is converted to curves.
As mentioned, the text path can be also used for stroking, which will produce a nice text outline:

neděle 15. března 2009

Sending big files using Django

And now for something completely different...

Even though it is recommended not to serve static files using Django and one should run a separate lightweight server (such as lighthttpd) for this task, it is not uncommon that website systems written in Django sometimes need to send big files directly. In my case it was to restrict access to PDF files only to specific IP addresses which are stored in the systems database.

The main reason you should not send static files directly from Django - by reading the content of the file and sending it out - is that the whole file would be read into memory before sending it. For larger files - in my case about one to several megabytes - this is very inefficient and could easily choke the system where 90% of the traffic is generated by those bulky PDFs.

My original idea was to serve this data as other static files and use some form of name mangling in order for the user not to be able to guess the right name. However, such security through obscurity just moves the problem somewhere else - once a user obtains the right URL, he is not restricted in any way to use it.

Because of this, I decided that it would be useful to find a way to more effectively serve static files from Django, even if I should write it myself. Fortunately, I did not have to :)
After quick Google search, I found this ticket on Django website. It is an already approved patch that adds the HttpResponseSendFile function which does exactly what I need - very efficiently sends static files using the underlying systems optimized routines.
The patch attached to this ticked applied without problems to my Django 1.0.2 installation and in fifteen minutes was serving my static files to the world :)

I hope this information might get useful to other Django fans who stumble upon a similar problem.

pondělí 9. února 2009

PDF and SVG support added to OASA

In the newest versions of OASA, I have added the possibility to create images not only in PNG, but also in SVG and PDF.
This functionality comes for free as a courtesy of the Cairo library and gives the user the possibility to create output much more suitable for printing.
Here is a small example code showing how to create a PDF export:

from oasa import smiles, cairo_out
mol = smiles.text_to_mol( "Oc1ccc(N)cc1Cl")
mol.normalize_bond_length( 30)
mol.remove_unimportant_hydrogens()
cairo_out.mol_to_cairo( mol, "example.pdf", format="pdf")

The output looks like this (of course, this is rendered to PNG, the PDF can be found here):
(Because SMILES was used as input, OASA generates the 2D structure for you.)
For SVG, just replace "pdf" with "svg" in the example above.
The cairo_out.mol_to_cairo function has many keyword arguments that allows for changing of almost every aspect of the output. For example, the following adds hydrogen symbols to hetero-atoms and changes the line width for bonds.

cairo_out.mol_to_cairo( mol, "example.svg", format="svg",
show_hydrogens_on_hetero=True,
line_width=2)

The output now looks like this (again in PNG, the SVG can be found here):



One big advantage of the SVG generated by Cairo is that all text is converted to curves. This means that the output will look the same on every machine, regardless of installed fonts.