From f999ba9cc438ae185377a217306963136a32aabe Mon Sep 17 00:00:00 2001 From: Benny Malengier Date: Fri, 29 May 2009 19:52:57 +0000 Subject: [PATCH] Part 1 basedoc changes: move out backend stuff from BaseDoc, use backend in the docs. As a dir change will be done, backend itself will be committed later, trunk will be broken till then svn: r12590 --- src/BaseDoc.py | 183 +--------------------- src/plugins/docgen/LaTeXDoc.py | 272 +++++++++++---------------------- src/plugins/docgen/PdfDoc.py | 4 +- src/plugins/lib/libcairodoc.py | 52 +------ 4 files changed, 95 insertions(+), 416 deletions(-) diff --git a/src/BaseDoc.py b/src/BaseDoc.py index a419a96aa..e25dfa802 100644 --- a/src/BaseDoc.py +++ b/src/BaseDoc.py @@ -1405,41 +1405,13 @@ class BaseDoc(object): # TextDoc # #------------------------------------------------------------------------ -def noescape(text): - return text - + class TextDoc(object): """ Abstract Interface for text document generators. Output formats for text reports must implment this interface to be used by the report system. """ - BOLD = 0 - ITALIC = 1 - UNDERLINE = 2 - FONTFACE = 3 - FONTSIZE = 4 - FONTCOLOR = 5 - HIGHLIGHT = 6 - SUPERSCRIPT = 7 - - SUPPORTED_MARKUP = [] - - ESCAPE_FUNC = lambda x: noescape - #Map between styletypes and internally used values. This map is needed - # to make TextDoc officially independant of gen.lib.styledtexttag - STYLETYPE_MAP = { - } - CLASSMAP = None - - #STYLETAGTABLE to store markup for write_markup associated with style tags - STYLETAG_MARKUP = { - BOLD : ("", ""), - ITALIC : ("", ""), - UNDERLINE : ("", ""), - SUPERSCRIPT : ("", ""), - } - def page_break(self): "Forces a page break, creating a new page" raise NotImplementedError @@ -1592,159 +1564,6 @@ class TextDoc(object): @param h_cm: height in centimeters """ raise NotImplementedError - - def find_tag_by_stag(self, s_tag): - """ - @param s_tag: object: assumed styledtexttag - @param s_tagvalue: None/int/str: value associated with the tag - - A styled tag is type with a value. - Every styled tag must be converted to the tags used in the corresponding - markup for the backend, eg text for bold in html. - These markups are stored in STYLETAG_MARKUP. They are tuples for begin - and end tag - If a markup is not present yet, it is created, using the - _create_xmltag method you can overwrite - """ - type = s_tag.name - - if not self.STYLETYPE_MAP or \ - self.CLASSMAP <> type.__class__.__name__ : - self.CLASSMAP == type.__class__.__name__ - self.STYLETYPE_MAP[type.__class__.BOLD] = self.BOLD - self.STYLETYPE_MAP[type.ITALIC] = self.ITALIC - self.STYLETYPE_MAP[type.UNDERLINE] = self.UNDERLINE - self.STYLETYPE_MAP[type.FONTFACE] = self.FONTFACE - self.STYLETYPE_MAP[type.FONTSIZE] = self.FONTSIZE - self.STYLETYPE_MAP[type.FONTCOLOR] = self.FONTCOLOR - self.STYLETYPE_MAP[type.HIGHLIGHT] = self.HIGHLIGHT - self.STYLETYPE_MAP[type.SUPERSCRIPT] = self.SUPERSCRIPT - - typeval = int(s_tag.name) - s_tagvalue = s_tag.value - tag_name = None - if type.STYLE_TYPE[typeval] == bool: - return self.STYLETAG_MARKUP[self.STYLETYPE_MAP[typeval]] - elif type.STYLE_TYPE[typeval] == str: - tag_name = "%d %s" % (typeval, s_tagvalue) - elif type.STYLE_TYPE[typeval] == int: - tag_name = "%d %d" % (typeval, s_tagvalue) - if not tag_name: - return None - - tags = self.STYLETAG_MARKUP.get(tag_name) - if tags is not None: - return tags - #no tag known yet, create the markup, add to lookup, and return - tags = self._create_xmltag(self.STYLETYPE_MAP[typeval], s_tagvalue) - self.STYLETAG_MARKUP[tag_name] = tags - return tags - - def _create_xmltag(self, type, value): - """ - Create the xmltags for the backend. - Overwrite this method to create functionality with a backend - """ - if type not in self.SUPPORTED_MARKUP: - return None - return ('', '') - - def _add_markup_from_styled(self, text, s_tags, split=''): - """ - Input is plain text, output is text with markup added according to the - s_tags which are assumed to be styledtexttags. - When split is given the text will be split over the value given, and - tags applied in such a way that it the text can be safely splitted in - pieces along split - - @param text : str, a piece of text - @param s_tags : styledtexttags that must be applied to the text - @param split : str, optional. A string along which the output can - be safely split without breaking the styling. - As adding markup means original text must be escaped, ESCAPE_FUNC is - used - This can be used to convert the text of a styledtext to the format - needed for a document backend - Do not call this method in a report, use the write_markup method - - @note: the algorithm is complex as it assumes mixing of tags is not - allowed: eg text here not is assumed invalid - as markup. If the s_tags require such a setup, what is returned - is text here not - overwrite this method if this complexity is not needed. - """ - FIRST = 0 - LAST = 1 - tagspos = {} - for s_tag in s_tags: - tag = self.find_tag_by_stag(s_tag) - if tag is not None: - for (start, end) in s_tag.ranges: - if start in tagspos: - tagspos[start] += [(tag, FIRST)] - else: - tagspos[start] = [(tag, FIRST)] - if end in tagspos: - tagspos[end] += [(tag, LAST)] - else: - tagspos[end] = [(tag, LAST)] - start = 0 - end = len(text) - keylist = tagspos.keys() - keylist.sort() - keylist = [x for x in keylist if x<=len(text)] - opentags = [] - otext = u"" #the output, text with markup - lensplit = len(split) - for pos in keylist: - #write text up to tag - if pos > start: - if split: - #make sure text can split - splitpos = text[start:pos].find(split) - while splitpos <> -1: - otext += self.ESCAPE_FUNC()(text[start:start+splitpos]) - #close open tags - for opentag in reversed(opentags): - otext += opentag[1] - #add split text - otext += self.ESCAPE_FUNC()(split) - #open the tags again - for opentag in opentags: - otext += opentag[0] - #obtain new values - start = start + splitpos + lensplit - splitpos = text[start:pos].find(split) - - otext += self.ESCAPE_FUNC()(text[start:pos]) - #write out tags - for tag in tagspos[pos]: - #close open tags starting from last open - for opentag in reversed(opentags): - otext += opentag[1] - #if start, add to opentag in beginning as first to open - if tag[1] == FIRST: - opentags = [tag[0]] + opentags - else: - #end tag, is closed already, remove from opentag - opentags = [x for x in opentags if not x == tag[0] ] - #now all tags are closed, open the ones that should open - for opentag in opentags: - otext += opentag[0] - start = pos - #add remainder of text, no markup present there - otext += self.ESCAPE_FUNC()(text[start:end]) - - #opentags should be empty. If not, user gave tags on positions that - # are over the end of the text. Just close the tags still open - if opentags: - print 'WARNING: TextDoc : More style tags in text than length '\ - 'of text allows.\n', opentags - for opentag in reversed(opentags): - otext += opentag[1] - - return otext - #------------------------------------------------------------------------ # diff --git a/src/plugins/docgen/LaTeXDoc.py b/src/plugins/docgen/LaTeXDoc.py index ee66a8f8d..220468229 100644 --- a/src/plugins/docgen/LaTeXDoc.py +++ b/src/plugins/docgen/LaTeXDoc.py @@ -40,6 +40,7 @@ from gettext import gettext as _ # #------------------------------------------------------------------------ import BaseDoc +from docbackend.latexbackend import LateXBackend, latexescape from gen.plug import PluginManager, DocGenPlugin import ImgManip import Errors @@ -128,81 +129,18 @@ class TexFont(object): # #------------------------------------------------------------------------ -def latexescape(text): - """ - change text in text that latex shows correctly - special characters: \& \$ \% \# \_ \{ \} - """ - text = text.replace('&','\\&') - text = text.replace('$','\\$') - text = text.replace('%','\\%') - text = text.replace('#','\\#') - text = text.replace('_','\\_') - text = text.replace('{','\\{') - text = text.replace('}','\\}') - return text - -def latexescapeverbatim(text): - """ - change text in text that latex shows correctly respecting whitespace - special characters: \& \$ \% \# \_ \{ \} - Now also make sure space and newline is respected - """ - text = text.replace('&', '\\&') - text = text.replace('$', '\\$') - text = text.replace('%', '\\%') - text = text.replace('#', '\\#') - text = text.replace('_', '\\_') - text = text.replace('{', '\\{') - text = text.replace('}', '\\}') - text = text.replace(' ', '\\ ') - text = text.replace('\n', '\\newline\n') - #spaces at begin are normally ignored, make sure they are not. - #due to above a space at begin is now \newline\n\ - text = text.replace('\\newline\n\\ ', '\\newline\n\\hspace*{0.1cm}\\ ') - return text - class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): """LaTeX document interface class. Derived from BaseDoc""" - # overwrite base class attributes, they become static var of LaTeXDoc - SUPPORTED_MARKUP = [ - BaseDoc.TextDoc.BOLD, - BaseDoc.TextDoc.ITALIC, - BaseDoc.TextDoc.UNDERLINE, - BaseDoc.TextDoc.FONTSIZE, - BaseDoc.TextDoc.FONTFACE, - BaseDoc.TextDoc.SUPERSCRIPT ] - - STYLETAG_MARKUP = { - BaseDoc.TextDoc.BOLD : ("\\textbf{", "}"), - BaseDoc.TextDoc.ITALIC : ("\\textit{", "}"), - BaseDoc.TextDoc.UNDERLINE : ("\\underline{", "}"), - BaseDoc.TextDoc.SUPERSCRIPT : ("\\textsuperscript{", "}"), - } - - ESCAPE_FUNC = lambda x: latexescape - def page_break(self): "Forces a page break, creating a new page" - self.f.write('\\newpage ') + self._backend.write('\\newpage ') - def open(self,filename): + def open(self, filename): """Opens the specified file, making sure that it has the extension of .tex""" - - if filename[-4:] != ".tex": - self.filename = filename + ".tex" - else: - self.filename = filename - - try: - self.f = open(self.filename,"w") - except IOError,msg: - errmsg = "%s\n%s" % (_("Could not create %s") % self.filename, msg) - raise Errors.ReportError(errmsg) - except: - raise Errors.ReportError(_("Could not create %s") % self.filename) + self._backend = LateXBackend(filename) + self._backend.open() # Font size control seems to be limited. For now, ignore # any style constraints, and use 12pt has the default @@ -229,45 +167,45 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): # Use the article template, T1 font encodings, and specify # that we should use Latin1 and unicode character encodings. - self.f.write('\\documentclass[%s]{article}\n' % options) - self.f.write('\\usepackage[T1]{fontenc}\n') - self.f.write('%\n% We use latin1 encoding at a minimum by default.\n') - self.f.write('% GRAMPS uses unicode UTF-8 encoding for its\n') - self.f.write('% international support. LaTeX can deal gracefully\n') - self.f.write('% with unicode encoding by using the ucs style invoked\n') - self.f.write('% when utf8 is specified as an option to the inputenc\n') - self.f.write('% package. This package is included by default in some\n') - self.f.write('% installations, but not in others, so we do not make it\n') - self.f.write('% the default. Uncomment the second line if you wish to use it\n') - self.f.write('% (If you do not have ucs.sty, you may obtain it from\n') - self.f.write('% http://www.tug.org/tex-archive/macros/latex/contrib/supported/unicode/)\n') - self.f.write('%\n') - self.f.write('\\usepackage[latin1]{inputenc}\n') - self.f.write('%\\usepackage[latin1,utf8]{inputenc}\n') + self._backend.write('\\documentclass[%s]{article}\n' % options) + self._backend.write('\\usepackage[T1]{fontenc}\n') + self._backend.write('%\n% We use latin1 encoding at a minimum by default.\n') + self._backend.write('% GRAMPS uses unicode UTF-8 encoding for its\n') + self._backend.write('% international support. LaTeX can deal gracefully\n') + self._backend.write('% with unicode encoding by using the ucs style invoked\n') + self._backend.write('% when utf8 is specified as an option to the inputenc\n') + self._backend.write('% package. This package is included by default in some\n') + self._backend.write('% installations, but not in others, so we do not make it\n') + self._backend.write('% the default. Uncomment the second line if you wish to use it\n') + self._backend.write('% (If you do not have ucs.sty, you may obtain it from\n') + self._backend.write('% http://www.tug.org/tex-archive/macros/latex/contrib/supported/unicode/)\n') + self._backend.write('%\n') + self._backend.write('\\usepackage[latin1]{inputenc}\n') + self._backend.write('%\\usepackage[latin1,utf8]{inputenc}\n') # add packages (should be standard on a default installation) # for finer output control. Put comments in file for user to read - self.f.write('\\usepackage{graphicx} % Extended graphics support\n') - self.f.write('\\usepackage{longtable} % For multi-page tables\n') - self.f.write('\\usepackage{calc} % For margin indents\n') - self.f.write('%\n% Depending on your LaTeX installation, the') - self.f.write(' margins may be too\n% narrow. ') - self.f.write(' This can be corrected by uncommenting the following\n') - self.f.write('% two lines and adjusting the width appropriately.') - self.f.write(' The example\n% removes 0.5in from each margin.') - self.f.write(' (Adds 1 inch to the text)\n') - self.f.write('%\\addtolength{\\oddsidemargin}{-0.5in}\n') - self.f.write('%\\addtolength{\\textwidth}{1.0in}\n%\n') - self.f.write('% Create a margin-adjusting command that allows LaTeX\n') - self.f.write('% to behave like the other gramps-supported output formats\n') - self.f.write('\\newlength{\\leftedge}\n') - self.f.write('\\setlength{\\leftedge}{\\parindent}\n') - self.f.write('\\newlength{\\grampstext}\n') - self.f.write('\\setlength{\\grampstext}{\\textwidth}\n') - self.f.write('\\newcommand{\\grampsindent}[1]{%\n') - self.f.write(' \\setlength{\\parindent}{\\leftedge + #1}%\n') - self.f.write(' \\setlength{\\textwidth}{\\grampstext - #1}%\n') - self.f.write('}\n\n') - self.f.write('\\begin{document}\n\n') + self._backend.write('\\usepackage{graphicx} % Extended graphics support\n') + self._backend.write('\\usepackage{longtable} % For multi-page tables\n') + self._backend.write('\\usepackage{calc} % For margin indents\n') + self._backend.write('%\n% Depending on your LaTeX installation, the') + self._backend.write(' margins may be too\n% narrow. ') + self._backend.write(' This can be corrected by uncommenting the following\n') + self._backend.write('% two lines and adjusting the width appropriately.') + self._backend.write(' The example\n% removes 0.5in from each margin.') + self._backend.write(' (Adds 1 inch to the text)\n') + self._backend.write('%\\addtolength{\\oddsidemargin}{-0.5in}\n') + self._backend.write('%\\addtolength{\\textwidth}{1.0in}\n%\n') + self._backend.write('% Create a margin-adjusting command that allows LaTeX\n') + self._backend.write('% to behave like the other gramps-supported output formats\n') + self._backend.write('\\newlength{\\leftedge}\n') + self._backend.write('\\setlength{\\leftedge}{\\parindent}\n') + self._backend.write('\\newlength{\\grampstext}\n') + self._backend.write('\\setlength{\\grampstext}{\\textwidth}\n') + self._backend.write('\\newcommand{\\grampsindent}[1]{%\n') + self._backend.write(' \\setlength{\\parindent}{\\leftedge + #1}%\n') + self._backend.write(' \\setlength{\\textwidth}{\\grampstext - #1}%\n') + self._backend.write('}\n\n') + self._backend.write('\\begin{document}\n\n') self.in_list = 0 self.in_table = 0 @@ -351,15 +289,15 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): def close(self): """Clean up and close the document""" if self.in_list: - self.f.write('\\end{enumerate}\n') - self.f.write('\n\\end{document}\n') - self.f.close() + self._backend.write('\\end{enumerate}\n') + self._backend.write('\n\\end{document}\n') + self._backend.close() if self.open_req: - Utils.open_file_with_default_application(self.filename) + Utils.open_file_with_default_application(self._backend.filename) def end_page(self): """Issue a new page command""" - self.f.write('\\newpage') + self._backend.write('\\newpage') def start_paragraph(self,style_name,leader=None): """Paragraphs handling - A Gramps paragraph is any @@ -378,11 +316,11 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): if self.indent is not None and not self.in_table: myspace = '%scm' % str(self.indent) - self.f.write('\\grampsindent{%s}\n' % myspace) + self._backend.write('\\grampsindent{%s}\n' % myspace) self.fix_indent = 1 if leader is not None and not self.in_list: - self.f.write('\\begin{enumerate}\n') + self._backend.write('\\begin{enumerate}\n') self.in_list = 1 if leader is not None: # try obtaining integer @@ -394,22 +332,22 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): num = int(leader_1) except ValueError: num = 1 - self.f.write(' \\renewcommand\\theenumi{\\arabic{enumi}}') + self._backend.write(' \\renewcommand\\theenumi{\\arabic{enumi}}') else: # roman, set the case correctly if leader_1.islower(): - self.f.write(' \\renewcommand\\theenumi{\\roman{enumi}}') + self._backend.write(' \\renewcommand\\theenumi{\\roman{enumi}}') else: - self.f.write(' \\renewcommand\\theenumi{\\Roman{enumi}}') + self._backend.write(' \\renewcommand\\theenumi{\\Roman{enumi}}') - self.f.write(' \\setcounter{enumi}{%d} ' % num) - self.f.write(' \\addtocounter{enumi}{-1}\n') - self.f.write(' \\item ') + self._backend.write(' \\setcounter{enumi}{%d} ' % num) + self._backend.write(' \\addtocounter{enumi}{-1}\n') + self._backend.write(' \\item ') if leader is None and not self.in_list and not self.in_table: - self.f.write('\n') + self._backend.write('\n') - self.f.write('%s ' % self.fbeg) + self._backend.write('%s ' % self.fbeg) def end_paragraph(self): """End the current paragraph""" @@ -417,30 +355,30 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): if self.in_list: self.in_list = 0 - self.f.write('\n\\end{enumerate}\n') + self._backend.write('\n\\end{enumerate}\n') newline = '' elif self.in_table: newline = ('') - self.f.write('%s%s' % (self.fend, newline)) + self._backend.write('%s%s' % (self.fend, newline)) if self.fix_indent == 1: self.fix_indent = 0 - self.f.write('\\grampsindent{0cm}\n') + self._backend.write('\\grampsindent{0cm}\n') def start_bold(self): """Bold face""" - self.f.write('\\textbf{') + self._backend.write('\\textbf{') def end_bold(self): """End bold face""" - self.f.write('}') + self._backend.write('}') def start_superscript(self): - self.f.write('\\textsuperscript{') + self._backend.write('\\textsuperscript{') def end_superscript(self): - self.f.write('}') + self._backend.write('}') def start_table(self, name,style_name): """Begin new table""" @@ -453,13 +391,13 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): self.numcols = self.tblstyle.get_columns() tblfmt = '*{%d}{l}' % self.numcols - self.f.write('\n\n\\begin{longtable}[l]{%s}\n' % tblfmt) + self._backend.write('\n\n\\begin{longtable}[l]{%s}\n' % tblfmt) def end_table(self): """Close the table environment""" self.in_table = 0 # Create a paragraph separation below the table. - self.f.write('\\end{longtable}\n\\par\n') + self._backend.write('\\end{longtable}\n\\par\n') def start_row(self): """Begin a new row""" @@ -471,14 +409,14 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): def end_row(self): """End the row (new line)""" - self.f.write('\\\\ ') + self._backend.write('\\\\ ') if self.doline == 1: if self.skipfirst == 1: - self.f.write('\\cline{2-%d}\n' % self.numcols) + self._backend.write('\\cline{2-%d}\n' % self.numcols) else: - self.f.write('\\hline \\\\ \n') + self._backend.write('\\hline \\\\ \n') else: - self.f.write('\n') + self._backend.write('\n') def start_cell(self,style_name,span=1): """Add an entry to the table. @@ -513,14 +451,14 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): self.skipfirst = 1 if self.tborder != 0: - self.f.write('\\hline\n') - self.f.write ('\\multicolumn{%d}{%s}{' % (span,cellfmt)) + self._backend.write('\\hline\n') + self._backend.write ('\\multicolumn{%d}{%s}{' % (span,cellfmt)) def end_cell(self): """Prepares for next cell""" - self.f.write('} ') + self._backend.write('} ') if self.curcol < self.numcols: - self.f.write('& ') + self._backend.write('& ') def add_media_object(self, name,pos,x,y): """Add photo to report""" @@ -538,11 +476,11 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): # x and y will be maximum width OR height in units of cm mysize = 'width=%dcm, height=%dcm,keepaspectratio' % (x,y) if pos == "right": - self.f.write('\\hfill\\includegraphics[%s]{%s}\n' % (mysize,picf)) + self._backend.write('\\hfill\\includegraphics[%s]{%s}\n' % (mysize,picf)) elif pos == "left": - self.f.write('\\includegraphics[%s]{%s}\\hfill\n' % (mysize,picf)) + self._backend.write('\\includegraphics[%s]{%s}\\hfill\n' % (mysize,picf)) else: - self.f.write('\\centerline{\\includegraphics[%s]{%s}}\n' % (mysize,picf)) + self._backend.write('\\centerline{\\includegraphics[%s]{%s}}\n' % (mysize,picf)) def write_text(self,text,mark=None): """Write the text to the file""" @@ -552,7 +490,7 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): #hard coded replace of the underline used for missing names/data text = text.replace('\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_', '\\underline{\hspace{3cm}}') - self.f.write(text) + self._backend.write(text) def write_styled_note(self, styledtext, format, style_name): """ @@ -569,72 +507,34 @@ class LaTeXDoc(BaseDoc.BaseDoc,BaseDoc.TextDoc): s_tags = styledtext.get_tags() if format == 1: #preformatted, use different escape function - BaseDoc.TextDoc.ESCAPE_FUNC = lambda x: latexescapeverbatim + self._backend.setescape(True) - markuptext = self._add_markup_from_styled(text, s_tags) + markuptext = self._backend.add_markup_from_styled(text, s_tags) #there is a problem if we write out a note in a table. No newline is # possible, the note runs over the margin into infinity. # A good solution for this ??? # A quick solution: create a minipage for the note and add that always # hoping that the user will have left sufficient room for the page - self.f.write("\\begin{minipage}{{0.8\\linewidth}}\n") + self._backend.write("\\begin{minipage}{{0.8\\linewidth}}\n") self.start_paragraph(style_name) - self.f.write(markuptext) + self._backend.write(markuptext) self.end_paragraph() #end the minipage, add trick to have a white line at bottom of note, # we assume here a note should be distinct from its surrounding. - self.f.write("\n\\vspace*{0.5cm} \n\end{minipage}\n") + self._backend.write("\n\\vspace*{0.5cm} \n\end{minipage}\n\n") if format == 1: #preformatted finished, go back to normal escape function - BaseDoc.TextDoc.ESCAPE_FUNC = lambda x: latexescape - - def _create_xmltag(self, type, value): - """ - overwrites the method in BaseDoc.TextDoc. - creates the latex tags needed for non bool style types we support: - BaseDoc.TextDoc.FONTSIZE : use different \large denomination based - on size - : very basic, in mono in the font face - then we use {\ttfamily } - """ - if type not in self.SUPPORTED_MARKUP: - return None - elif type == BaseDoc.TextDoc.FONTSIZE: - #translate size in point to something LaTeX can work with - if value >= 22: - return ("{\\Huge ", "}") - elif value >= 20: - return ("{\\huge ", "}") - elif value >= 18: - return ("{\\LARGE ", "}") - elif value >= 16: - return ("{\\Large ", "}") - elif value >= 14: - return ("{\\large ", "}") - elif value < 8: - return ("{\\scriptsize ", "}") - elif value < 10: - return ("{\\footnotesize ", "}") - elif value < 12: - return ("{\\small ", "}") - else: - return ("", "") - elif type == BaseDoc.TextDoc.FONTFACE: - if 'MONO' in value.upper(): - return ("{\\ttfamily ", "}") - elif 'ROMAN' in value.upper(): - return ("{\\rmfamily ", "}") - return None + self._backend.setescape(False) def write_note(self,text,format,style_name): """Write the note's text to the file, respecting the format""" self.start_paragraph(style_name) if format == 1: - self.f.write('\\begin{verbatim}') + self._backend.write('\\begin{verbatim}') self.write_text(text) if format == 1: - self.f.write('\\end{verbatim}') + self._backend.write('\\end{verbatim}') self.end_paragraph() #------------------------------------------------------------------------ diff --git a/src/plugins/docgen/PdfDoc.py b/src/plugins/docgen/PdfDoc.py index 92f2a23ce..bf9547cb2 100644 --- a/src/plugins/docgen/PdfDoc.py +++ b/src/plugins/docgen/PdfDoc.py @@ -86,7 +86,7 @@ class PdfDoc(libcairodoc.CairoDoc): top_margin = self.paper.get_top_margin() * DPI / 2.54 # create cairo context and pango layout - surface = cairo.PDFSurface(self._filename, paper_width, paper_height) + surface = cairo.PDFSurface(self._backend.filename, paper_width, paper_height) surface.set_fallback_resolution(300, 300) cr = pangocairo.CairoContext(cairo.Context(surface)) @@ -125,7 +125,7 @@ class PdfDoc(libcairodoc.CairoDoc): # load the result into an external viewer if self.open_req: - Utils.open_file_with_default_application(self._filename) + Utils.open_file_with_default_application(self._backend.filename) #------------------------------------------------------------------------ # diff --git a/src/plugins/lib/libcairodoc.py b/src/plugins/lib/libcairodoc.py index 6486ca4d7..ea1350607 100644 --- a/src/plugins/lib/libcairodoc.py +++ b/src/plugins/lib/libcairodoc.py @@ -32,7 +32,6 @@ #------------------------------------------------------------------------ from gettext import gettext as _ from math import radians -from xml.sax.saxutils import escape #------------------------------------------------------------------------ # @@ -43,6 +42,7 @@ import BaseDoc from ReportBase import ReportUtils from Errors import PluginError from gen.plug import PluginManager, Plugin +from docbackend import CairoBackend #------------------------------------------------------------------------ # @@ -1200,37 +1200,11 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc): page style. """ - STYLETAG_TO_PROPERTY = { - BaseDoc.TextDoc.FONTCOLOR : 'foreground', - BaseDoc.TextDoc.HIGHLIGHT : 'background', - BaseDoc.TextDoc.FONTFACE : 'face', - BaseDoc.TextDoc.FONTSIZE : 'size', - } - - # overwrite base class attributes, they become static var of CairoDoc - SUPPORTED_MARKUP = [ - BaseDoc.TextDoc.BOLD, - BaseDoc.TextDoc.ITALIC, - BaseDoc.TextDoc.UNDERLINE, - BaseDoc.TextDoc.FONTFACE, - BaseDoc.TextDoc.FONTSIZE, - BaseDoc.TextDoc.FONTCOLOR, - BaseDoc.TextDoc.HIGHLIGHT, - BaseDoc.TextDoc.SUPERSCRIPT ] - - STYLETAG_MARKUP = { - BaseDoc.TextDoc.BOLD : ("", ""), - BaseDoc.TextDoc.ITALIC : ("", ""), - BaseDoc.TextDoc.UNDERLINE : ("", ""), - BaseDoc.TextDoc.SUPERSCRIPT : ("", ""), - } - - ESCAPE_FUNC = lambda x: escape # BaseDoc implementation def open(self, filename): - self._filename = filename + self._backend = CairoBackend(filename) self._doc = GtkDocDocument() self._active_element = self._doc self._pages = [] @@ -1303,21 +1277,6 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc): def end_cell(self): self._active_element = self._active_element.get_parent() - def _create_xmltag(self, type, value): - """ - overwrites the method in BaseDoc.TextDoc. - creates the pango xml tags needed for non bool style types - """ - if type not in self.SUPPORTED_MARKUP: - return None - if type == BaseDoc.TextDoc.FONTSIZE: - #size is in thousandths of a point in pango - value = str(1000 * value) - - return ('' % (self.STYLETAG_TO_PROPERTY[type], - self.ESCAPE_FUNC()(value)), - '') - def write_note(self, text, format, style_name): """ Method to write the note objects text on a @@ -1358,7 +1317,8 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc): s_tags = styledtext.get_tags() #FIXME: following split should be regex to match \n\s*\n instead? - markuptext = self._add_markup_from_styled(text, s_tags, split='\n\n') + markuptext = self._backend.add_markup_from_styled(text, s_tags, + split='\n\n') if format == 1: #preformatted, retain whitespace. Cairo retains \n automatically, @@ -1391,7 +1351,7 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc): # calls. This way we save the markup created by the report # The markup in the note editor is not in the text so is not # considered. It must be added by pango too - text = escape(text) + text = self._backend.ESCAPE_FUNC()(text) self._active_element.add_text(text) def write_text(self, text, mark=None): @@ -1411,7 +1371,7 @@ class CairoDoc(BaseDoc.BaseDoc, BaseDoc.TextDoc, BaseDoc.DrawDoc): @param s_tags: assumed to be list of styledtexttags to apply to the text """ - markuptext = self._add_markup_from_styled(text, s_tags) + markuptext = self._backend.add_markup_from_styled(text, s_tags) self.__write_text(text, markup=True) def add_media_object(self, name, pos, x_cm, y_cm):