Apply basic ligatures to a document

This script is a search and replace tool "specialized" in ligatures. The specific code is mostly meant for displaying the report at the end. And to make sure it doesn't try to apply some ligatures with fonts that doesn't have them.

Note that since Scribus doesn't support OpenType features nor direct glyph access yet, these ligatures need to be mapped as characters in the font.

How to use it
Ligatures are presented in a python dictionary. Since not all fonts have the same ligatures, you need to specify the font name. So the first level in this dictionary is the font name according to scribus. Then you have to put the ligatures you want as a sub-dictionary. liga = { 'Miama Italic': { u'oos':u'\ue0f9', u'os':u'\ue0fa', u'Th':u'\ue0fc', u'tt':u'\ue0fd', u'tz':u'\ue0fe', u'oo':u'\ue0ff', u'ff':u'\ufb00', u'fl':u'\ufb02', u'ffl':u'\ufb04', u'ſt':u'\ufb05', u'st':u'\ufb06' },	'DejaVu Sans Book': { u'ff':u'\ufb00', u'fi':u'\ufb01', u'fl':u'\ufb02', u'ffi':u'\ufb03', u'ffl':u'\ufb04', u'ſt':u'\ufb05', u'st':u'\ufb06' } } In my example, DejaVu Sans has all the standard (unicode) ligatures while Miama doesn't (missing fi and ffi) but it has other ligatures mapped in the private use area.

The script

 * 1) !/usr/bin/env python
 * 2) coding: utf-8
 * 3)       Copyright 2012 Olivier Berten 
 * 4)       This program is free software; you can redistribute it and/or modify
 * 5)       it under the terms of the GNU General Public License as published by
 * 6)       the Free Software Foundation; either version 3 of the License, or
 * 7)       (at your option) any later version.
 * 8)       This program is distributed in the hope that it will be useful,
 * 9)       but WITHOUT ANY WARRANTY; without even the implied warranty of
 * 10)       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * 11)       GNU General Public License for more details.
 * 12)       You should have received a copy of the GNU General Public License
 * 13)       along with this program; if not, write to the Free Software
 * 14)       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * 15)       MA 02110-1301, USA.
 * 1)       You should have received a copy of the GNU General Public License
 * 2)       along with this program; if not, write to the Free Software
 * 3)       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * 4)       MA 02110-1301, USA.

import scribus import re

punctuation = '!"#$%&\'*+,-./:;<=>?@[\\]^_`{|}~'

liga = { 'Miama Italic': { u'oos':u'\ue0f9', u'os':u'\ue0fa', u'Th':u'\ue0fc', u'tt':u'\ue0fd', u'tz':u'\ue0fe', u'oo':u'\ue0ff', u'ff':u'\ufb00', u'fl':u'\ufb02', u'ffl':u'\ufb04', u'ſt':u'\ufb05', u'st':u'\ufb06' },	'DejaVu Sans Book': { u'ff':u'\ufb00', u'fi':u'\ufb01', u'fl':u'\ufb02', u'ffi':u'\ufb03', u'ffl':u'\ufb04', u'ſt':u'\ufb05', u'st':u'\ufb06' } }

def applyLigatures: page = 1 pagenum = scribus.pageCount report = '' while (page <= pagenum): scribus.gotoPage(page) d = scribus.getPageItems rep_page = ['Page ' + str(page) + '\n', True] for item in d:			if (item[1] == 4): contents = unicode(scribus.getAllText(item[0])) rep_frame = ['   ' + item[0] + '\n', True] words = re.compile(r'[%s\s]+' % re.escape(punctuation)).split(contents) p = 0 d = 0 for w in words: wo = w					d2 = 0 p = contents.find(w,p) lig = False rep_lig = [] for font, lpairs in liga.iteritems: for l in sorted(lpairs.keys, key=len, reverse=True): f = [m.start for m in re.finditer(l, w)] if len(f) > 0: for e in f:									scribus.selectText(p+e-d+d2, len(l), item[0]) Font = scribus.getFont(item[0]) FontSize = scribus.getFontSize(item[0]) if Font == font: lig = True scribus.deleteText(item[0]) scribus.insertText(lpairs[l], p+e-d+d2, item[0]) scribus.selectText(p+e-d+d2, len(lpairs[l]), item[0]) scribus.setFont(Font, item[0]) scribus.selectText(p+e-d+d2, len(lpairs[l]), item[0]) scribus.setFontSize(FontSize, item[0]) d += len(l)-len(lpairs[l]) d2 += len(l)-len(lpairs[l]) w = w.replace(l, lpairs[l], 1) rep_lig.append(l) if lig: if rep_page[1]: report += rep_page[0] rep_page[1] = False if rep_frame[1]: report += rep_frame[0] rep_frame[1] = False report += '       ' + wo + ' (' + ', '.join(rep_lig) + ')\n' page += 1 scribus.docChanged(True) if report > '': report = 'Ligatures made:\n\n' + report else: report = 'No ligature made' scribus.messageBox("Finished", report)

if scribus.haveDoc: try: applyLigatures except Exception, e:		print e else: scribus.messageBox('Error', 'This script needs an opened document!')