7258: Work around PyCairo path issue by opening the target file first.

PyCairo, even the latest version, insists on using the 'mbcs' codec on path names on Windows.
That destroys pathnames with characters that aren't in the current default code-page.
This commit is contained in:
John Ralls 2014-04-19 15:02:46 -07:00
parent f62a38ef9a
commit 7962403216

View File

@ -94,104 +94,106 @@ class CairoDocgen(libcairodoc.CairoDoc):
# create cairo context and pango layout # create cairo context and pango layout
filename = self._backend.filename filename = self._backend.filename
# Work around a bug in pycairo 1.8.10 and earlier. OSX and # Cairo can't reliably handle unicode filenames on Linux or
# Win32 AIOs use pycairo 1.10.0, in which the bug is fixed. # Windows, so open the file for it.
if (sys.version_info[0] < 3 and lin()): with open(filename, 'wb') as fd:
filename = filename.encode(glocale.getfilesystemencoding()) try:
try: surface = self.create_cairo_surface(fd, paper_width,
surface = self.create_cairo_surface(filename, paper_width, paper_height) paper_height)
except IOError as msg: surface.set_fallback_resolution(300, 300)
errmsg = "%s\n%s" % (_("Could not create %s") % filename, msg) cr = cairo.Context(surface)
raise ReportError(errmsg) fontmap = PangoCairo.font_map_new()
except Exception as err: fontmap.set_resolution(DPI)
errmsg = "%s\n%s" % (_("Could not create %s") % filename, err) pango_context = fontmap.create_context()
raise ReportError(errmsg) options = cairo.FontOptions()
surface.set_fallback_resolution(300, 300) options.set_hint_metrics(cairo.HINT_METRICS_OFF)
cr = cairo.Context(surface) PangoCairo.context_set_font_options(pango_context, options)
fontmap = PangoCairo.font_map_new() layout = Pango.Layout(pango_context)
fontmap.set_resolution(DPI) PangoCairo.update_context(cr, pango_context)
pango_context = fontmap.create_context() # paginate the document
options = cairo.FontOptions() self.paginate_document(layout, page_width, page_height,
options.set_hint_metrics(cairo.HINT_METRICS_OFF) DPI, DPI)
PangoCairo.context_set_font_options(pango_context, options) body_pages = self._pages
layout = Pango.Layout(pango_context)
PangoCairo.update_context(cr, pango_context)
# paginate the document
self.paginate_document(layout, page_width, page_height, DPI, DPI)
body_pages = self._pages
# build the table of contents and alphabetical index # build the table of contents and alphabetical index
toc_page = None toc_page = None
index_page = None index_page = None
toc = [] toc = []
index = {} index = {}
for page_nr, page in enumerate(body_pages): for page_nr, page in enumerate(body_pages):
if page.has_toc(): if page.has_toc():
toc_page = page_nr toc_page = page_nr
if page.has_index(): if page.has_index():
index_page = page_nr index_page = page_nr
for mark in page.get_marks(): for mark in page.get_marks():
if mark.type == INDEX_TYPE_ALP: if mark.type == INDEX_TYPE_ALP:
if mark.key in index: if mark.key in index:
if page_nr + 1 not in index[mark.key]: if page_nr + 1 not in index[mark.key]:
index[mark.key].append(page_nr + 1) index[mark.key].append(page_nr + 1)
else:
index[mark.key] = [page_nr + 1]
elif mark.type == INDEX_TYPE_TOC:
toc.append([mark, page_nr + 1])
# paginate the table of contents
rebuild_required = False
if toc_page is not None:
toc_pages = self.__generate_toc(layout, page_width,
page_height, toc)
offset = len(toc_pages) - 1
if offset > 0:
self.__increment_pages(toc, index, toc_page, offset)
rebuild_required = True
else: else:
index[mark.key] = [page_nr + 1] toc_pages = []
elif mark.type == INDEX_TYPE_TOC:
toc.append([mark, page_nr + 1])
# paginate the table of contents
rebuild_required = False
if toc_page is not None:
toc_pages = self.__generate_toc(layout, page_width, page_height,
toc)
offset = len(toc_pages) - 1
if offset > 0:
self.__increment_pages(toc, index, toc_page, offset)
rebuild_required = True
else:
toc_pages = []
# paginate the index # paginate the index
if index_page is not None: if index_page is not None:
index_pages = self.__generate_index(layout, page_width, page_height, index_pages = self.__generate_index(layout, page_width,
index) page_height, index)
offset = len(index_pages) - 1 offset = len(index_pages) - 1
if offset > 0: if offset > 0:
self.__increment_pages(toc, index, index_page, offset) self.__increment_pages(toc, index, index_page, offset)
rebuild_required = True rebuild_required = True
else: else:
index_pages = [] index_pages = []
# rebuild the table of contents and index if required # rebuild the table of contents and index if required
if rebuild_required: if rebuild_required:
if toc_page is not None: if toc_page is not None:
toc_pages = self.__generate_toc(layout, page_width, page_height, toc_pages = self.__generate_toc(layout, page_width,
toc) page_height, toc)
if index_page is not None: if index_page is not None:
index_pages = self.__generate_index(layout, page_width, index_pages = self.__generate_index(layout, page_width,
page_height, index) page_height, index)
# render the pages # render the pages
if toc_page is not None: if toc_page is not None:
body_pages = body_pages[:toc_page] + toc_pages + \ body_pages = body_pages[:toc_page] + toc_pages + \
body_pages[toc_page+1:] body_pages[toc_page+1:]
if index_page is not None: if index_page is not None:
body_pages = body_pages[:index_page] + index_pages + \ body_pages = body_pages[:index_page] + index_pages + \
body_pages[index_page+1:] body_pages[index_page+1:]
self._pages = body_pages self._pages = body_pages
for page_nr in range(len(self._pages)): for page_nr in range(len(self._pages)):
cr.save() cr.save()
cr.translate(left_margin, top_margin) cr.translate(left_margin, top_margin)
self.draw_page(page_nr, cr, layout, self.draw_page(page_nr, cr, layout,
page_width, page_height, page_width, page_height,
DPI, DPI) DPI, DPI)
cr.show_page() cr.show_page()
cr.restore() cr.restore()
# close the surface (file) # close the surface (file)
surface.finish() surface.finish()
except IOError as msg:
errmsg = "%s\n%s" % (_("Could not create %s") % filename, msg)
raise ReportError(errmsg)
except Exception as err:
errmsg = "%s\n%s" % (_("Could not create %s") % filename, err)
raise ReportError(errmsg)
def __increment_pages(self, toc, index, start_page, offset): def __increment_pages(self, toc, index, start_page, offset):
""" """
Increment the page numbers in the table of contents and index. Increment the page numbers in the table of contents and index.