# # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2004 Donald N. Allingham # # Modifications and feature additions: # 2002 Donald A. Peterson # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Written by Billy C. Earney, 2003-2004 # Modified by Alex Roitman, 2004 # $Id$ """LPR document generator""" #------------------------------------------------------------------------ # # python modules # #------------------------------------------------------------------------ import string from gettext import gettext as _ #------------------------------------------------------------------------ # # GNOME/GTK Modules # #------------------------------------------------------------------------ import gtk.gdk ### FIXME ### # This is a dirty workaround for incomplete gnomeprint bindings. # Switching to local pygtk version before importing gnomeprint # (I have CVS version installed locally) import sys newpath = [ '/usr/local/lib/python2.3', '/usr/local/lib/python2.3/site-packages', '/usr/local/lib/python2.3/site-packages/gtk-2.0' ] sys.path = newpath + sys.path ### end FIXME ### import gnomeprint, gnomeprint.ui ### FIXME ### if gnomeprint.Context.__dict__.has_key('grestore'): support_photos = 1 else: support_photos = 0 print "LPRDoc: Photos and rotated text (used in TimeChart)" print "are not supported for direct priting." print "Get gnome-python from CVS or wait for the next gnome-python release." ### end FIXME ### #------------------------------------------------------------------------ # # gramps modules # #------------------------------------------------------------------------ import BaseDoc import Plugins import ImgManip #------------------------------------------------------------------------ # # Constants # #------------------------------------------------------------------------ # Spacing in points (distance between the bottoms of two adjacent lines) _LINE_SPACING = 20 # Elevation of superscripts: a fraction of it's size _SUPER_ELEVATION_FRACTION = 0.3 # Number of points to subtract to get the superscrip size _SUPER_SIZE_REDUCTION = 2 # Font constants -- specific for gnome-print _TTF_FREEFONT = ( ( 'FreeSerif Medium', 'FreeSerif Bold', 'FreeSerif Italic', 'FreeSerif BoldItalic' ), ( 'FreeSans Medium', 'FreeSans Bold', 'FreeSans Oblique', 'FreeSans BoldOblique'), ( 'FreeMono Medium', 'FreeMono Bold', 'FreeMono Oblique', 'FreeMono BoldOblique') ) _MS_TTFONT = ( ( 'Times New Roman Regular', 'Times New Roman Bold', 'Times New Roman Italic', 'Times New Roman Bold Italic' ), ( 'Arial Regular', 'Arial Bold', 'Arial Italic', 'Arial Bold Italic'), ( 'Courier New Regular', 'Courier New Bold', 'Courier New Italic', 'Courier New Bold Italic') ) _GNOME_FONT = ( ( 'Serif Regular', 'Serif Bold', 'Serif Italic', 'Serif Bold Italic' ), ( 'Sans Regular', 'Sans Bold', 'Sans Italic', 'Sans Bold Italic'), ( 'Monospace Regular', 'Monospace New Bold', 'Monospace New Italic', 'Monospace New Bold Italic') ) # Search for ttf-freefont first ttf_not_found = 0 for family in _TTF_FREEFONT: for font in family: if font not in gnomeprint.font_list(): ttf_not_found = 1 break if ttf_not_found: print "Free true type fonts not found." # Search for MS ttfs ms_not_found = 0 for family in _MS_TTFONT: for font in family: if font not in gnomeprint.font_list(): ms_not_found = 1 break if ms_not_found: print "Microsoft true type fonts not found." print "Using Gnome standard fonts." print "Non-ascii characters will appear garbled in the output." print "INSTALL Free true type fonts from http://www.nongnu.org/freefont/" _FONT_SET = _GNOME_FONT else: print "Found Microsoft true type fonts. Will use them for now." print "These fonts are not free. " print "We would advise you to switch to Free true type fonts" print "INSTALL Free true type fonts from http://www.nongnu.org/freefont/" _FONT_SET = _MS_TTFONT else: _FONT_SET = _TTF_FREEFONT # Formatting directive constants _LINE_BREAK = "Break" _BOLD = "Bold" _SUPER = "Super" _MONO = "Mono" #------------------------------------------------------------------------ # # Units conversion # #------------------------------------------------------------------------ def cm2u(cm): """ Convert cm to gnome-print units """ return cm * 72.0 / 2.54 #------------------------------------------------------------------------ # # font lookup function # #------------------------------------------------------------------------ def find_font_from_fontstyle(fontstyle): """ This function returns the gnomeprint.Font() object instance corresponding to the parameters of BaseDoc.FontStyle() object. fontstyle - a BaseDoc.FontStyle() instance """ if fontstyle.get_type_face() == BaseDoc.FONT_SERIF: family = _FONT_SET[0] elif fontstyle.get_type_face() == BaseDoc.FONT_SANS_SERIF: family = _FONT_SET[1] elif fontstyle.get_type_face() == BaseDoc.FONT_MONOSPACE: family = _FONT_SET[2] if fontstyle.get_bold(): if fontstyle.get_italic(): font = family[3] else: font = family[1] elif fontstyle.get_italic(): font = family[2] else: font = family[0] size = fontstyle.get_size() return gnomeprint.font_find_closest(font,size) #------------------------------------------------------------------------ # # basic font-specific text formatting functions # #------------------------------------------------------------------------ def get_text_width(text,fontstyle): """ This function returns the width of text using given fontstyle when not formatted. text - a text whose width to find fontstyle - a BaseDoc.FontStyle() instance """ font = find_font_from_fontstyle(fontstyle) return font.get_width_utf8(text) #------------------------------------------------------------------------ # # add to paragraph taking care of the newline characters # #------------------------------------------------------------------------ def append_to_paragraph(paragraph,directive,text): """ Add a piece to the paragraph while taking care of the newline characters. paragraph - a GnomePrintParagraph() instance directive - what to do with this piece text - the text of the corresponding piece """ if not directive and not text: return text_list = text.split('\n') for the_text in text_list[:-1]: paragraph.add_piece(directive,the_text) paragraph.add_piece(_LINE_BREAK,"") paragraph.add_piece(directive,text_list[-1:][0]) #------------------------------------------------------------------------ # # Paragraph class # #------------------------------------------------------------------------ class GnomePrintParagraph: """ A paragraph abstraction which provides the means for in-paragraph formatting. """ def __init__(self,paragraph_style): """ Creates a GnomePrintParapgrah instance. paragraph_style - an instance of BaseDoc paragraph style object """ self.style = paragraph_style self.fontstyle = self.style.get_font() self.piece_list = [] self.lines = [] self.height = None def add_piece(self,directive,text): """ Add a piece to the paragraph. directive - what to do with this piece text - the text of the corresponding piece """ self.piece_list.append((directive,text)) def get_piece_list(self): """ Return a list of pieces for the paragraph. """ return self.piece_list def get_fontstyle(self): """ Return fontstyle for the paragraph """ return self.fontstyle def get_alignment(self): """ Return requested alignment of the paragraph """ return self.style.get_alignment() def get_min_width(self): """ Determine the minimal width of the paragraph (longest word) """ max_word_size = 0 for (directive,text) in self.piece_list: fontstyle = BaseDoc.FontStyle(self.fontstyle) if directive == _BOLD: fontstyle.set_bold(1) elif directive == _SUPER: size = fontstyle.get_size() fontstyle.set_size(size-_SUPER_SIZE_REDUCTION) elif directive == _MONO: fontstyle.set_type_face(BaseDoc.FONT_MONOSPACE) for word in text.split(): length = get_text_width(word,fontstyle) if length > max_word_size: max_word_size = length return max_word_size def get_height(self,width): """ Determine the height the paragraph would have if formatted for a given width. width - required formatting width """ if not self.lines: self.format(width) return self.height def format(self,width): """ Format the paragraph for a given width. This is a complex procedure. It assembles lines from the paragraph's pieces. It also sets the height of the whole paragraph and the widths available after the lines are assembled. width - required formatting width """ if self.lines: return width = width - cm2u(self.style.get_right_margin()) \ - cm2u(self.style.get_left_margin()) nlines = 1 avail_width = width start_piece = end_piece = start_word = end_word = 0 first = 1 for piece_num in range(len(self.piece_list)): end_piece = piece_num (directive,text) = self.piece_list[piece_num] fontstyle = BaseDoc.FontStyle(self.fontstyle) if directive == _BOLD: fontstyle.set_bold(1) elif directive == _SUPER: size = fontstyle.get_size() fontstyle.set_size(size-_SUPER_SIZE_REDUCTION) elif directive == _MONO: fontstyle.set_type_face(BaseDoc.FONT_MONOSPACE) if first: first = 0 avail_width = avail_width - cm2u(self.style.get_first_indent()) if text and avail_width > get_text_width(text,fontstyle): avail_width -= get_text_width(text,fontstyle) end_word = len(text.split()) elif directive == _LINE_BREAK: nlines += 1 end_word = 0 self.lines.append((start_piece,start_word,end_piece,end_word,avail_width)) avail_width = width start_piece = end_piece start_word = 0 elif text and avail_width <= get_text_width(text,fontstyle): # divide up text textlist = text.split() the_text = "" for word_num in range(len(textlist)): word = textlist[word_num] if get_text_width(the_text + word + " ",fontstyle) <= avail_width: the_text = the_text + word + " " else: # the_text contains as much as avail_width allows nlines += 1 end_word = word_num avail_width -= get_text_width(the_text,fontstyle) self.lines.append((start_piece,start_word,end_piece,end_word,avail_width)) avail_width = width the_text = word + " " start_piece = end_piece start_word = word_num # if the_text still contains data, we will want to print it out if the_text: avail_width = width - get_text_width(the_text,fontstyle) end_word = len(textlist) self.lines.append((start_piece,start_word,end_piece,end_word,avail_width)) self.height = nlines * self.fontstyle.get_size() \ + 2 * cm2u(self.style.get_padding()) def get_lines(self): """ Return a list of assemlbed lines for the paragraph. Each element is a tuple corresponding to the line's contents: (start_piece,start_word,end_piece,end_word,avail_width) """ return self.lines #------------------------------------------------------------------------ # # Photo class # #------------------------------------------------------------------------ class GnomePrintPhoto: """ A photo abstraction which provides the means for correct photo placement. Way less complex that paragraph, but still useful. """ def __init__(self,name,pos,x_size,y_size): """ Creates a GnomePrintPhoto instance. """ self.name = name self.alignment = pos self.pixbuf = gtk.gdk.pixbuf_new_from_file(name) self.height = self.pixbuf.get_height() self.width = self.pixbuf.get_width() max_size = cm2u(max(x_size,y_size)) self.scale_x = int( max_size * float(self.width)/max(self.height,self.width) ) self.scale_y = int( max_size * float(self.height)/max(self.height,self.width) ) def get_image(self): """ Return the raw image of the photo. """ return self.pixbuf.get_pixels() def get_has_alpha(self): """ Return has_alpha of the photo. """ return self.pixbuf.get_has_alpha() def get_rowstride(self): """ Return the rowstride of the photo. """ return self.pixbuf.get_rowstride() def get_height(self,width=None): """ Return the real height of the photo as it should appear on the page. """ return self.scale_y def get_width(self): """ Return the real width of the photo as it should appear on the page. """ return self.scale_x def get_min_width(self): """ Return the minimum width of the photo as it should appear on the page. """ return self.scale_x def get_image_height(self): """ Return the height of the photo in terms of image's pixels. """ return self.height def get_image_width(self): """ Return the width of the photo in terms of image's pixels. """ return self.width #------------------------------------------------------------------------ # # LPRDoc class # #------------------------------------------------------------------------ class LPRDoc(BaseDoc.BaseDoc): """Gnome-print document interface class. Derived from BaseDoc""" #------------------------------------------------------------------------ # # General methods # #------------------------------------------------------------------------ def open(self,filename): """Sets up initialization""" #set up variables needed to keep track of which state we are in self.__in_table = 0 self.__in_cell = 0 self.__page_count = 0 self.__page_open = 0 self.paragraph = None self.__cell_data = [] self.__table_data = [] #create main variables for this print job self.__job = gnomeprint.Job(gnomeprint.config_default()) self.__pc = self.__job.get_context() #find out what the width and height of the page is width, height = gnomeprint.job_get_page_size_from_config(self.__job.get_config()) self.left_margin = cm2u(self.get_left_margin()) self.right_margin = width - cm2u(self.get_right_margin()) self.top_margin = height - cm2u(self.get_top_margin()) self.bottom_margin = cm2u(self.get_bottom_margin()) self.start_page(self) def close(self): """Clean up and close the document""" #gracefully end page before we close the doc if a page is open if self.__page_open: self.end_page() self.__job.close() self.__show_print_dialog() def start_page(self,orientation=None): """Create a new page""" #reset variables dealing with opening a page if (self.__page_open): self.end_page() self.__page_open = 1 self.__page_count += 1 self.__x = self.left_margin self.__y = self.top_margin self.__pc.beginpage(str(self.__page_count)) self.__pc.moveto(self.__x, self.__y) def end_page(self): """Close the current page""" if (self.__page_open): self.__page_open = 0 self.__pc.showpage() self.__y -= self.top_margin + _LINE_SPACING def page_break(self): "Forces a page break, creating a new page" # If we're already at the very top, relax and do nothing if self.__y != self.top_margin: self.end_page() self.start_page() #------------------------------------------------------------------------ # # Text methods # #------------------------------------------------------------------------ def line_break(self): "Forces a line break within a paragraph" # Add previously held text to the paragraph, # then add line break directive, # then start accumulating further text append_to_paragraph(self.paragraph,self.__paragraph_directive,self.__paragraph_text) self.paragraph.add_piece(_LINE_BREAK,"") self.__paragraph_text = "" def start_paragraph(self,style_name,leader=None): """Paragraphs handling - A Gramps paragraph is any single body of text, from a single word, to several sentences. We assume a linebreak at the end of each paragraph.""" # Instantiate paragraph object and initialize buffers self.paragraph = GnomePrintParagraph(self.style_list[style_name]) self.__paragraph_directive = "" self.__paragraph_text = "" if leader: self.__paragraph_text += leader + " " def end_paragraph(self): """End the current paragraph""" # Add current text/directive to paragraoh, # then either add paragrah to the list of cell's paragraphs # or print it right away if not in cell append_to_paragraph(self.paragraph,self.__paragraph_directive,self.__paragraph_text) if self.__in_cell: # We're inside cell. Add paragrah to celldata self.__cell_data.append(self.paragraph) else: # paragraph not in table: write it right away self.__x, self.__y = self.write_paragraph(self.paragraph, self.__x, self.__y, self.right_margin - self.left_margin) self.paragraph = None def start_bold(self): """Bold face""" append_to_paragraph(self.paragraph,self.__paragraph_directive,self.__paragraph_text) self.__paragraph_directive = _BOLD self.__paragraph_text = "" def end_bold(self): """End bold face""" append_to_paragraph(self.paragraph,self.__paragraph_directive,self.__paragraph_text) self.__paragraph_directive = "" self.__paragraph_text = "" def start_superscript(self): append_to_paragraph(self.paragraph,self.__paragraph_directive,self.__paragraph_text) self.__paragraph_directive = _SUPER self.__paragraph_text = "" def end_superscript(self): append_to_paragraph(self.paragraph,self.__paragraph_directive,self.__paragraph_text) self.__paragraph_directive = "" self.__paragraph_text = "" def start_table(self,name,style_name): """Begin new table""" # initialize table, compute its width, find number of columns self.__table_data = [] self.__in_table = 1 self.__tbl_style = self.table_styles[style_name] self.__ncols = self.__tbl_style.get_columns() self.rownum = -1 self.__table_width = (self.right_margin - self.left_margin) * \ self.__tbl_style.get_width() / 100.0 self.__cell_widths = [] self.__cell_styles = [] def end_table(self): """Close the table environment""" # output table contents self.__output_table() self.__in_table = 0 self.__y = self.__advance_line(self.__y) def start_row(self): """Begin a new row""" # Initialize row, compute cell widths self.__row_data = [] self.rownum = self.rownum + 1 self.cellnum = -1 self.__span = 1 self.__cell_widths.append([0] * self.__ncols) self.__cell_styles.append([None] * self.__ncols) for cell in range(self.__ncols): self.__cell_widths[self.rownum][cell] = self.__table_width * \ self.__tbl_style.get_column_width(cell) / 100.0 def end_row(self): """End the row (new line)""" # add row data to the data we have for the current table self.__table_data.append(self.__row_data) def start_cell(self,style_name,span=1): """Add an entry to the table.""" # Initialize a cell, take care of span>1 cases self.__in_cell = 1 self.__cell_data = [] self.cellnum = self.cellnum + self.__span self.__span = span self.__cell_styles[self.rownum][self.cellnum] = \ self.cell_styles[style_name] for __extra_cell in range(1,span): self.__cell_widths[self.rownum][self.cellnum] += \ self.__cell_widths[self.rownum][self.cellnum + __extra_cell] self.__cell_widths[self.rownum][self.cellnum + __extra_cell] = 0 def end_cell(self): """Prepares for next cell""" # append the cell text to the row data self.__in_cell = 0 self.__row_data.append(self.__cell_data) def add_photo(self,name,pos,x,y): """Add photo to report""" photo = GnomePrintPhoto(name,pos,x,y) if self.__in_cell: # We're inside cell. Add photo to celldata self.__cell_data.append(photo) else: # photo not in table: write it right away self.__x, self.__y = self.write_photo(photo, self.__x, self.__y, self.right_margin - self.left_margin) def write_photo(self,photo,x,y,width): """ Write the photo. photo - GnomePrintPhoto instance x,y - coordinates to start at width - allocated width """ # FIXME -- remove when gnome-python is released and hits every distro if not support_photos: return (x,y) # end FIXME width = photo.get_width() height = photo.get_height() if y - height < self.bottom_margin: self.end_page() self.start_page() y = self.__y self.__pc.gsave() self.__pc.translate(x,y-height) self.__pc.scale(width,height) if photo.get_has_alpha(): self.__pc.rgbaimage(photo.get_image(), photo.get_image_width(), photo.get_image_height(), photo.get_rowstride()) else: self.__pc.rgbimage(photo.get_image(), photo.get_image_width(), photo.get_image_height(), photo.get_rowstride()) self.__pc.grestore() x = x y = y - height return (x,y) def write_text(self,text): """Add the text to the paragraph""" # Take care of superscript tags super_count = text.count('') for num in range(super_count): start = text.find('') self.__paragraph_text = self.__paragraph_text + text[:start] append_to_paragraph(self.paragraph,self.__paragraph_directive,self.__paragraph_text) self.__paragraph_text = "" text = text[start+7:] start = text.find('') self.__paragraph_text = self.__paragraph_text + text[:start] append_to_paragraph(self.paragraph,_SUPER,self.__paragraph_text) self.__paragraph_text = "" text = text[start+8:] self.__paragraph_text = self.__paragraph_text + text def write_note(self,text,format,style_name): if format == 1: for line in text.split('\n'): self.start_paragraph(style_name) self.__paragraph_directive = _MONO self.write_text(line) self.end_paragraph() elif format == 0: for line in text.split('\n\n'): self.start_paragraph(style_name) line = line.replace('\n',' ') line = string.join(string.split(line)) self.write_text(line) self.end_paragraph() #function to help us advance a line def __advance_line(self,y,paragraph=None): if paragraph: spacing = paragraph.fontstyle.get_size() else: spacing = _LINE_SPACING new_y = y - spacing if y < self.bottom_margin: x = self.__x self.end_page() self.start_page() new_y = self.__y self.__x = x return new_y def write_paragraph(self,paragraph,x,y,width): """ Write the contents of the paragraph, observing per-piece info. paragraph - GnomePrintParagraph instance x,y - coordinates to start at width - allocated width """ if not paragraph.get_piece_list(): return (x,y) paragraph.format(width) x = x + cm2u(paragraph.style.get_left_margin()) width = width - cm2u(paragraph.style.get_right_margin()) \ - cm2u(paragraph.style.get_left_margin()) left_margin = x no_space = 0 first = 1 if y - paragraph.fontstyle.get_size() < self.bottom_margin: self.end_page() self.start_page() x = left_margin y = self.__y if y != self.top_margin: y = y - cm2u(paragraph.style.get_padding()) # Loop over lines which were assembled by paragraph.format() for (start_piece,start_word,end_piece,end_word,avail_width) \ in paragraph.get_lines(): if paragraph.get_alignment() == BaseDoc.PARA_ALIGN_CENTER: x = x + 0.5 * avail_width elif paragraph.get_alignment() == BaseDoc.PARA_ALIGN_RIGHT: x = x + avail_width elif paragraph.get_alignment() == BaseDoc.PARA_ALIGN_LEFT: pass elif paragraph.get_alignment() == BaseDoc.PARA_ALIGN_JUSTIFY: print "Paragraph justification not supported." print "Falling back to left-justified mode." if first: first = 0 x = x + cm2u(paragraph.style.get_first_indent()) y = y - paragraph.fontstyle.get_size() # Loop over pieces that constitute the line for piece_num in range(start_piece,end_piece+1): (directive,text) = paragraph.get_piece_list()[piece_num] fontstyle = BaseDoc.FontStyle(paragraph.get_fontstyle()) if directive == _BOLD: fontstyle.set_bold(1) elif directive == _SUPER: size = fontstyle.get_size() fontstyle.set_size(size-_SUPER_SIZE_REDUCTION) y = y + _SUPER_ELEVATION_FRACTION * fontstyle.get_size() elif directive == _MONO: fontstyle.set_type_face(BaseDoc.FONT_MONOSPACE) textlist = text.split() if start_piece == end_piece: the_textlist = textlist[start_word:end_word] elif piece_num > start_piece and piece_num < end_piece: the_textlist = textlist[:] elif piece_num == start_piece: the_textlist = textlist[start_word:] elif piece_num == end_piece: the_textlist = textlist[:end_word] the_text = string.join(the_textlist) if piece_num == start_piece \ or directive == _SUPER \ or no_space \ or (the_text and the_text[0] in string.punctuation): spacer = "" else: spacer = " " the_text = spacer + the_text self.__pc.setfont(find_font_from_fontstyle(fontstyle)) self.__pc.moveto(x, y) self.__pc.show(the_text) x = x + get_text_width(the_text,fontstyle) if directive == _SUPER: y = y - _SUPER_ELEVATION_FRACTION * fontstyle.get_size() # If this was the linebreak, no space on the next line's start if end_word: no_space = 0 else: no_space = 1 y = self.__advance_line(y,paragraph) x = left_margin x = x - cm2u(paragraph.style.get_left_margin()) y = y - cm2u(paragraph.style.get_padding()) return (x,y) def __output_table(self): """do calcs on data in table and output data in a formatted way""" __min_col_size = [0] * self.__ncols __max_vspace = [0] * len(self.__table_data) for __row_num in range(len(self.__table_data)): __row = self.__table_data[__row_num][:] #do calcs on each __row and keep track on max length of each column for __col in range(self.__ncols): if not self.__cell_widths[__row_num][__col]: continue padding = cm2u(self.__cell_styles[__row_num][__col].get_padding()) __max = 0 for paragraph in __row[__col]: __min = paragraph.get_min_width() if __min > __min_col_size[__col]: __min_col_size[__col] = __min __max += paragraph.get_height( self.__cell_widths[__row_num][__col]) __max += 2 * padding if __max > __max_vspace[__row_num]: __max_vspace[__row_num] = __max #is table width larger than the width of the paper? __min_table_width = 0 for __size in __min_col_size: __min_table_width = __min_table_width + __size if __min_table_width > (self.right_margin - self.left_margin): print "Table does not fit onto the page.\n" #for now we will assume left justification of tables #output data in table for __row_num in range(len(self.__table_data)): __row = self.__table_data[__row_num] # If this row puts us below the bottom, start new page here if self.__y - __max_vspace[__row_num] < self.bottom_margin: self.end_page() self.start_page() __x = self.left_margin #reset so that x is at margin col_y = self.__y # all columns start at the same height for __col in range(self.__ncols): if not self.__cell_widths[__row_num][__col]: continue self.__y = col_y padding = cm2u(self.__cell_styles [__row_num][__col].get_padding()) for paragraph in __row[__col]: if paragraph.__class__.__name__ == 'GnomePrintPhoto': write_item = self.write_photo else: write_item = self.write_paragraph junk, self.__y = write_item(paragraph, __x + padding, self.__y - padding, self.__cell_widths[__row_num][__col] \ - 2 * padding) __x = __x + self.__cell_widths[__row_num][__col] # set up margin for this row self.__y = col_y - __max_vspace[__row_num] #------------------------------------------------------------------------ # # Graphic methods # #------------------------------------------------------------------------ def horizontal_line(self): self.__pc.moveto(self.left_margin, self.__y) self.__pc.lineto(self.right_margin, self.__y) def draw_path(self,style,path): stype = self.draw_styles[style] color = [ val/255.0 for val in stype.get_fill_color()] point = path[0] x = cm2u(point[0]) + self.left_margin y = self.top_margin - cm2u(point[1]) self.__pc.moveto(x,y) for point in path[1:]: x = cm2u(point[0]) + self.left_margin y = self.top_margin - cm2u(point[1]) self.__pc.lineto(x,y) self.__pc.closepath() self.__pc.stroke() point = path[0] x = cm2u(point[0]) + self.left_margin y = self.top_margin - cm2u(point[1]) self.__pc.moveto(x,y) for point in path[1:]: x = cm2u(point[0]) + self.left_margin y = self.top_margin - cm2u(point[1]) self.__pc.lineto(x,y) self.__pc.closepath() self.__pc.setrgbcolor(color[0],color[1],color[2]) self.__pc.fill() self.__pc.setrgbcolor(0,0,0) def draw_box(self,style,text,x,y): #assuming that we start drawing box from current position x = self.left_margin + cm2u(x) y = self.top_margin - cm2u(y) box_style = self.draw_styles[style] para_name = box_style.get_paragraph_style() para_style = self.style_list[para_name] fontstyle = para_style.get_font() bh = cm2u(box_style.get_height()) bw = cm2u(box_style.get_width()) self.__pc.rect_stroked(x,y,bw,-bh) if text: lines = text.split('\n') start_x = x + 0.5 * fontstyle.get_size() start_y = y - fontstyle.get_size() for line in lines: if not line.split(): continue self.__pc.setfont(find_font_from_fontstyle(fontstyle)) self.__pc.moveto(start_x,start_y) self.__pc.show(line) start_y -= fontstyle.get_size() def write_at (self, style, text, x, y): para_style = self.style_list[style] fontstyle = para_style.get_font() self.__pc.setfont(find_font_from_fontstyle(fontstyle)) self.__pc.moveto(cm2u(x), cm2u(y)) self.__pc.show(text) def draw_bar(self, style, x1, y1, x2, y2): self.__pc.moveto(x1, y1) self.__pc.lineto(x2, y2) def draw_text(self,style,text,x,y): box_style = self.draw_styles[style] para_name = box_style.get_paragraph_style() para_style = self.style_list[para_name] fontstyle = para_style.get_font() start_x = self.left_margin + cm2u(x) start_y = self.top_margin - cm2u(y) - fontstyle.get_size() self.__pc.setfont(find_font_from_fontstyle(fontstyle)) self.__pc.moveto(start_x,start_y) self.__pc.show(text) def center_text(self,style,text,x,y): box_style = self.draw_styles[style] para_name = box_style.get_paragraph_style() para_style = self.style_list[para_name] fontstyle = para_style.get_font() width = get_text_width(text,fontstyle) start_x = self.left_margin + cm2u(x) - 0.5 * width self.__pc.setfont(find_font_from_fontstyle(fontstyle)) self.__pc.moveto(start_x, self.top_margin - cm2u(y) - fontstyle.get_size()) self.__pc.show(text) def rotate_text(self,style,text,x,y,angle): # FIXME - remove when new gnome-python is in all distros if not support_photos: return # end FIXME box_style = self.draw_styles[style] para_name = box_style.get_paragraph_style() para_style = self.style_list[para_name] fontstyle = para_style.get_font() y_start = self.top_margin - cm2u(y) x_start = self.left_margin + cm2u(x) size = fontstyle.get_size() self.__pc.gsave() self.__pc.translate(x_start,y_start) self.__pc.rotate(-angle) this_y = 0 for line in text: if not line.split(): continue width = get_text_width(line,fontstyle) this_x = -0.5 * width self.__pc.setfont(find_font_from_fontstyle(fontstyle)) self.__pc.moveto(this_x,this_y) self.__pc.show(line) this_y -= size self.__pc.grestore() def draw_line(self,style,x1,y1,x2,y2): x1 = cm2u(x1) + self.left_margin x2 = cm2u(x2) + self.left_margin y1 = self.top_margin - cm2u(y1) y2 = self.top_margin - cm2u(y2) self.__pc.line_stroked(x1,y1,x2,y2) #------------------------------------------------------------------------ # # Print job methods # #------------------------------------------------------------------------ #function to print text to a printer def __do_print(self,dialog, job): __pc = gnomeprint.Context(dialog.get_config()) job.render(__pc) __pc.close() #I believe this is a print preview def __show_preview(self, dialog): __w = gnomeprint.ui.JobPreview(self.__job, _("Print Preview")) __w.set_property('allow-grow', 1) __w.set_property('allow-shrink', 1) __w.set_transient_for(dialog) __w.show_all() #function used to get users response and do a certain #action depending on that response def __print_dialog_response(self, dialog, resp, job): if resp == gnomeprint.ui.DIALOG_RESPONSE_PREVIEW: self.__show_preview(dialog) elif resp == gnomeprint.ui.DIALOG_RESPONSE_CANCEL: dialog.destroy() elif resp == gnomeprint.ui.DIALOG_RESPONSE_PRINT: self.__do_print(dialog, self.__job) dialog.destroy() #function displays a window that allows user to choose #to print, show, etc def __show_print_dialog(self): __dialog = gnomeprint.ui.Dialog(self.__job, _("Print..."), 0) __dialog.connect('response', self.__print_dialog_response, self.__job) __dialog.show() #------------------------------------------------------------------------ # # Register the document generator with the system # #------------------------------------------------------------------------ Plugins.register_text_doc( name=_("Print..."), classref=LPRDoc, table=1, paper=1, style=1, ext="" ) Plugins.register_book_doc( _("Print..."), LPRDoc, 1, 1, 1, "") Plugins.register_draw_doc( _("Print..."), LPRDoc, 1, 1, "");