def setFont(self, family=None, style=None, size=None, font=None): """ Set the document font object, size given in points. If family, style, and/or size is given, generates a new Font object, checks to see if it is already in use, and selects it. May also use the font keyword to add an already instantiated PDFFont object. """ if size is None: size = self.font.fontsize if font is not None: newfont = font else: newfont = PDFFont(family, style, size) #Test if font is already selected if not newfont._equals(self.font): #Test if used for the first time if newfont.fontkey not in self.fonts: i = len(self.fonts) + 1 newfont._setIndex(i) self.fonts.append(newfont) #Select it self.font = newfont if(self.page.index > 0): self.SS._out('BT /F%d %.2f Tf ET' % (self.font.index, self.font.fontsize), self.page) else: del newfont
def _set_default_font(self): """ Internal method to set the initial default font. Change the font using set_font method.""" self.font = PDFFont(self.session) self.font._set_index() self.fonts.append(self.font) self.fontkeys.append(self.font.font_key)
def _setDefaultFont(self): """ Internal method to set the initial default font. Change the font using setFont method. """ self.font = PDFFont() self.font._setIndex() self.fonts.append(self.font)
def setFont(self, family, style=None, size=None): "Select a font; size given in points" if size is None: size = self.font.fontsize newfont = PDFFont(family, style, size) #Test if font is already selected if not newfont.equals(self.font): #Test if used for the first time if newfont.fontkey not in self.fonts: i = len(self.fonts) + 1 newfont.setIndex(i) self.fonts[newfont.fontkey] = newfont #Select it self.font = self.fonts[newfont.fontkey] if(self.page.number > 0): self.SS.out('BT /F%d %.2f Tf ET' % (self.font.index, self.font.fontsize), self.page) else: del newfont
def set_font(self, family=None, style='', size=None, font=None): """ Set the document font object, size given in points. If family, style, and/or size is given, generates a new Font object, checks to see if it is already in use, and selects it. """ if font: testfont = font elif isinstance(family, PDFFont): testfont = family else: # If size is not defined, keep the last size. if size is None: size = self.font.font_size # Create a font from givens to test its key if family in CORE_FONTS: testfont = PDFFont(self.session, family, style, size) else: testfont = PDFTTFont(self.session, family, style, size) testkey = testfont.font_key if testkey in self.fontkeys: index = self.fontkeys.index(testkey) self.font = self.fonts[index] if size != self.font.font_size: self.font._set_size(size) if style != self.font.style: self.font._set_style(style) else: self.font = testfont self._register_new_font(self.font) self.font.is_set = False if self.page.index > 0: self.session._out( 'BT /F%d %.2f Tf ET' % (self.font.index, self.font.font_size), self.page) self.font.is_set = True return self.font
class PDFDocument(object): def __init__(self, session): self.SS = session self.pages = [] self.fonts = [] # array of used fonts self._setDefaults() def _setDefaults(self): self._setColor() self._setFont() self.addPage() def _setColor(self): self.color = PDFColors() def _setFont(self): self.font = PDFFont() self.font.setIndex() self.fonts.append(self.font) def addPage(self): self.page = PDFPage(self.SS) self.page.setIndex(len(self.pages)) self.pages.append(self.page) def setFont(self, family, style=None, size=None): "Select a font; size given in points" if size is None: size = self.font.fontsize newfont = PDFFont(family, style, size) #Test if font is already selected if not newfont.equals(self.font): #Test if used for the first time if newfont.fontkey not in self.fonts: i = len(self.fonts) + 1 newfont.setIndex(i) self.fonts[newfont.fontkey] = newfont #Select it self.font = self.fonts[newfont.fontkey] if(self.page.number > 0): self.SS.out('BT /F%d %.2f Tf ET' % (self.font.index, self.font.fontsize), self.page) else: del newfont def setFontSize(self, size): "Set font size in points" if(self.font.fontsize == size): return else: self.setFont(self.font.family, self.font.style, size) def _getOrientationChanges(self): self.orientation_changes = [] for page in self.pages: if page.orientation_change is True: self.orientation_changes.append(page.number) else: pass return self.orientation_changes def outputPages(self): if self.orientation_changes is None: self.getOrientationChanges() else: #Page for page in self.pages: self.SS.newobj() self.SS.out('<</Type /Page') self.SS.out('/Parent 1 0 R') if page in self.orientation_changes: self.SS.out('/MediaBox [0 0 %.2f %.2f]' % (page.h, page.w)) self.SS.out('/Resources 2 0 R') self.SS.out('/Contents %s 0 R>>' % len(self.SS.objects)) self.SS.out('endobj') #Page content self.SS.newobj() self.SS.out('<<' + '/Filter /Length %s >>' % len(page.buffer)) self.SS.putstream(page.buffer) self.SS.out('endobj') def outputFonts(self): for font in self.fonts: obj = self.SS.newobj() font.setNumber(obj.id) self.SS.out('<</Type /Font') self.SS.out('/BaseFont /' + font.name) self.SS.out('/Subtype /Type1') if(font.name != 'Symbol' and font.name != 'ZapfDingbats'): self.SS.out('/Encoding /WinAnsiEncoding') self.SS.out('>>') self.SS.out('endobj') def addText(self, x, y, text): cursor = PDFCursor(x, y) text = PDFText(self.SS, self.page, self.font, self.color, cursor, text) return cursor def addTextOnCursor(self, cursor, text): text = PDFText(self.SS, self.page, self.font, self.color, cursor, text)
def _setFont(self): self.font = PDFFont() self.font.setIndex() self.fonts.append(self.font)
class PDFDocument(object): """ The Document object is the base class that is used to add and manage the content of the pdf file. Document maintains lists of pages and other resources, provides for default selections, which can be changed through the convinence methods. Note that page and text objects do not maintain fonts themselves. If they must use them (for calculating widths or such), they must have the current font passed to them. """ def __init__(self, session, orientation, layout): """Sets up a standard default document.""" self.session = session self.pages = [] self.fonts = [] self.fontkeys = [] # array of used fonts self.images = [] self.imagekeys = [] self.image_filter = None self.margins = None self.orientation_default = orientation self.layout_default = layout self.justification = 'left' self.double_spacing = None self.diffs = [] self._set_defaults() # Set Defaults def _set_defaults(self): """Set color scheme & font to defaults.""" self._set_color_scheme() self._set_default_font() self.add_page() # add first page def _set_color_scheme(self, draw_color=None, fill_color=None, text_color=None): """ Default color object is black letters & black lines.""" if draw_color is None: draw_color = PDFColor() draw_color._set_type('d') if fill_color is None: fill_color = PDFColor() fill_color._set_type('f') if text_color is None: text_color = PDFColor() text_color._set_type('t') self.draw_color = draw_color self.fill_color = fill_color self.text_color = text_color def set_text_color(self, color): if isinstance(color, PDFColor): self.text_color = color else: raise ValueError("Not a PDFColor instance") def set_fill_color(self, color): if isinstance(color, PDFColor): self.fill_color = color else: raise ValueError("Not a PDFColor instance") def set_draw_color(self, color): if isinstance(color, PDFColor): self.draw_color = color else: raise ValueError("Not a PDFColor instance") def _set_default_font(self): """ Internal method to set the initial default font. Change the font using set_font method.""" self.font = PDFFont(self.session) self.font._set_index() self.fonts.append(self.font) self.fontkeys.append(self.font.font_key) @staticmethod def get_color(): return PDFColor() # Public methods, main interface # Pages def add_page(self, page=None): """ May generate and add a PDFPage separately, or use this to generate a default page.""" if page is None: self.page = PDFPage(self.orientation_default, self.layout_default, self.margins) else: self.page = page self.page._set_index(len(self.pages)) self.pages.append(self.page) currentfont = self.font self.set_font(font=currentfont) self.session._reset_colors() def get_page(self): """Returns reference to current page object.""" return self.page def set_margins(self, left, top=None, right=None, bottom=None): if isinstance(left, PDFMargin): self.margins = left else: self.margins = PDFMargin(left, top, right, bottom) if self.page is not None: self.page.set_margins(self.margins) def set_justification(self, value='left'): if value in ['left', 'right', 'center']: self.justification = value else: raise ValueError("Incorrect value for justification %s" % value) def add_page_numbers(self, location='right', font=None, cursor=None, color=None, text1="Page %s", text2=None): self.page_numbers = location self.page_numbers_font = font self.page_numbers_cursor = cursor self.page_numbers_color = color self.page_numbers_text1 = text1 self.page_numbers_text2 = text2 def change_page_orientation(self): self.page._change_orientation() # Cursor def get_new_cursor(self): """ Returns a new default cursor """ return PDFCursor() def get_cursor(self): return self.page.cursor.copy() def set_cursor(self, x=None, y=None): if x is not None and isinstance(x, PDFCursor): self.page.cursor = x elif x is not None and y is not None: self.page.cursor = PDFCursor(x, y, True) else: raise Exception("Invalid cursor input") # Font def set_font(self, family=None, style='', size=None, font=None): """ Set the document font object, size given in points. If family, style, and/or size is given, generates a new Font object, checks to see if it is already in use, and selects it. """ if font: testfont = font elif isinstance(family, PDFFont): testfont = family else: # If size is not defined, keep the last size. if size is None: size = self.font.font_size # Create a font from givens to test its key if family in CORE_FONTS: testfont = PDFFont(self.session, family, style, size) else: testfont = PDFTTFont(self.session, family, style, size) testkey = testfont.font_key if testkey in self.fontkeys: index = self.fontkeys.index(testkey) self.font = self.fonts[index] if size != self.font.font_size: self.font._set_size(size) if style != self.font.style: self.font._set_style(style) else: self.font = testfont self._register_new_font(self.font) self.font.is_set = False if self.page.index > 0: self.session._out('BT /F%d %.2f Tf ET' % (self.font.index, self.font.font_size), self.page) self.font.is_set = True return self.font def get_font(self): """ Get the current font object. Useful for storing in variables, and switching between styles. """ return self.font def set_font_size(self, size): """Convenience method for just changing font size.""" if self.font.font_size == size: pass else: self.font._set_size(size) def get_font_size(self): return self.font.font_size def print_available_fonts(self): print PDFTTFont.available_fonts() # Writing def add_text(self, text, cursor=None, justification=None): """ Input text, short or long. Writes in order, within the defined page boundaries. Sequential add_text commands will print without additional whitespace. """ if cursor is None: cursor = self.page.cursor text = re.sub("\s\s+" , " ", text) if justification is None: justification = self.justification if '\n' in text: text_list = text.split('\n') for text in text_list: PDFText(self.session, self.page, text, self.font, self.text_color, cursor, justification, self.double_spacing) self.add_newline() else: PDFText(self.session, self.page, text, self.font, self.text_color, cursor, justification, self.double_spacing) def draw_text(self, *args, **kwargs): self.add_text(*args, **kwargs) def text(self, *args, **kwargs): self.add_text(*args, **kwargs) def double_space(self, multiplier=1): self.double_spacing = multiplier def add_newline(self, number=1): """ Starts over again at the new line. If number is specified, it will leave multiple lines.""" if isinstance(number, int): try: self.page._add_newline(self.font, number, self.double_spacing) except ValueError: self.add_page() else: raise TypeError("Number of newlines must be an integer.") def newline(self, *args, **kwargs): self.add_newline(*args, **kwargs) def add_indent(self, spaces=4): """ Adds a standard tab of 4 spaces. """ self.page._add_indent(self.font, spaces) def indent(self, *args, **kwargs): self.add_indent(*args, **kwargs) def start_block_indent(self, px=20): self.px = px self.page.cursor.x_plus(self.px) self.page.cursor.xmin = self.page.cursor.x def end_block_indent(self): self.page.cursor.xmin -= self.px self.page.cursor.x_plus(-self.px) def add_list(self, *args, **kwargs): bullet_code = 149 if 'bullet' in kwargs: if kwargs['bullet'] == 1: bullet_code = 149 elif kwargs['bullet'] == 2: bullet_code = 186 elif kwargs['bullet'] == 3: bullet_code = 150 char = chr(bullet_code) if 'force' in kwargs and kwargs['force'] is True: saved_font = self.get_font() for arg in args: self.set_font(family='helvetica', size=saved_font.font_size) self.add_text(char) self.set_font(saved_font) self.add_text(' %s' % arg) self.add_newline(2) else: for arg in args: if isinstance(arg, list): for item in arg: self.add_text(char) self.add_text(' %s' % item) self.add_newline(1) else: self.add_text(char) self.add_text(' %s' % arg) self.add_newline(2) def list(self, *args, **kwargs): self.add_list(*args, **kwargs) def add_html(self, htmltext, context=None, formats=None, cursor=None): if cursor is not None: self.set_cursor(cursor) if hasattr(htmltext, 'write'): htmltext = htmltext.read() PDFHtml(self, self.session, htmltext, formats, context) def html(self, *args, **kwargs): self.add_html(*args, **kwargs) # Shapes def add_line(self, x1=None, y1=None, x2=None, y2=None, cursor1=None, cursor2=None, stroke="solid"): if cursor1 is not None: if cursor2 is not None: pass elif x2 is not None and y2 is not None: cursor2 = self.page.cursor.copy() cursor2.x = x2 cursor2.y = y2 else: raise Exception("Line not fully specified") elif x1 is not None and y1 is not None: cursor1 = self.page.cursor.copy() cursor1.x = x1 cursor1.y = y1 if cursor2 is not None: pass elif x2 is not None and y2 is not None: cursor2 = self.page.cursor.copy() cursor2.x = x2 cursor2.y = y2 else: raise Exception("Line not fully specified") else: raise Exception("Line not specified") myline = PDFLine(self.session, self.page, cursor1, cursor2, self.draw_color, stroke) myline._draw() def draw_line(self, *args, **kwargs): self.add_line(*args, **kwargs) def line(self, *args, **kwargs): self.add_line(*args, **kwargs) def draw_horizontal_line(self): end_cursor = self.page.cursor.copy() end_cursor.x = end_cursor.xmax myline = PDFLine(self.session, self.page, self.page.cursor, end_cursor, self.draw_color, None) myline._draw() def add_horizontal_line(self): self.draw_horizontal_line() def horizontal_line(self): self.draw_horizontal_line() def draw_rectangle(self, x1=None, y1=None, x2=None, y2=None, width=None, height=None, cursor1=None, cursor2=None, style='S', stroke="solid", size=1): if cursor1 is not None: if cursor2 is not None: pass elif width is not None and height is not None: dims = PDFCursor(width, height) cursor2 = cursor1 + dims elif x2 is not None and y2 is not None: cursor2 = PDFCursor(x2, y2) else: raise Exception("Rectangle not defined") else: if x1 is not None and y1 is not None: cursor1 = PDFCursor(x1, y1) if x2 is not None and y2 is not None: cursor2 = PDFCursor(x2, y2) elif width is not None and height is not None: dims = PDFCursor(width, height) cursor2 = cursor1 + dims elif cursor2 is not None: pass else: raise Exception("Rectangle not defined") else: raise Exception("Rectangle not defined") rectangle = PDFRectangle(self.session, self.page, cursor1, cursor2, self.draw_color, self.fill_color, style, stroke, size) rectangle._draw() def add_rectangle(self, *args, **kwargs): self.draw_rectangle(*args, **kwargs) def rectangle(self, *args, **kwargs): self.draw_rectangle(*args, **kwargs) def draw_circle(self, center_cursor, radius, border_color=None, fill_color=None, style="S", stroke='solid', size=1): self.draw_ellipse(center_cursor, radius, radius, border_color, fill_color, style, stroke, size) def draw_ellipse(self, center_cursor, x_radius, y_radius, border_color=None, fill_color=None, style="S", stroke='solid', size=1): radius_cursor = PDFCursor(x_radius, y_radius) if isinstance(border_color, PDFColor): border_color = border_color else: border_color = self.draw_color if isinstance(fill_color, PDFColor): fill_color = fill_color else: fill_color = self.fill_color circle = PDFEllipse(self.session, self.page, center_cursor, radius_cursor, border_color, fill_color, style, stroke, size) circle._draw() def draw_arc(self, center_cursor, radius, starting_angle, arc_angle, inverted=False, end_angle=None, border_color=None, fill_color=None, style='S', stroke='solid', size=1): if isinstance(border_color, PDFColor): border_color = border_color else: border_color = self.draw_color if isinstance(fill_color, PDFColor): fill_color = fill_color else: fill_color = self.fill_color arc = PDFArc(self.session, self.page, center_cursor, radius, starting_angle, arc_angle, inverted, end_angle, border_color, fill_color, style, stroke, size) arc._draw() def draw_bezier_lines(self, points, color=None, style="S", stroke="solid"): save_draw_color = self.draw_color line = PDFBezier(self.session, self.page, points, color, style, stroke) self.set_draw_color(save_draw_color) # Graphs def add_line_graph(self, data, cursor, width, height, title=None, x_axis_limits=None, y_axis_limits=None, frequency=None, axis_titles=None, axis_labels=None, axis_font_size=None, line_colors=None, background=None, legend=None, dots=None, style="S", axis=True): save_draw_color = self.draw_color save_fill_color = self.fill_color save_font_size = self.get_font_size() if axis_font_size is None: self.set_font_size(8) else: self.set_font_size(axis_font_size) graph = PDFLineGraph(self.session, self.page, cursor, data, width, height, title, x_axis_limits, y_axis_limits, frequency, axis_titles, axis_labels, line_colors, background, legend, dots, style, axis) self.set_font_size(save_font_size) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) def add_xy_scatter(self, data, cursor, width, height, title=None, x_axis_limits=None, y_axis_limits=None, frequency=None, axis_titles=None, axis_labels=None, axis_font_size=None, line_colors=None, background=None, legend=None, dots=None, linear_regression=None, linear_regression_equation=None): save_draw_color = self.draw_color save_fill_color = self.fill_color save_font_size = self.get_font_size() if axis_font_size is None: self.set_font_size(8) else: self.set_font_size(axis_font_size) graph = PDFXYScatter(self.session, self.page, cursor, data, width, height, title, x_axis_limits, y_axis_limits, frequency, axis_titles, axis_labels, line_colors, background, legend, dots, linear_regression, linear_regression_equation) self.set_font_size(save_font_size) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) def add_simple_bar_chart(self, data, cursor, width, height, title=None, axis_titles=None, axis_font_size=None, y_axis_limits=None, y_axis_frequency=None, bar_style="B", bar_padding=0.1, bar_border_colors=None, bar_fill_colors=None, background=None): save_draw_color = self.draw_color save_fill_color = self.fill_color save_font_size = self.get_font_size() if axis_font_size is None: self.set_font_size(8) else: self.set_font_size(axis_font_size) graph = PDFBarChart(self.session, self.page, data, cursor, width, height, title, axis_titles, y_axis_limits, y_axis_frequency, bar_style, bar_padding, bar_border_colors, bar_fill_colors, background) self.set_font_size(save_font_size) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) def add_multi_bar_chart(self, data, cursor, width, height, title=None, axis_titles=None, axis_font_size=None, y_axis_limits=None, y_axis_frequency=None, bar_style="B", bar_padding=0.1, bar_border_colors=None, bar_fill_colors=None, background=None, legend=None): save_draw_color = self.draw_color save_fill_color = self.fill_color save_font_size = self.get_font_size() if axis_font_size is None: self.set_font_size(8) else: self.set_font_size(axis_font_size) graph = PDFMultiBarChart(self.session, self.page, data, cursor, width, height, title, axis_titles, y_axis_limits, y_axis_frequency, bar_style, bar_padding, bar_border_colors, bar_fill_colors, background, legend) self.set_font_size(save_font_size) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) def add_pie_chart(self, data, cursor, width, height, title=None, data_type="raw", fill_colors=None, labels=False, background=None, legend=None): """ Data type may be "raw" or "percent" """ save_draw_color = self.draw_color save_fill_color = self.fill_color chart = PDFPieChart(self.session, self.page, data, cursor, width, height, title, data_type, fill_colors, labels, background, legend) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) # Tables def add_table(self, rows, columns, cursor=None): if cursor is None: cursor = self.page.cursor table = PDFTable(self.session, self.page, rows, columns, cursor, self.font) return table def draw_table(self, table): if isinstance(table, PDFTable): table._draw() self.page.cursor = table.cursor else: raise Exception("Invalid Table") def add_cell_format(self, data=None, cell_font=None): if cell_font is None: cell_font = self.font if data is None: data = {} format = PDFCellFormat(data, cell_font) return format # Images def add_image(self, image, name=None): if isinstance(image, PDFImage): # It's an image object myimage = self._get_image(image.name) if not myimage: self._register_new_image(image) myimage = image elif isinstance(image, str): # Name or path image_string = image if image_string.find('.') == -1: # Not a path, treat as name myimage = self._get_image(image_string) if not myimage: raise Exception('Not a proper image path') else: # Is a path if not name: # But it doesn't have a name specified. name = os.path.splitext(image_string)[0] # Specify it myimage = self._get_image(name) if not myimage: # New image extension = os.path.splitext(image_string)[1] if extension == '.png': myimage = PDFPNG(self.session, image_string, name) elif extension == '.jpg': myimage = PDFJPG(self.session, image_string, name) else: raise Exception("Image format %s not supported" % extension) self._register_new_image(myimage) return myimage def draw_image(self, image, cursor=None, width=None, height=None): if isinstance(image, PDFImage): # It's an image object myimage = self._get_image(image.name) else: try: myimage = self._get_image(image) except: raise Exception("%s is an invalid image. Add it first.") if not cursor: imagecursor = self.page.cursor else: imagecursor = cursor myimage._set_cursor(imagecursor) myimage._set_size(width, height) myimage._draw(self.page) # If a cursor was not specified, place at the end if not cursor: self.page.cursor = myimage.cursor def set_background_image(self, image): background_cursor = PDFCursor(0, 0) background_cursor.set_bounds(xmin=0, ymin=0, xmax=self.page.width, ymax=self.page.height, ymaxmax=self.page.height) myimage = self.add_image(image) self.draw_image(myimage, background_cursor, width=self.page.width) # Private methods for outputting document def _get_image(self, image_name): if image_name in self.imagekeys: index = self.imagekeys.index(image_name) myimage = self.images[index] return myimage else: return False def _output_pages(self): """ Called by the PDFLite object to prompt creating the page objects.""" if not self.orientation_changes: self._get_orientation_changes() # Page for page in self.pages: obj = self.session._add_object() self.session._out('<</Type /Page') self.session._out('/Parent 1 0 R') if self.orientation_changes: self.session._out('/MediaBox [0 0 %.2f %.2f]' % (page.width, page.height)) self.session._out('/Resources 2 0 R') self.session._out('/Group <</Type /Group /S /Transparency /CS /DeviceRGB>>') self.session._out('/Contents %s 0 R>>' % (obj.id + 1)) self.session._out('endobj') # Page content self.session._add_object() if self.session.compression is True: textfilter = ' /Filter /FlateDecode ' page._compress() else: textfilter = '' self.session._out('<<%s/Length %s >>' % (textfilter, len(page.buffer))) self.session._put_stream(page.buffer) self.session._out('endobj') def _set_page_numbers(self): if hasattr(self, 'page_numbers'): for page in self.pages: self._add_page_number(page, len(self.pages)) def _add_page_number(self, page, number_of_pages): if self.page_numbers_font is not None: fs = 'BT /F%d %.2f Tf ET' % (self.page_numbers_font.index, self.page_numbers_font.font_size) self.session._out(fs, page) if self.page_numbers_color is not None: self.page_numbers_color._set_type('t') self.session._out(self.page_numbers_color._get_color_string(), page) text_string = self.page_numbers_text1 % (page.index + 1) if self.page_numbers_text2 is not None: text_string += self.page_numbers_text2 % number_of_pages if self.page_numbers_cursor is None: sw = self.font._string_width(text_string) y = page.page_size[1] y = y - self.page.margin.bottom if self.page_numbers == 'left': x = self.page.margin.left elif self.page_numbers == 'right': x = page.page_size[0] - page.margin.right - sw else: x = page.page_size[0] / 2 - int(sw / 2.0) cursor = PDFCursor(x, y) else: cursor = self.page_numbers_cursor text_string = '(%s)' % text_string s = 'BT %.2f %.2f Td %s Tj ET' % (cursor.x, cursor.y_prime, text_string) self.session._out(s, page) def _get_orientation_changes(self): """ Returns a list of the pages that have orientation changes.""" self.orientation_changes = [] for page in self.pages: if page.orientation_change is True: self.orientation_changes.append(page.index) else: pass return self.orientation_changes def _register_new_font(self, font): font._set_index(len(self.fonts) + 1) self.fonts.append(self.font) self.fontkeys.append(self.font.font_key) if hasattr(font, 'diffs') and font.diffs is not None: try: index_of_diff = self.diffs.index(font.diffs) except AttributeError: index_of_diff = len(self.diffs) + 1 self.diffs.append(font.diffs) font.diff_number = index_of_diff def _output_fonts(self): """ Called by the PDFLite object to prompt creating the font objects.""" self.session._save_object_number() self._output_encoding_diffs() self._output_font_files() for font in self.fonts: obj = self.session._add_object() font._set_number(obj.id) font._output() def _output_font_files(self): for font in self.fonts: if hasattr(font, 'file'): font.output_file() def _output_encoding_diffs(self): if self.diffs: for _ in self.diffs: self.session._add_object() self.session._out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [%s]>>') self.session._out('endobj') def _register_new_image(self, image): image._set_index(len(self.images) + 1) self.images.append(image) self.imagekeys.append(image.name) def _output_images(self): """ Creates reference images, that can be drawn throughout the document.""" for image in self.images: obj = self.session._add_object() image._set_number(obj.id) image._output()
class PDFDocument(object): """ The Document object is the base class that is used to add and manage the content of the pdf file. Document maintains lists of pages and other resources, provides for default selections, which can be changed through the convinence methods. Note that page and text objects do not maintain fonts themselves. If they must use them (for calculating widths or such), they must have the current font passed to them. """ def __init__(self, session): "Sets up a standard default document." self.SS = session self.pages = [] self.fonts = [] # array of used fonts self._setDefaults() def _setDefaults(self): self.setColorScheme() self._setDefaultFont() self.addPage() def setColorScheme(self, colorscheme=None): """ Default color object is black. """ if colorscheme is None: self.colorscheme = PDFColorScheme() else: if isinstance(colorscheme, PDFColorScheme): self.colorscheme = colorscheme else: raise Exception("invalid color scheme") def _setDefaultFont(self): """ Internal method to set the initial default font. Change the font using setFont method. """ self.font = PDFFont() self.font._setIndex() self.fonts.append(self.font) def addPage(self, page=None): """ May generate and add a PDFPage separately, or use this to generate a default page. """ if page is None: self.page = PDFPage() else: self.page = page self.page._setIndex(len(self.pages)) self.pages.append(self.page) currentfont = self.font self.setFont(font=currentfont) def getPage(self): "Returns reference to current page object." return self.page def setFont(self, family=None, style=None, size=None, font=None): """ Set the document font object, size given in points. If family, style, and/or size is given, generates a new Font object, checks to see if it is already in use, and selects it. May also use the font keyword to add an already instantiated PDFFont object. """ if size is None: size = self.font.fontsize if font is not None: newfont = font else: newfont = PDFFont(family, style, size) #Test if font is already selected if not newfont._equals(self.font): #Test if used for the first time if newfont.fontkey not in self.fonts: i = len(self.fonts) + 1 newfont._setIndex(i) self.fonts.append(newfont) #Select it self.font = newfont if(self.page.index > 0): self.SS._out('BT /F%d %.2f Tf ET' % (self.font.index, self.font.fontsize), self.page) else: del newfont def getFont(self): """ Get the current font object. Useful for storing in variables, and switching between styles. """ return self.font def setFontSize(self, size): "Convinence method for just changing font size." if(self.font.fontsize == size): pass else: self.setFont(self.font.family, self.font.style, size) def _getOrientationChanges(self): """ Returns a list of the pages that have orientation changes. """ self.orientation_changes = [] for page in self.pages: if page.orientation_change is True: self.orientation_changes.append(page.index) else: pass return self.orientation_changes def _outputPages(self): """ Called by the PDFLite object to prompt creating the page objects. """ if self.orientation_changes is None: self._getOrientationChanges() else: #Page for page in self.pages: self.SS._addObject() self.SS._out('<</Type /Page') self.SS._out('/Parent 1 0 R') if page in self.orientation_changes: self.SS._out('/MediaBox [0 0 %.2f %.2f]' % (page.width, page.height)) self.SS._out('/Resources 2 0 R') self.SS._out('/Contents %s 0 R>>' % len(self.SS.objects)) self.SS._out('endobj') #Page content self.SS._addObject() if self.SS.compression is True: textfilter = '/Filter /FlateDecode' page._compress() else: textfilter = '' self.SS._out('<< %s /Length %s >>' % (textfilter, len(page.buffer))) self.SS._putStream(page.buffer) self.SS._out('endobj') def _outputFonts(self): """ Called by the PDFLite object to prompt creating the font objects. """ for font in self.fonts: obj = self.SS._addObject() font._setNumber(obj.id) self.SS._out('<</Type /Font') self.SS._out('/BaseFont /' + font.name) self.SS._out('/Subtype /Type1') if(font.name != 'Symbol' and font.name != 'ZapfDingbats'): self.SS._out('/Encoding /WinAnsiEncoding') self.SS._out('>>') self.SS._out('endobj') """ The following methods are the core ways to input content. """ def addText(self, text): """ Input text, short or long. Writes in order, within the pre-defined page boundaries. Use addNewline as a return character. Sequential addText commands will print without additional whitespace. Currently all "left-justified", although that may change in future version. """ text = PDFText(self.SS, self.page, self.font, self.colorscheme, text) def addNewline(self, number=1): """ Starts over again at the new line. If number is specified, it will leave multiple lines. """ if isinstance(number, int): try: self.page.addNewline(self.font, number) except ValueError: self.addPage() else: raise TypeError("Number of newlines must be an integer.") def addIndent(self): """ Adds a standard tab of 4 spaces. """ self.page.addIndent(self.font) def addLine(self, x1=None, y1=None, x2=None, y2=None, cursor1=None, cursor2=None): if cursor1 is not None: if cursor2 is not None: pass else: cursor1 = PDFCursor(x1, y1) cursor2 = PDFCursor(x2, y2) myline = PDFLine(self.SS, self.page, self.colorscheme, cursor1, cursor2) myline.draw() def drawHorizonalLine(self): endcursor = self.page.cursor.copy() endcursor.x = endcursor.xmax myline = PDFLine(self.SS, self.page, self.colorscheme, self.page.cursor, endcursor) myline.draw() def drawRectangle(self, x1=None, y1=None, x2=None, y2=None, width=None, height=None, cursor1=None, cursor2=None, style='S'): if cursor1 is not None: if cursor2 is not None: pass elif width is not None and height is not None: dims = PDFCursor(width, height) cursor2 = cursor1.add(dims) elif x2 is not None and y2 is not None: cursor2 = PDFCursor(x2, y2) else: raise Exception("Rectanlge not defined") else: if x1 is not None and y1 is not None: cursor1 = PDFCursor(x1, y1) if x2 is not None and y2 is not None: cursor2 = PDFCursor(x2, y2) elif width is not None and height is not None: dims = PDFCursor(width, height) cursor2 = cursor1.add(dims) else: raise Exception("Rectanlge not defined") else: raise Exception("Rectanlge not defined") rect = PDFRectangle(self.SS, self.page, self.colorscheme, cursor1, cursor2, size=1, style=style) rect.draw() def addTable(self, datalist, headerlist=None, cursor=None): pass
class PDFDocument(object): """ The Document object is the base class that is used to add and manage the content of the pdf file. Document maintains lists of pages and other resources, provides for default selections, which can be changed through the convinence methods. Note that page and text objects do not maintain fonts themselves. If they must use them (for calculating widths or such), they must have the current font passed to them. """ def __init__(self, session, orientation, layout): """Sets up a standard default document.""" self.session = session self.pages = [] self.fonts = [] self.fontkeys = [] # array of used fonts self.images = [] self.imagekeys = [] self.image_filter = None self.margins = None self.orientation_default = orientation self.layout_default = layout self.justification = 'left' self.double_spacing = None self.diffs = [] self._set_defaults() # Set Defaults def _set_defaults(self): """Set color scheme & font to defaults.""" self._set_color_scheme() self._set_default_font() self.add_page() # add first page def _set_color_scheme(self, draw_color=None, fill_color=None, text_color=None): """ Default color object is black letters & black lines.""" if draw_color is None: draw_color = PDFColor() draw_color._set_type('d') if fill_color is None: fill_color = PDFColor() fill_color._set_type('f') if text_color is None: text_color = PDFColor() text_color._set_type('t') self.draw_color = draw_color self.fill_color = fill_color self.text_color = text_color def set_text_color(self, color): if isinstance(color, PDFColor): self.text_color = color else: raise ValueError("Not a PDFColor instance") def set_fill_color(self, color): if isinstance(color, PDFColor): self.fill_color = color else: raise ValueError("Not a PDFColor instance") def set_draw_color(self, color): if isinstance(color, PDFColor): self.draw_color = color else: raise ValueError("Not a PDFColor instance") def _set_default_font(self): """ Internal method to set the initial default font. Change the font using set_font method.""" self.font = PDFFont(self.session) self.font._set_index() self.fonts.append(self.font) self.fontkeys.append(self.font.font_key) @staticmethod def get_color(): return PDFColor() # Public methods, main interface # Pages def add_page(self, page=None): """ May generate and add a PDFPage separately, or use this to generate a default page.""" if page is None: self.page = PDFPage(self.orientation_default, self.layout_default, self.margins) else: self.page = page self.page._set_index(len(self.pages)) self.pages.append(self.page) currentfont = self.font self.set_font(font=currentfont) self.session._reset_colors() def get_page(self): """Returns reference to current page object.""" return self.page def set_margins(self, left, top=None, right=None, bottom=None): if isinstance(left, PDFMargin): self.margins = left else: self.margins = PDFMargin(left, top, right, bottom) if self.page is not None: self.page.set_margins(self.margins) def set_justification(self, value='left'): if value in ['left', 'right', 'center']: self.justification = value else: raise ValueError("Incorrect value for justification %s" % value) def add_page_numbers(self, location='right', font=None, cursor=None, color=None, text1="Page %s", text2=None): self.page_numbers = location self.page_numbers_font = font self.page_numbers_cursor = cursor self.page_numbers_color = color self.page_numbers_text1 = text1 self.page_numbers_text2 = text2 def change_page_orientation(self): self.page._change_orientation() # Cursor def get_new_cursor(self): """ Returns a new default cursor """ return PDFCursor() def get_cursor(self): return self.page.cursor.copy() def set_cursor(self, x=None, y=None): if x is not None and isinstance(x, PDFCursor): self.page.cursor = x elif x is not None and y is not None: self.page.cursor = PDFCursor(x, y, True) else: raise Exception("Invalid cursor input") # Font def set_font(self, family=None, style='', size=None, font=None): """ Set the document font object, size given in points. If family, style, and/or size is given, generates a new Font object, checks to see if it is already in use, and selects it. """ if font: testfont = font elif isinstance(family, PDFFont): testfont = family else: # If size is not defined, keep the last size. if size is None: size = self.font.font_size # Create a font from givens to test its key if family in CORE_FONTS: testfont = PDFFont(self.session, family, style, size) else: testfont = PDFTTFont(self.session, family, style, size) testkey = testfont.font_key if testkey in self.fontkeys: index = self.fontkeys.index(testkey) self.font = self.fonts[index] if size != self.font.font_size: self.font._set_size(size) if style != self.font.style: self.font._set_style(style) else: self.font = testfont self._register_new_font(self.font) self.font.is_set = False if self.page.index > 0: self.session._out( 'BT /F%d %.2f Tf ET' % (self.font.index, self.font.font_size), self.page) self.font.is_set = True return self.font def get_font(self): """ Get the current font object. Useful for storing in variables, and switching between styles. """ return self.font def set_font_size(self, size): """Convenience method for just changing font size.""" if self.font.font_size == size: pass else: self.font._set_size(size) def get_font_size(self): return self.font.font_size def print_available_fonts(self): print PDFTTFont.available_fonts() # Writing def add_text(self, text, cursor=None, justification=None): """ Input text, short or long. Writes in order, within the defined page boundaries. Sequential add_text commands will print without additional whitespace. """ if cursor is None: cursor = self.page.cursor text = re.sub("\s\s+", " ", text) if justification is None: justification = self.justification if '\n' in text: text_list = text.split('\n') for text in text_list: PDFText(self.session, self.page, text, self.font, self.text_color, cursor, justification, self.double_spacing) self.add_newline() else: PDFText(self.session, self.page, text, self.font, self.text_color, cursor, justification, self.double_spacing) def draw_text(self, *args, **kwargs): self.add_text(*args, **kwargs) def text(self, *args, **kwargs): self.add_text(*args, **kwargs) def double_space(self, multiplier=1): self.double_spacing = multiplier def add_newline(self, number=1): """ Starts over again at the new line. If number is specified, it will leave multiple lines.""" if isinstance(number, int): try: self.page._add_newline(self.font, number, self.double_spacing) except ValueError: self.add_page() else: raise TypeError("Number of newlines must be an integer.") def newline(self, *args, **kwargs): self.add_newline(*args, **kwargs) def add_indent(self, spaces=4): """ Adds a standard tab of 4 spaces. """ self.page._add_indent(self.font, spaces) def indent(self, *args, **kwargs): self.add_indent(*args, **kwargs) def start_block_indent(self, px=20): self.px = px self.page.cursor.x_plus(self.px) self.page.cursor.xmin = self.page.cursor.x def end_block_indent(self): self.page.cursor.xmin -= self.px self.page.cursor.x_plus(-self.px) def add_list(self, *args, **kwargs): bullet_code = 149 if 'bullet' in kwargs: if kwargs['bullet'] == 1: bullet_code = 149 elif kwargs['bullet'] == 2: bullet_code = 186 elif kwargs['bullet'] == 3: bullet_code = 150 char = chr(bullet_code) if 'force' in kwargs and kwargs['force'] is True: saved_font = self.get_font() for arg in args: self.set_font(family='helvetica', size=saved_font.font_size) self.add_text(char) self.set_font(saved_font) self.add_text(' %s' % arg) self.add_newline(2) else: for arg in args: if isinstance(arg, list): for item in arg: self.add_text(char) self.add_text(' %s' % item) self.add_newline(1) else: self.add_text(char) self.add_text(' %s' % arg) self.add_newline(2) def list(self, *args, **kwargs): self.add_list(*args, **kwargs) def add_html(self, htmltext, context=None, formats=None, cursor=None): if cursor is not None: self.set_cursor(cursor) if hasattr(htmltext, 'write'): htmltext = htmltext.read() PDFHtml(self, self.session, htmltext, formats, context) def html(self, *args, **kwargs): self.add_html(*args, **kwargs) # Shapes def add_line(self, x1=None, y1=None, x2=None, y2=None, cursor1=None, cursor2=None, stroke="solid"): if cursor1 is not None: if cursor2 is not None: pass elif x2 is not None and y2 is not None: cursor2 = self.page.cursor.copy() cursor2.x = x2 cursor2.y = y2 else: raise Exception("Line not fully specified") elif x1 is not None and y1 is not None: cursor1 = self.page.cursor.copy() cursor1.x = x1 cursor1.y = y1 if cursor2 is not None: pass elif x2 is not None and y2 is not None: cursor2 = self.page.cursor.copy() cursor2.x = x2 cursor2.y = y2 else: raise Exception("Line not fully specified") else: raise Exception("Line not specified") myline = PDFLine(self.session, self.page, cursor1, cursor2, self.draw_color, stroke) myline._draw() def draw_line(self, *args, **kwargs): self.add_line(*args, **kwargs) def line(self, *args, **kwargs): self.add_line(*args, **kwargs) def draw_horizontal_line(self): end_cursor = self.page.cursor.copy() end_cursor.x = end_cursor.xmax myline = PDFLine(self.session, self.page, self.page.cursor, end_cursor, self.draw_color, None) myline._draw() def add_horizontal_line(self): self.draw_horizontal_line() def horizontal_line(self): self.draw_horizontal_line() def draw_rectangle(self, x1=None, y1=None, x2=None, y2=None, width=None, height=None, cursor1=None, cursor2=None, style='S', stroke="solid", size=1): if cursor1 is not None: if cursor2 is not None: pass elif width is not None and height is not None: dims = PDFCursor(width, height) cursor2 = cursor1 + dims elif x2 is not None and y2 is not None: cursor2 = PDFCursor(x2, y2) else: raise Exception("Rectangle not defined") else: if x1 is not None and y1 is not None: cursor1 = PDFCursor(x1, y1) if x2 is not None and y2 is not None: cursor2 = PDFCursor(x2, y2) elif width is not None and height is not None: dims = PDFCursor(width, height) cursor2 = cursor1 + dims elif cursor2 is not None: pass else: raise Exception("Rectangle not defined") else: raise Exception("Rectangle not defined") rectangle = PDFRectangle(self.session, self.page, cursor1, cursor2, self.draw_color, self.fill_color, style, stroke, size) rectangle._draw() def add_rectangle(self, *args, **kwargs): self.draw_rectangle(*args, **kwargs) def rectangle(self, *args, **kwargs): self.draw_rectangle(*args, **kwargs) def draw_circle(self, center_cursor, radius, border_color=None, fill_color=None, style="S", stroke='solid', size=1): self.draw_ellipse(center_cursor, radius, radius, border_color, fill_color, style, stroke, size) def draw_ellipse(self, center_cursor, x_radius, y_radius, border_color=None, fill_color=None, style="S", stroke='solid', size=1): radius_cursor = PDFCursor(x_radius, y_radius) if isinstance(border_color, PDFColor): border_color = border_color else: border_color = self.draw_color if isinstance(fill_color, PDFColor): fill_color = fill_color else: fill_color = self.fill_color circle = PDFEllipse(self.session, self.page, center_cursor, radius_cursor, border_color, fill_color, style, stroke, size) circle._draw() def draw_arc(self, center_cursor, radius, starting_angle, arc_angle, inverted=False, end_angle=None, border_color=None, fill_color=None, style='S', stroke='solid', size=1): if isinstance(border_color, PDFColor): border_color = border_color else: border_color = self.draw_color if isinstance(fill_color, PDFColor): fill_color = fill_color else: fill_color = self.fill_color arc = PDFArc(self.session, self.page, center_cursor, radius, starting_angle, arc_angle, inverted, end_angle, border_color, fill_color, style, stroke, size) arc._draw() def draw_bezier_lines(self, points, color=None, style="S", stroke="solid"): save_draw_color = self.draw_color line = PDFBezier(self.session, self.page, points, color, style, stroke) self.set_draw_color(save_draw_color) # Graphs def add_line_graph(self, data, cursor, width, height, title=None, x_axis_limits=None, y_axis_limits=None, frequency=None, axis_titles=None, axis_labels=None, axis_font_size=None, line_colors=None, background=None, legend=None, dots=None, style="S", axis=True): save_draw_color = self.draw_color save_fill_color = self.fill_color save_font_size = self.get_font_size() if axis_font_size is None: self.set_font_size(8) else: self.set_font_size(axis_font_size) graph = PDFLineGraph(self.session, self.page, cursor, data, width, height, title, x_axis_limits, y_axis_limits, frequency, axis_titles, axis_labels, line_colors, background, legend, dots, style, axis) self.set_font_size(save_font_size) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) def add_xy_scatter(self, data, cursor, width, height, title=None, x_axis_limits=None, y_axis_limits=None, frequency=None, axis_titles=None, axis_labels=None, axis_font_size=None, line_colors=None, background=None, legend=None, dots=None, linear_regression=None, linear_regression_equation=None): save_draw_color = self.draw_color save_fill_color = self.fill_color save_font_size = self.get_font_size() if axis_font_size is None: self.set_font_size(8) else: self.set_font_size(axis_font_size) graph = PDFXYScatter(self.session, self.page, cursor, data, width, height, title, x_axis_limits, y_axis_limits, frequency, axis_titles, axis_labels, line_colors, background, legend, dots, linear_regression, linear_regression_equation) self.set_font_size(save_font_size) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) def add_simple_bar_chart(self, data, cursor, width, height, title=None, axis_titles=None, axis_font_size=None, y_axis_limits=None, y_axis_frequency=None, bar_style="B", bar_padding=0.1, bar_border_colors=None, bar_fill_colors=None, background=None): save_draw_color = self.draw_color save_fill_color = self.fill_color save_font_size = self.get_font_size() if axis_font_size is None: self.set_font_size(8) else: self.set_font_size(axis_font_size) graph = PDFBarChart(self.session, self.page, data, cursor, width, height, title, axis_titles, y_axis_limits, y_axis_frequency, bar_style, bar_padding, bar_border_colors, bar_fill_colors, background) self.set_font_size(save_font_size) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) def add_multi_bar_chart(self, data, cursor, width, height, title=None, axis_titles=None, axis_font_size=None, y_axis_limits=None, y_axis_frequency=None, bar_style="B", bar_padding=0.1, bar_border_colors=None, bar_fill_colors=None, background=None, legend=None): save_draw_color = self.draw_color save_fill_color = self.fill_color save_font_size = self.get_font_size() if axis_font_size is None: self.set_font_size(8) else: self.set_font_size(axis_font_size) graph = PDFMultiBarChart(self.session, self.page, data, cursor, width, height, title, axis_titles, y_axis_limits, y_axis_frequency, bar_style, bar_padding, bar_border_colors, bar_fill_colors, background, legend) self.set_font_size(save_font_size) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) def add_pie_chart(self, data, cursor, width, height, title=None, data_type="raw", fill_colors=None, labels=False, background=None, legend=None): """ Data type may be "raw" or "percent" """ save_draw_color = self.draw_color save_fill_color = self.fill_color chart = PDFPieChart(self.session, self.page, data, cursor, width, height, title, data_type, fill_colors, labels, background, legend) self.set_draw_color(save_draw_color) self.set_fill_color(save_fill_color) # Tables def add_table(self, rows, columns, cursor=None): if cursor is None: cursor = self.page.cursor table = PDFTable(self.session, self.page, rows, columns, cursor, self.font) return table def draw_table(self, table): if isinstance(table, PDFTable): table._draw() self.page.cursor = table.cursor else: raise Exception("Invalid Table") def add_cell_format(self, data=None, cell_font=None): if cell_font is None: cell_font = self.font if data is None: data = {} format = PDFCellFormat(data, cell_font) return format # Images def add_image(self, image, name=None): if isinstance(image, PDFImage): # It's an image object myimage = self._get_image(image.name) if not myimage: self._register_new_image(image) myimage = image elif isinstance(image, str): # Name or path image_string = image if image_string.find('.') == -1: # Not a path, treat as name myimage = self._get_image(image_string) if not myimage: raise Exception('Not a proper image path') else: # Is a path if not name: # But it doesn't have a name specified. name = os.path.splitext(image_string)[0] # Specify it myimage = self._get_image(name) if not myimage: # New image extension = os.path.splitext(image_string)[1] if extension == '.png': myimage = PDFPNG(self.session, image_string, name) elif extension == '.jpg': myimage = PDFJPG(self.session, image_string, name) else: raise Exception("Image format %s not supported" % extension) self._register_new_image(myimage) return myimage def draw_image(self, image, cursor=None, width=None, height=None): if isinstance(image, PDFImage): # It's an image object myimage = self._get_image(image.name) else: try: myimage = self._get_image(image) except: raise Exception("%s is an invalid image. Add it first.") if not cursor: imagecursor = self.page.cursor else: imagecursor = cursor myimage._set_cursor(imagecursor) myimage._set_size(width, height) myimage._draw(self.page) # If a cursor was not specified, place at the end if not cursor: self.page.cursor = myimage.cursor def set_background_image(self, image): background_cursor = PDFCursor(0, 0) background_cursor.set_bounds(xmin=0, ymin=0, xmax=self.page.width, ymax=self.page.height, ymaxmax=self.page.height) myimage = self.add_image(image) self.draw_image(myimage, background_cursor, width=self.page.width) # Private methods for outputting document def _get_image(self, image_name): if image_name in self.imagekeys: index = self.imagekeys.index(image_name) myimage = self.images[index] return myimage else: return False def _output_pages(self): """ Called by the PDFLite object to prompt creating the page objects.""" if not self.orientation_changes: self._get_orientation_changes() # Page for page in self.pages: obj = self.session._add_object() self.session._out('<</Type /Page') self.session._out('/Parent 1 0 R') if self.orientation_changes: self.session._out('/MediaBox [0 0 %.2f %.2f]' % (page.width, page.height)) self.session._out('/Resources 2 0 R') self.session._out( '/Group <</Type /Group /S /Transparency /CS /DeviceRGB>>') self.session._out('/Contents %s 0 R>>' % (obj.id + 1)) self.session._out('endobj') # Page content self.session._add_object() if self.session.compression is True: textfilter = ' /Filter /FlateDecode ' page._compress() else: textfilter = '' self.session._out('<<%s/Length %s >>' % (textfilter, len(page.buffer))) self.session._put_stream(page.buffer) self.session._out('endobj') def _set_page_numbers(self): if hasattr(self, 'page_numbers'): for page in self.pages: self._add_page_number(page, len(self.pages)) def _add_page_number(self, page, number_of_pages): if self.page_numbers_font is not None: fs = 'BT /F%d %.2f Tf ET' % (self.page_numbers_font.index, self.page_numbers_font.font_size) self.session._out(fs, page) if self.page_numbers_color is not None: self.page_numbers_color._set_type('t') self.session._out(self.page_numbers_color._get_color_string(), page) text_string = self.page_numbers_text1 % (page.index + 1) if self.page_numbers_text2 is not None: text_string += self.page_numbers_text2 % number_of_pages if self.page_numbers_cursor is None: sw = self.font._string_width(text_string) y = page.page_size[1] y = y - self.page.margin.bottom if self.page_numbers == 'left': x = self.page.margin.left elif self.page_numbers == 'right': x = page.page_size[0] - page.margin.right - sw else: x = page.page_size[0] / 2 - int(sw / 2.0) cursor = PDFCursor(x, y) else: cursor = self.page_numbers_cursor text_string = '(%s)' % text_string s = 'BT %.2f %.2f Td %s Tj ET' % (cursor.x, cursor.y_prime, text_string) self.session._out(s, page) def _get_orientation_changes(self): """ Returns a list of the pages that have orientation changes.""" self.orientation_changes = [] for page in self.pages: if page.orientation_change is True: self.orientation_changes.append(page.index) else: pass return self.orientation_changes def _register_new_font(self, font): font._set_index(len(self.fonts) + 1) self.fonts.append(self.font) self.fontkeys.append(self.font.font_key) if hasattr(font, 'diffs') and font.diffs is not None: try: index_of_diff = self.diffs.index(font.diffs) except AttributeError: index_of_diff = len(self.diffs) + 1 self.diffs.append(font.diffs) font.diff_number = index_of_diff def _output_fonts(self): """ Called by the PDFLite object to prompt creating the font objects.""" self.session._save_object_number() self._output_encoding_diffs() self._output_font_files() for font in self.fonts: obj = self.session._add_object() font._set_number(obj.id) font._output() def _output_font_files(self): for font in self.fonts: if hasattr(font, 'file'): font.output_file() def _output_encoding_diffs(self): if self.diffs: for _ in self.diffs: self.session._add_object() self.session._out( '<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [%s]>>' ) self.session._out('endobj') def _register_new_image(self, image): image._set_index(len(self.images) + 1) self.images.append(image) self.imagekeys.append(image.name) def _output_images(self): """ Creates reference images, that can be drawn throughout the document.""" for image in self.images: obj = self.session._add_object() image._set_number(obj.id) image._output()