This week I once again ran into the problem of “non-standard” fonts, and if earlier it was sometimes possible to get by with the most usual cutting in a graphic editor or using some kind of client substitution technique, then this time the task is the most global. There are really a lot of dynamic titles in the oncoming project.
I would like to share my thoughts, search and the final decision with you.
Preamble
So, in principle, what options do we have:
- Replace with Flash: sIFR, swftype;
- draw on canvas with JavaScript: cufon, typeface;
- use a server for this purpose.
I already used the first option in a couple of projects, though not actually sIFR, but it doesn’t matter, I was not very pleased with the result. Build-rebuild the Flash file with the font, check for flash, "frame" in IE7, not kosher in the end. The second option is always considered too heavy, both in terms of traffic (files with rendered fonts weigh decently, and they are not always correctly converted), as well as the load on the client's processor. So I never let him go to production.
')
So I came to the third option. Once I had already worked through this method on one of the then php projects, having read the idea on
A List Apart . It works and works quite well, although JavaScript was still used in this method. Moreover, now we are developing projects only on Django, so I went on a search and after a while found two similar projects: django-cairo-text and django-image-replacement. The first one has sufficiently wide capabilities, but it does not know how to draw with a font from a file, only one of those installed in the system, which in my case absolutely does not fit, the second is too simple for my needs and uses approaches that are not very convenient for me.
But the base is there, there is a goal and, as usual, I decided to write my crutches with a turbo drive. Actually, what came of it, I want to present to your review.
So django-headline
What we can do today
- Rendering pictures from a template in three ways: filter, tag and tag that changes context
- Naturally, caching previously rendered images
- Defining standard font styles through classes
- Automatic replacement of html-entities with Unicode characters
- Splitting a text string by br or by words
- Own settings for the location of fonts and cache folders
- Optional optimization of the output png, through external utilities
Installation and Setup
Work requires the installed ones: PIL and Freetype2
Place the
headline.py file in your application's templatetags folder.
The following parameters are available for setting:
# ( MEDIA_ROOT/MEDIA_URL) HEADLINE_CACHE_DIR = 'upload/textcache' # ( MEDIA_ROOT) HEADLINE_FONTS_DIR = 'fonts' # , HEADLINE_PNG_OPTIMIZER = "optipng -o7 %(file)s" # HEADLINE_CLASSES = { "<class_name>": { 'font': <file>, 'size': <size>, 'color': <hex color>, 'decoration': ['underline', 'strikeout'], # Optional }, ... }
Examples of using
{% load headline %}
Like a filter
{{ foo|headline:"font.ttf,20,#000" }} {{ foo|headline:"font.ttf,20,#000,underline,all" }} {{ foo|headline:"base,br" }}
As tag
{% headline "font.ttf,20,#000" %}Big {{ foo }}{% endheadline %} {% headline "font.ttf,20,#000,strikeout,none" %}Big {{ foo }}{% endheadline %} {% headline "base" %}Big {{ foo }}{% endheadline %}
As a context modifying tag
{% headlines foo_list bar_dict baz_var "And some text" as headers "font.ttf,20,#000" %} {% headlines foo_list bar_dict baz_var "And some text" as headers "font.ttf,20,#000,all" %} {% headlines foo_list bar_dict baz_var "And some text" as headers "base" %}
In this case, as parameters you can pass both variables and simple strings enclosed in double quotes, as well as lists and dictionaries. At the output, we have a list of headers from {file, text, width, height} objects:
{% for head in headers %} <img src="{{ head.file }}" alt="{{ head.text }}" width="{{ head.width }}" height="{{ head.height }}" /> {% endfor %}
This is what, for example,
can happen in the final . I am not a designer, and I selected fonts by eye, so I’m asking for them not to kick my feet.
Thus, for the client, it looks like manual cutting, for the server - the load is one-time in nature, for the developer everything is simple and transparent. Profit!
Again related links:
Thank you for this, I accept reviews on the topic, any degree of compliment.