def toParagraphStyle(self, first, full=False): style = ParagraphStyle('default%d' % self.UID(), keepWithNext=first.keepWithNext) style.fontName = first.fontName style.fontSize = first.fontSize style.leading = max(first.leading, first.fontSize * 1.25) style.backColor = first.backColor style.spaceBefore = first.spaceBefore style.spaceAfter = first.spaceAfter style.leftIndent = first.leftIndent style.rightIndent = first.rightIndent style.firstLineIndent = first.firstLineIndent style.textColor = first.textColor style.alignment = first.alignment style.bulletFontName = first.bulletFontName or first.fontName style.bulletFontSize = first.fontSize style.bulletIndent = first.bulletIndent # Border handling for Paragraph style.borderWidth = 0 if getBorderStyle(first.borderTopStyle): style.borderWidth = max(first.borderLeftWidth, first.borderRightWidth, first.borderTopWidth, first.borderBottomWidth) style.borderPadding = first.borderPadding # + first.borderWidth style.borderColor = first.borderTopColor # If no border color is given, the text color is used (XXX Tables!) if (style.borderColor is None) and style.borderWidth: style.borderColor = first.textColor if full: style.fontName = tt2ps(first.fontName, first.bold, first.italic) return style
def addPara(self, force=False): # Cleanup the trail for frag in reversed(self.fragList): frag.text = frag.text.rstrip() if frag.text: break if force or (self.text.strip() and self.fragList): # Strip trailing whitespaces # for f in self.fragList: # f.text = f.text.lstrip() # if f.text: # break # self.fragList[-1].lineBreak = self.fragList[-1].text.rstrip() # Update paragraph style by style of first fragment first = self.fragBlock style = ParagraphStyle("default%d" % self.UID(), keepWithNext=first.keepWithNext) style.fontName = first.fontName style.fontSize = first.fontSize style.leading = max(first.leading, first.fontSize * 1.25) style.backColor = first.backColor style.spaceBefore = first.spaceBefore style.spaceAfter = first.spaceAfter style.leftIndent = first.leftIndent style.rightIndent = first.rightIndent style.firstLineIndent = first.firstLineIndent style.alignment = first.alignment style.bulletFontName = first.fontName style.bulletFontSize = first.fontSize style.bulletIndent = first.bulletIndent style.borderWidth = max( first.borderLeftWidth, first.borderRightWidth, first.borderTopWidth, first.borderBottomWidth ) style.borderPadding = first.borderPadding # + first.borderWidth style.borderColor = first.borderTopColor # borderRadius: None, # print repr(self.text.strip()), style.leading, "".join([repr(x.text) for x in self.fragList]) # print first.leftIndent, first.listStyleType,repr(self.text) # Add paragraph to story para = PmlParagraph( self.text, style, frags=self.fragAnchor + self.fragList, bulletText=copy.copy(first.bulletText) ) para.outline = frag.outline para.outlineLevel = frag.outlineLevel para.outlineOpen = frag.outlineOpen self.addStory(para) self.fragAnchor = [] first.bulletText = None self.clearFrag()
def toParagraphStyle(self, first): style = ParagraphStyle('default%d' % self.UID(), keepWithNext=first.keepWithNext) style.fontName = first.fontName style.fontSize = first.fontSize style.letterSpacing = first.letterSpacing style.leading = max(first.leading + first.leadingSpace, first.fontSize * 1.25) style.backColor = first.backColor style.spaceBefore = first.spaceBefore style.spaceAfter = first.spaceAfter style.leftIndent = first.leftIndent style.rightIndent = first.rightIndent style.firstLineIndent = first.firstLineIndent style.textColor = first.textColor style.alignment = first.alignment style.bulletFontName = first.bulletFontName or first.fontName style.bulletFontSize = first.fontSize style.bulletIndent = first.bulletIndent style.wordWrap = first.wordWrap # Border handling for Paragraph # Transfer the styles for each side of the border, *not* the whole # border values that reportlab supports. We'll draw them ourselves in # PmlParagraph. style.borderTopStyle = first.borderTopStyle style.borderTopWidth = first.borderTopWidth style.borderTopColor = first.borderTopColor style.borderBottomStyle = first.borderBottomStyle style.borderBottomWidth = first.borderBottomWidth style.borderBottomColor = first.borderBottomColor style.borderLeftStyle = first.borderLeftStyle style.borderLeftWidth = first.borderLeftWidth style.borderLeftColor = first.borderLeftColor style.borderRightStyle = first.borderRightStyle style.borderRightWidth = first.borderRightWidth style.borderRightColor = first.borderRightColor # If no border color is given, the text color is used (XXX Tables!) if (style.borderTopColor is None) and style.borderTopWidth: style.borderTopColor = first.textColor if (style.borderBottomColor is None) and style.borderBottomWidth: style.borderBottomColor = first.textColor if (style.borderLeftColor is None) and style.borderLeftWidth: style.borderLeftColor = first.textColor if (style.borderRightColor is None) and style.borderRightWidth: style.borderRightColor = first.textColor style.borderPadding = first.borderPadding style.paddingTop = first.paddingTop style.paddingBottom = first.paddingBottom style.paddingLeft = first.paddingLeft style.paddingRight = first.paddingRight style.fontName = tt2ps(first.fontName, first.bold, first.italic) return style
def cover(self): """ Display a cover. """ # Define a style for the cover cover = ParagraphStyle("Cover") cover.textColor = "black" cover.borderColor = "black" cover.borderPadding = 80 cover.borderWidth = 1 cover.alignment = TA_CENTER cover.fontSize = 30 cover.borderRadius = 20 cover.backColor = "gray" cover.leading = 40 pagesize = self.templates["OneCol"]["pagesize"] self.story.append(Cover(pagesize[0], pagesize[1] / 3, self.author, self.client, self.poweredby, self.project, self.timepoint, self.subject, self.date)) self.story.append(Spacer(0, pagesize[1] / 2)) self.story.append(Paragraph(self.title, cover))
def cover(self): """ Display a cover. """ # Define a style for the cover cover = ParagraphStyle("Cover") cover.textColor = "black" cover.borderColor = "black" cover.borderPadding = 80 cover.borderWidth = 1 cover.alignment = TA_CENTER cover.fontSize = 30 cover.borderRadius = 20 cover.backColor = "gray" cover.leading = 40 pagesize = self.templates["OneCol"]["pagesize"] self.story.append( Cover(pagesize[0], pagesize[1] / 3, self.author, self.client, self.poweredby, self.project, self.timepoint, self.subject, self.date)) self.story.append(Spacer(0, pagesize[1] / 2)) self.story.append(Paragraph(self.title, cover))
def update_paragraph_style(default_style: ParagraphStyle, bnml_style: Dict[str, Any]): """Replaces ReportLab ParagraphStyle attributes with Kassia bnml attributes. :param default_style: The default ParagraphStyle (a ReportLab class). :param bnml_style: A dictionary of styles read a Kassia bnml file. The bnml_style needs to have ben already run through fill_dict_attributes(). """ if 'font_family' in bnml_style and font_reader.is_registered_font( bnml_style['font_family']): default_style.fontName = bnml_style['font_family'] if 'font_size' in bnml_style: default_style.fontSize = bnml_style['font_size'] if 'color' in bnml_style: default_style.textColor = bnml_style['color'] if 'bgcolor' in bnml_style: default_style.backColor = bnml_style['bgcolor'] if 'align' in bnml_style: default_style.alignment = bnml_style['align'] if 'first_line_indent' in bnml_style: default_style.firstLineIndent = bnml_style['first_line_indent'] if 'auto_leading' in bnml_style: default_style.autoLeading = bnml_style['auto_leading'] if 'leading' in bnml_style: default_style.leading = bnml_style['leading'] if 'left_indent' in bnml_style: default_style.leftIndent = bnml_style['left_indent'] if 'right_indent' in bnml_style: default_style.rightIndent = bnml_style['right_indent'] if 'space_before' in bnml_style: default_style.spaceBefore = bnml_style['space_before'] if 'space_after' in bnml_style: default_style.spaceAfter = bnml_style['space_after'] if 'word_spacing' in bnml_style: default_style.wordSpace = bnml_style['word_spacing'] if 'border_width' in bnml_style: default_style.borderWidth = bnml_style['border_width'] if 'border_color' in bnml_style: default_style.borderColor = bnml_style['border_color'] return default_style
def toParagraphStyle(self, first, full=False): style = ParagraphStyle('default%d' % self.UID(), keepWithNext=first.keepWithNext) style.fontName = first.fontName style.fontSize = first.fontSize style.leading = max(first.leading, first.fontSize * 1.25) style.backColor = first.backColor style.spaceBefore = first.spaceBefore style.spaceAfter = first.spaceAfter style.leftIndent = first.leftIndent style.rightIndent = first.rightIndent style.firstLineIndent = first.firstLineIndent style.textColor = first.textColor style.alignment = first.alignment style.bulletFontName = first.bulletFontName or first.fontName style.bulletFontSize = first.fontSize style.bulletIndent = first.bulletIndent # Border handling for Paragraph # Transfer the styles for each side of the border, *not* the whole # border values that reportlab supports. We'll draw them ourselves in # PmlParagraph. style.borderTopStyle = first.borderTopStyle style.borderTopWidth = first.borderTopWidth style.borderTopColor = first.borderTopColor style.borderBottomStyle = first.borderBottomStyle style.borderBottomWidth = first.borderBottomWidth style.borderBottomColor = first.borderBottomColor style.borderLeftStyle = first.borderLeftStyle style.borderLeftWidth = first.borderLeftWidth style.borderLeftColor = first.borderLeftColor style.borderRightStyle = first.borderRightStyle style.borderRightWidth = first.borderRightWidth style.borderRightColor = first.borderRightColor # If no border color is given, the text color is used (XXX Tables!) if (style.borderTopColor is None) and style.borderTopWidth: style.borderTopColor = first.textColor if (style.borderBottomColor is None) and style.borderBottomWidth: style.borderBottomColor = first.textColor if (style.borderLeftColor is None) and style.borderLeftWidth: style.borderLeftColor = first.textColor if (style.borderRightColor is None) and style.borderRightWidth: style.borderRightColor = first.textColor style.borderPadding = first.borderPadding style.paddingTop = first.paddingTop style.paddingBottom = first.paddingBottom style.paddingLeft = first.paddingLeft style.paddingRight = first.paddingRight # This is the old code replaced by the above, kept for reference #style.borderWidth = 0 #if getBorderStyle(first.borderTopStyle): # style.borderWidth = max(first.borderLeftWidth, first.borderRightWidth, first.borderTopWidth, first.borderBottomWidth) # style.borderPadding = first.borderPadding # + first.borderWidth # style.borderColor = first.borderTopColor # # If no border color is given, the text color is used (XXX Tables!) # if (style.borderColor is None) and style.borderWidth: # style.borderColor = first.textColor if full: style.fontName = tt2ps(first.fontName, first.bold, first.italic) return style
def makeStory(): story = [] a = story.append styleSheet = getSampleStyleSheet() h1 = styleSheet['Heading1'] h1.pageBreakBefore = 1 h1.keepWithNext = 1 h2 = styleSheet['Heading2'] h2.frameBreakBefore = 1 h2.keepWithNext = 1 h3 = styleSheet['Heading3'] h3.backColor = colors.cyan h3.keepWithNext = 1 bt = styleSheet['BodyText'] btj = ParagraphStyle('bodyText1j', parent=bt, alignment=TA_JUSTIFY) btr = ParagraphStyle('bodyText1r', parent=bt, alignment=TA_RIGHT) btc = ParagraphStyle('bodyText1c', parent=bt, alignment=TA_CENTER) from reportlab.lib.utils import TimeStamp ts = TimeStamp() a( Paragraph( """ <a name='top'/>Subsequent pages test pageBreakBefore, frameBreakBefore and keepTogether attributes. Generated at %s. The number in brackets at the end of each paragraph is its position in the story. (%d)""" % (ts.asctime, len(story)), bt)) for i in range(10): a( Paragraph( 'Heading 1 always starts a new page (%d)' % len(story), h1)) for j in range(3): a( Paragraph( 'Heading1 paragraphs should always' 'have a page break before. Heading 2 on the other hand' 'should always have a FRAME break before (%d)' % len(story), bt)) a( Paragraph( 'Heading 2 always starts a new frame (%d)' % len(story), h2)) a( Paragraph( 'Heading1 paragraphs should always' 'have a page break before. Heading 2 on the other hand' 'should always have a FRAME break before (%d)' % len(story), bt)) for j in range(3): a( Paragraph( RT((i, j, 0), theme=PYTHON, sentences=2) + ' (%d)' % len(story), bt)) a( Paragraph( 'I should never be at the bottom of a frame (%d)' % len(story), h3)) a( Paragraph( RT((i, j, 1), theme=PYTHON, sentences=1) + ' (%d)' % len(story), bt)) for align, bts in [('left', bt), ('JUSTIFIED', btj), ('RIGHT', btr), ('CENTER', btc)]: a(Paragraph('Now we do <br/> tests(align=%s)' % align, h1)) a(Paragraph('First off no br tags', h3)) a(Paragraph(_text1, bts)) a(Paragraph("<br/> after 'the' in line 4", h3)) a( Paragraph( _text1.replace('forms of the', 'forms of the<br/>', 1), bts)) a(Paragraph("2*<br/> after 'the' in line 4", h3)) a( Paragraph( _text1.replace('forms of the', 'forms of the<br/><br/>', 1), bts)) a(Paragraph("<br/> after 'I suggested ' in line 5", h3)) a( Paragraph( _text1.replace('I suggested ', 'I suggested<br/>', 1), bts)) a(Paragraph("2*<br/> after 'I suggested ' in line 5", h3)) a( Paragraph( _text1.replace('I suggested ', 'I suggested<br/><br/>', 1), bts)) a(Paragraph("<br/> at the end of the paragraph!", h3)) a(Paragraph("""text one<br/>text two<br/>""", bts)) a( Paragraph( "Border with <br/> at the end of the paragraph!", h3)) bt1 = ParagraphStyle('bodyText1', bts) bt1.borderWidth = 0.5 bt1.borderColor = colors.toColor('red') bt1.backColor = colors.pink bt1.borderRadius = 2 bt1.borderPadding = 3 a(Paragraph("""text one<br/>text two<br/>""", bt1)) a( Paragraph("Border no <br/> at the end of the paragraph!", h3)) bt1 = ParagraphStyle('bodyText1', bts) bt1.borderWidth = 0.5 bt1.borderColor = colors.toColor('red') bt1.backColor = colors.pink bt1.borderRadius = 2 bt1.borderPadding = 3 a(Paragraph("""text one<br/>text two""", bt1)) a(Paragraph("Different border style!", h3)) bt2 = ParagraphStyle('bodyText1', bt1) bt2.borderWidth = 1.5 bt2.borderColor = colors.toColor('blue') bt2.backColor = colors.gray bt2.borderRadius = 3 bt2.borderPadding = 3 a(Paragraph("""text one<br/>text two<br/>""", bt2)) for i in 0, 1, 2: P = Paragraph( """This is a paragraph with <font color='blue'><a href='#top'>with an incredibly long and boring link in side of it that contains lots and lots of stupidly boring and worthless information. So that we can split the link and see if we get problems like Dinu's. I hope we don't, but you never do Know.</a></font>""", bt) a(P) return story
def _test0(self): "This makes one long multi-page paragraph." # Build story. story = [] a = story.append styleSheet = getSampleStyleSheet() h1 = styleSheet["Heading1"] h1.pageBreakBefore = 1 h1.keepWithNext = 1 h2 = styleSheet["Heading2"] h2.frameBreakBefore = 1 h2.keepWithNext = 1 h3 = styleSheet["Heading3"] h3.backColor = colors.cyan h3.keepWithNext = 1 bt = styleSheet["BodyText"] a( Paragraph( """ Subsequent pages test pageBreakBefore, frameBreakBefore and keepTogether attributes. Generated at %s. The number in brackets at the end of each paragraph is its position in the story. (%d)""" % (time.ctime(time.time()), len(story)), bt, ) ) for i in xrange(10): a(Paragraph("Heading 1 always starts a new page (%d)" % len(story), h1)) for j in xrange(3): a( Paragraph( "Heading1 paragraphs should always" "have a page break before. Heading 2 on the other hand" "should always have a FRAME break before (%d)" % len(story), bt, ) ) a(Paragraph("Heading 2 always starts a new frame (%d)" % len(story), h2)) a( Paragraph( "Heading1 paragraphs should always" "have a page break before. Heading 2 on the other hand" "should always have a FRAME break before (%d)" % len(story), bt, ) ) for j in xrange(3): a(Paragraph(randomText(theme=PYTHON, sentences=2) + " (%d)" % len(story), bt)) a(Paragraph("I should never be at the bottom of a frame (%d)" % len(story), h3)) a(Paragraph(randomText(theme=PYTHON, sentences=1) + " (%d)" % len(story), bt)) a(Paragraph("Now we do <br/> tests", h1)) a(Paragraph("First off no br tags", h3)) a(Paragraph(_text1, bt)) a(Paragraph("<br/> after 'the' in line 4", h3)) a(Paragraph(_text1.replace("forms of the", "forms of the<br/>", 1), bt)) a(Paragraph("2*<br/> after 'the' in line 4", h3)) a(Paragraph(_text1.replace("forms of the", "forms of the<br/><br/>", 1), bt)) a(Paragraph("<br/> after 'I suggested ' in line 5", h3)) a(Paragraph(_text1.replace("I suggested ", "I suggested<br/>", 1), bt)) a(Paragraph("2*<br/> after 'I suggested ' in line 5", h3)) a(Paragraph(_text1.replace("I suggested ", "I suggested<br/><br/>", 1), bt)) a(Paragraph("<br/> at the end of the paragraph!", h3)) a(Paragraph("""text one<br/>text two<br/>""", bt)) a(Paragraph("Border with <nr/> at the end of the paragraph!", h3)) bt1 = ParagraphStyle("bodyText1", bt) bt1.borderWidth = 0.5 bt1.borderColor = colors.toColor("red") bt1.backColor = colors.pink bt1.borderRadius = 2 bt1.borderPadding = 3 a(Paragraph("""text one<br/>text two<br/>""", bt1)) a(Paragraph("Border no <nr/> at the end of the paragraph!", h3)) bt1 = ParagraphStyle("bodyText1", bt) bt1.borderWidth = 0.5 bt1.borderColor = colors.toColor("red") bt1.backColor = colors.pink bt1.borderRadius = 2 bt1.borderPadding = 3 a(Paragraph("""text one<br/>text two""", bt1)) a(Paragraph("Different border style!", h3)) bt2 = ParagraphStyle("bodyText1", bt1) bt2.borderWidth = 1.5 bt2.borderColor = colors.toColor("blue") bt2.backColor = colors.gray bt2.borderRadius = 3 bt2.borderPadding = 3 a(Paragraph("""text one<br/>text two<br/>""", bt2)) doc = MyDocTemplate(outputfile("test_platypus_breaking.pdf")) doc.multiBuild(story)
def _test0(self): "This makes one long multi-page paragraph." # Build story. story = [] a = story.append styleSheet = getSampleStyleSheet() h1 = styleSheet['Heading1'] h1.pageBreakBefore = 1 h1.keepWithNext = 1 h2 = styleSheet['Heading2'] h2.frameBreakBefore = 1 h2.keepWithNext = 1 h3 = styleSheet['Heading3'] h3.backColor = colors.cyan h3.keepWithNext = 1 bt = styleSheet['BodyText'] a( Paragraph( """ Subsequent pages test pageBreakBefore, frameBreakBefore and keepTogether attributes. Generated at %s. The number in brackets at the end of each paragraph is its position in the story. (%d)""" % (time.ctime(time.time()), len(story)), bt)) for i in xrange(10): a(Paragraph('Heading 1 always starts a new page (%d)' % len(story), h1)) for j in xrange(3): a( Paragraph( 'Heading1 paragraphs should always' 'have a page break before. Heading 2 on the other hand' 'should always have a FRAME break before (%d)' % len(story), bt)) a( Paragraph( 'Heading 2 always starts a new frame (%d)' % len(story), h2)) a( Paragraph( 'Heading1 paragraphs should always' 'have a page break before. Heading 2 on the other hand' 'should always have a FRAME break before (%d)' % len(story), bt)) for j in xrange(3): a( Paragraph( randomText(theme=PYTHON, sentences=2) + ' (%d)' % len(story), bt)) a( Paragraph( 'I should never be at the bottom of a frame (%d)' % len(story), h3)) a( Paragraph( randomText(theme=PYTHON, sentences=1) + ' (%d)' % len(story), bt)) a(Paragraph('Now we do <br/> tests', h1)) a(Paragraph('First off no br tags', h3)) a(Paragraph(_text1, bt)) a(Paragraph("<br/> after 'the' in line 4", h3)) a(Paragraph(_text1.replace('forms of the', 'forms of the<br/>', 1), bt)) a(Paragraph("2*<br/> after 'the' in line 4", h3)) a( Paragraph(_text1.replace('forms of the', 'forms of the<br/><br/>', 1), bt)) a(Paragraph("<br/> after 'I suggested ' in line 5", h3)) a(Paragraph(_text1.replace('I suggested ', 'I suggested<br/>', 1), bt)) a(Paragraph("2*<br/> after 'I suggested ' in line 5", h3)) a(Paragraph(_text1.replace('I suggested ', 'I suggested<br/><br/>', 1), bt)) a(Paragraph("<br/> at the end of the paragraph!", h3)) a(Paragraph("""text one<br/>text two<br/>""", bt)) a(Paragraph("Border with <nr/> at the end of the paragraph!", h3)) bt1 = ParagraphStyle('bodyText1', bt) bt1.borderWidth = 0.5 bt1.borderColor = colors.toColor('red') bt1.backColor = colors.pink bt1.borderRadius = 2 bt1.borderPadding = 3 a(Paragraph("""text one<br/>text two<br/>""", bt1)) a(Paragraph("Border no <nr/> at the end of the paragraph!", h3)) bt1 = ParagraphStyle('bodyText1', bt) bt1.borderWidth = 0.5 bt1.borderColor = colors.toColor('red') bt1.backColor = colors.pink bt1.borderRadius = 2 bt1.borderPadding = 3 a(Paragraph("""text one<br/>text two""", bt1)) a(Paragraph("Different border style!", h3)) bt2 = ParagraphStyle('bodyText1', bt1) bt2.borderWidth = 1.5 bt2.borderColor = colors.toColor('blue') bt2.backColor = colors.gray bt2.borderRadius = 3 bt2.borderPadding = 3 a(Paragraph("""text one<br/>text two<br/>""", bt2)) doc = MyDocTemplate(outputfile('test_platypus_breaking.pdf')) doc.multiBuild(story)
def addPara(self, force=False): # Cleanup the trail for frag in reversed(self.fragList): frag.text = frag.text.rstrip() if frag.text: break if force or (self.text.strip() and self.fragList): # Strip trailing whitespaces #for f in self.fragList: # f.text = f.text.lstrip() # if f.text: # break #self.fragList[-1].lineBreak = self.fragList[-1].text.rstrip() # Update paragraph style by style of first fragment first = self.fragBlock style = ParagraphStyle('default%d' % self.UID(), keepWithNext=first.keepWithNext) style.fontName = first.fontName style.fontSize = first.fontSize style.leading = max(first.leading, first.fontSize * 1.25) style.backColor = first.backColor style.spaceBefore = first.spaceBefore style.spaceAfter = first.spaceAfter style.leftIndent = first.leftIndent style.rightIndent = first.rightIndent style.firstLineIndent = first.firstLineIndent style.alignment = first.alignment style.bulletFontName = first.fontName style.bulletFontSize = first.fontSize style.bulletIndent = first.bulletIndent style.borderWidth = max(first.borderLeftWidth, first.borderRightWidth, first.borderTopWidth, first.borderBottomWidth) style.borderPadding = first.borderPadding # + first.borderWidth style.borderColor = first.borderTopColor # borderRadius: None, # print repr(self.text.strip()), style.leading, "".join([repr(x.text) for x in self.fragList]) # print first.leftIndent, first.listStyleType,repr(self.text) # Add paragraph to story para = PmlParagraph(self.text, style, frags=self.fragAnchor + self.fragList, bulletText=copy.copy(first.bulletText)) para.outline = frag.outline para.outlineLevel = frag.outlineLevel para.outlineOpen = frag.outlineOpen self.addStory(para) self.fragAnchor = [] first.bulletText = None self.clearFrag()
def _test0(self): "This makes one long multi-page paragraph." # Build story. story = [] a = story.append styleSheet = getSampleStyleSheet() h1 = styleSheet['Heading1'] h1.pageBreakBefore = 1 h1.keepWithNext = 1 h2 = styleSheet['Heading2'] h2.frameBreakBefore = 1 h2.keepWithNext = 1 h3 = styleSheet['Heading3'] h3.backColor = colors.cyan h3.keepWithNext = 1 bt = styleSheet['BodyText'] btj = ParagraphStyle('bodyText1j',parent=bt,alignment=TA_JUSTIFY) btr = ParagraphStyle('bodyText1r',parent=bt,alignment=TA_RIGHT) btc = ParagraphStyle('bodyText1c',parent=bt,alignment=TA_CENTER) a(Paragraph(""" <a name='top'/>Subsequent pages test pageBreakBefore, frameBreakBefore and keepTogether attributes. Generated at %s. The number in brackets at the end of each paragraph is its position in the story. (%d)""" % ( time.ctime(time.time()), len(story)), bt)) for i in range(10): a(Paragraph('Heading 1 always starts a new page (%d)' % len(story), h1)) for j in range(3): a(Paragraph('Heading1 paragraphs should always' 'have a page break before. Heading 2 on the other hand' 'should always have a FRAME break before (%d)' % len(story), bt)) a(Paragraph('Heading 2 always starts a new frame (%d)' % len(story), h2)) a(Paragraph('Heading1 paragraphs should always' 'have a page break before. Heading 2 on the other hand' 'should always have a FRAME break before (%d)' % len(story), bt)) for j in range(3): a(Paragraph(randomText(theme=PYTHON, sentences=2)+' (%d)' % len(story), bt)) a(Paragraph('I should never be at the bottom of a frame (%d)' % len(story), h3)) a(Paragraph(randomText(theme=PYTHON, sentences=1)+' (%d)' % len(story), bt)) for align,bts in [('left',bt),('JUSTIFIED',btj),('RIGHT',btr),('CENTER',btc)]: a(Paragraph('Now we do <br/> tests(align=%s)' % align, h1)) a(Paragraph('First off no br tags',h3)) a(Paragraph(_text1,bts)) a(Paragraph("<br/> after 'the' in line 4",h3)) a(Paragraph(_text1.replace('forms of the','forms of the<br/>',1),bts)) a(Paragraph("2*<br/> after 'the' in line 4",h3)) a(Paragraph(_text1.replace('forms of the','forms of the<br/><br/>',1),bts)) a(Paragraph("<br/> after 'I suggested ' in line 5",h3)) a(Paragraph(_text1.replace('I suggested ','I suggested<br/>',1),bts)) a(Paragraph("2*<br/> after 'I suggested ' in line 5",h3)) a(Paragraph(_text1.replace('I suggested ','I suggested<br/><br/>',1),bts)) a(Paragraph("<br/> at the end of the paragraph!",h3)) a(Paragraph("""text one<br/>text two<br/>""",bts)) a(Paragraph("Border with <br/> at the end of the paragraph!",h3)) bt1 = ParagraphStyle('bodyText1',bts) bt1.borderWidth = 0.5 bt1.borderColor = colors.toColor('red') bt1.backColor = colors.pink bt1.borderRadius = 2 bt1.borderPadding = 3 a(Paragraph("""text one<br/>text two<br/>""",bt1)) a(Paragraph("Border no <br/> at the end of the paragraph!",h3)) bt1 = ParagraphStyle('bodyText1',bts) bt1.borderWidth = 0.5 bt1.borderColor = colors.toColor('red') bt1.backColor = colors.pink bt1.borderRadius = 2 bt1.borderPadding = 3 a(Paragraph("""text one<br/>text two""",bt1)) a(Paragraph("Different border style!",h3)) bt2 = ParagraphStyle('bodyText1',bt1) bt2.borderWidth = 1.5 bt2.borderColor = colors.toColor('blue') bt2.backColor = colors.gray bt2.borderRadius = 3 bt2.borderPadding = 3 a(Paragraph("""text one<br/>text two<br/>""",bt2)) for i in 0, 1, 2: P = Paragraph("""This is a paragraph with <font color='blue'><a href='#top'>with an incredibly long and boring link in side of it that contains lots and lots of stupidly boring and worthless information. So that we can split the link and see if we get problems like Dinu's. I hope we don't, but you never do Know.</a></font>""",bt) a(P) doc = MyDocTemplate(outputfile('test_platypus_breaking.pdf')) doc.multiBuild(story)
Image of Cambridge Map. ''' def __init__(self, xoffset=0): self.xoffset = xoffset def wrap(self, *args): return (self.xoffset, 0) def draw(self): canvas = self.canv canvas.drawImage("centre2_8000_rotated.jpg", -10,-260, width=400,height=280) # Create the styles for the document logoStyle = ParagraphStyle('normal') logoStyle.fontSize=16 logoStyle.leading=15 logoStyle.rightindent=5 logoStyle.backColor='grey' #logoStyle.textColor='white' logoStyle.borderWidth=5 logoStyle.borderColor='grey' rightStyle = ParagraphStyle('normal') rightStyle.alignment = TA_RIGHT rightStyle.spaceBefore = 10 paraStyle = ParagraphStyle('normal') paraStyle.spaceAfter = 10 paraStyle.alignment = TA_JUSTIFY medStyle = ParagraphStyle('normal') medStyle.fontSize = 8 medStyle.leading = 8
def __make_quiz(self, words, start_date, page_max = 10, filter = True): conn = sqlite3.connect('dict.db') cursor = conn.cursor() words_list = set() words_meaning = {} dictcn = dict_cn() for word in words: dict_word, meaning = dictcn.search(word) words_meaning[dict_word] = meaning words_list.add(dict_word) if filter : words_variant = self.words_with_tag('复数') words_variant = words_variant|self.words_with_tag('第三人称单数') words_variant = words_variant|self.words_with_tag('过去式') words_variant = words_variant|self.words_with_tag('过去分词') words_variant = words_variant|self.words_with_tag('现在分词') words_variant = words_variant|self.words_with_tag('比较级') words_variant = words_variant|self.words_with_tag('最高级') words_proper = self.words_with_tag('姓氏') words_proper = words_proper|self.words_with_tag('人名') words_proper = words_proper|self.words_with_tag('国名') words_proper = words_proper|self.words_with_tag('美国州名') words_proper = words_proper|self.words_with_tag('城市') words_proper = words_proper|self.words_with_tag('缩写') words_first_letter_capital = self.words_with_tag('首字母大写') word_count = len(words_list) self.__print_word_list(words_list & words_variant) words_list = words_list - words_variant #去除变体的单词 print('剔除 {} 个变体单词,剩余 {} 个单词'.format(word_count - len(words_list), len(words_list))) word_count = len(words_list) self.__print_word_list(words_list & words_proper) words_list = words_list - words_proper #去除专用单词,如:国名、地名、人名等 print('剔除 {} 个国名、地名等专有单词,剩余 {} 个单词'.format(word_count - len(words_list), len(words_list))) word_count = len(words_list) self.__print_word_list(words_list & words_first_letter_capital) words_list = words_list - words_first_letter_capital #去除首字母大写单词 print('剔除 {} 个首字母大写单词,剩余 {} 个单词'.format(word_count - len(words_list), len(words_list))) self.__print_word_list(words_list) print('最终输出 {} 个单词'.format(len(words_list))) words_dict = {} for word in words_list: words_dict[word] = words_meaning[word] chinese_number = ['0', '①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩'] roman_number = ['0', 'Ⅰ.', 'Ⅱ.', 'Ⅲ.', 'Ⅳ.', 'Ⅴ.', 'Ⅵ.', 'Ⅶ.', 'Ⅷ.', 'Ⅸ.', 'Ⅹ.'] pdfmetrics.registerFont(TTFont("SimSun", "SimSun.ttf")) words_per_page = 6 quiz_words = {} quiz_meanings = {} quiz_meanings_disorder = {} inside_page_index = 0 page_no = 0 pdf_filename = "" txt_filename = "" canv = None for word in words_dict.keys(): if page_no % page_max == 0: if round(page_no / page_max) > 0: canv.save() #获取quiz的日期字符串,此处借用sqlite来进行计算 sql = "select strftime('%Y%m%d', date(?, ?)) " #print(sql, start_date, '+{} day'.format(round(page_no / page_max)) ) cursor.execute(sql, (start_date, '+{} day'.format(round(page_no / page_max)), )) row = cursor.fetchone() cmp_date_str = row[0] #YYYYMMDD格式的日期字符串 pdf_filename = "words/plan/quiz-{}.pdf".format(cmp_date_str) txt_filename = "words/plan/quiz-{}.txt".format(cmp_date_str) canv = canvas.Canvas(pdf_filename) if inside_page_index == words_per_page: inside_page_index = 0 page_no += 1 style = ParagraphStyle(name='normal') style.fontSize = 20 style.fontName = "SimSun" style.alignment = 1 display_page_no = page_no % page_max if display_page_no == 0: display_page_no = page_max p = Paragraph("单词练习-{}".format(display_page_no), style) p.wrap(210 * mm, 35 * mm) p.drawOn(canv, 0, 292 * mm) with open(txt_filename, 'a') as f: f.write('##Page-{}'.format(display_page_no) + '\n') canv.setFont("SimSun", 18) quiz_mapping, reversed_quiz_mapping = self.__create_random_mapping_for_quiz(words_per_page) for i in range(0, words_per_page): quiz_meanings_disorder[i] = quiz_meanings[quiz_mapping[i]] for i in range(0, words_per_page): style = ParagraphStyle(name='normal') style.backColor = HexColor(0xEEEEEE) style.fontSize = 18 style.fontName = "SimSun" style.leading = 18 p = Paragraph('{}{}'.format(roman_number[i + 1], quiz_words[i]), style) word_width, word_height = p.wrap(75 * mm, 40 * mm) p.drawOn(canv, 0.5 * mm, (270 - i * 45) * mm - word_height) style = ParagraphStyle(name='normal') style.backColor = HexColor(0xEEEEEE) style.fontSize = 10 style.fontName = "SimSun" style.leading = 18 p = Paragraph('Answer:<br/><br/><br/>_________________________________________', style) answer_width, answer_height = p.wrap(75 * mm, 40 * mm) p.drawOn(canv, 0.5 * mm, (270 - i * 45) * mm - word_height - answer_height - 10) with open(txt_filename, 'a') as f: f.write('{}|word={}|meaning={}|result(P/F)=\n'.format(roman_number[i + 1], quiz_words[i], chinese_number[reversed_quiz_mapping[i] + 1])) #print('{}word={}|meaning={}'.format(roman_number[i + 1], quiz_words_disorder[i], chinese_number[reversed_quiz_mapping[i] + 1])) with open(txt_filename, 'a') as f: f.write('\n') for i in range(0, words_per_page): style = ParagraphStyle(name='normal') style.backColor = HexColor(0xEEEEEE) style.fontSize = 18 style.fontName = "SimSun" style.leading = 18 p = Paragraph('{}{}'.format(chinese_number[i + 1], quiz_meanings_disorder[i]), style) meaning_width, meaning_height = p.wrap(110 * mm, 40 * mm) p.drawOn(canv, 100 * mm, (270 - i * 45) * mm - meaning_height) #print('{}meaning={}'.format(chinese_number[i+1], quiz_meanings_disorder[i])) canv.showPage() canv.setFont("SimSun", 18) quiz_words[inside_page_index] = word quiz_meanings[inside_page_index] = words_dict[word] inside_page_index += 1 canv.save()
def createPDF(self): # ------------------------------------------------------------------------- # Define functions used internally # ------------------------------------------------------------------------- # Returns the plain (non-HTML) text for an item. Used at the lowest level # of the DOM tree because it doesn't preserve any HTML formatting def getItemText(item): if isinstance(item, Tag): return portal_transforms.convert('html_to_text', repr(item)).getData() elif isinstance(item, NavigableString): return str(item).strip() else: return str(item).strip() # Provides the limited subset of HTML content used by the PDF generator space_before_punctuation_re = re.compile(u"\s+([.;:,!?])", re.I|re.M) def getInlineContents(item): p_contents = [] for i in item.contents: if isinstance(i, Tag): item_type = i.name if item_type in ['b', 'strong', 'i', 'em', 'super', 'sub', 'a']: for a in ['class', 'title', 'rel']: if i.get(a): del i[a] if item_type == 'strong': i.name = 'b' elif item_type == 'em': i.name = 'i' elif item_type == 'a': i.name = 'link' if not (i['href'].startswith('http') or i['href'].startswith('mailto')): i['href'] = urljoin(self.context.absolute_url(), i['href']) # Wouldn't it be nice to underline the links? i['color'] = 'blue' if i.string: p_contents.append(repr(i)) else: p_contents.append(getInlineContents(i)) else: p_contents.append(getItemText(i)) elif isinstance(i, NavigableString): p_contents.append(str(i).strip()) contents = " ".join(p_contents) return space_before_punctuation_re.sub(r"\1", contents) # Returns structure containing table data when passed a BeautifulSoup # <table> element. def getTableData(item): def getCellSpan(cell): colspan = int(cell.get('colspan', 1)) rowspan = int(cell.get('rowspan', 1)) return (colspan, rowspan) th_bg = HexColor('#CCCCCC') th_text = HexColor('#000000') grid = HexColor('#999999') table_data = [] table_style = [] r_index = 0 for tr in item.findAll('tr'): c_index = 0 table_row = [] for i in tr.findAll('th'): table_row.append(Paragraph(getInlineContents(i), th_cell)) (colspan, rowspan) = getCellSpan(i) c_max = c_index + colspan - 1 r_max = r_index + rowspan - 1 table_style.extend([ ('FONTNAME', (c_index,r_index), (c_index,r_index), 'Times-Bold'), ('FONTSIZE', (c_index,r_index), (c_index,r_index), 9), ('BACKGROUND', (c_index,r_index), (c_index,r_index), th_bg), ('GRID', (c_index,r_index), (c_max,r_max), 0.5, grid), ('TEXTCOLOR', (c_index,r_index), (c_index,r_index), th_text), ('LEFTPADDING', (c_index,r_index), (c_index,r_index), 3), ('RIGHTPADDING', (c_index,r_index), (c_index,r_index), 3), ('SPAN', (c_index,r_index), (c_max,r_max)), ] ) c_index = c_index + 1 for i in tr.findAll('td'): td_align = i.get('align', 'LEFT').upper() if td_align == 'RIGHT': p = Paragraph(getInlineContents(i), td_cell_right) else: p = Paragraph(getInlineContents(i), td_cell) p.hAlign = td_align table_row.append(p) (colspan, rowspan) = getCellSpan(i) c_max = c_index + colspan - 1 r_max = r_index + rowspan - 1 table_style.extend([ ('GRID', (c_index,r_index), (c_max,r_max), 0.5, grid), ('FONTNAME', (c_index,r_index), (c_index,r_index), 'Times-Roman'), ('FONTSIZE', (c_index,r_index), (c_index,r_index), 9), ('LEFTPADDING', (c_index,r_index), (c_index,r_index), 3), ('RIGHTPADDING', (c_index,r_index), (c_index,r_index), 3), ('SPAN', (c_index,r_index), (c_max,r_max)), ('ALIGN', (c_index,r_index), (c_index,r_index), td_align), ] ) c_index = c_index + 1 table_data.append(table_row) r_index = r_index + 1 caption = item.find('caption') return (table_data, TableStyle(table_style), caption) # Provides the PDF entities for the corresponding HTML tags. def getContent(item, bump_headings=False): pdf = [] if isinstance(item, Tag): className=item.get('class', '').split() item_type = item.name if item_type in ['h2', 'h3', 'h4', 'h5', 'h6']: item_style = tag_to_style.get(item_type) h = Paragraph(getItemText(item), styles[item_style]) h.keepWithNext = True pdf.append(h) if item_type == 'h2' and not bump_headings: hr = HRFlowable(width='100%', thickness=0.25, spaceBefore=2, spaceAfter=4, color=styles[item_style].textColor) hr.keepWithNext = True pdf.append(hr) elif item_type in ['table']: (table_data, table_style, caption) = getTableData(item) table = Table(table_data) table.setStyle(table_style) table.hAlign = 'LEFT' table.spaceBefore = 10 table.spaceAfter = 10 if caption: caption_el = Paragraph(getInlineContents(caption), discreet) pdf.append(KeepTogether([table, caption_el])) else: pdf.append(table) elif item_type in ['ul']: for i in item.findAll('li'): pdf.append(Paragraph('<bullet>•</bullet>%s' % getInlineContents(i), bullet_list)) elif item_type in ['ol']: # Sequences were incrementing based on previous PDF generations. # Including explicit ID and reset li_uuid = uuid1().hex for i in item.findAll('li'): pdf.append(Paragraph('<seq id="%s" />. %s' % (li_uuid, getInlineContents(i)), bullet_list)) pdf.append(Paragraph('<seqReset id="%s" />' % li_uuid, styles['Normal'])) elif item_type in ['p'] or (item_type in ['div'] and 'captionedImage' in className or 'callout' in className or 'pullquote' in className): has_image = False # Pull images out of items and add before for img in item.findAll('img'): img.extract() src = img['src'].replace(self.site.absolute_url(), '') if src.startswith('/'): src = src.replace('/', '', 1) try: img_obj = self.site.restrictedTraverse(str(src)) except KeyError: continue has_image = True pdf_image = getImage(img_obj) pdf.append(pdf_image) # If we had an image, and the next paragraph has the # 'discreet' class (is a caption) then keep them together if has_image: s = item.findNextSiblings() if s and 'discreet' in s[0].get('class', ''): pdf[-1].keepWithNext = True # Get paragraph contents p_contents = getInlineContents(item) # Don't add anything if no contents. if not p_contents: pass elif 'callout' in className or 'pullquote' in className: pdf.append(Paragraph(p_contents, callout)) elif 'discreet' in className or 'captionedImage' in className: if len(pdf) and isinstance(pdf[-1], Image): pdf[-1].keepWithNext = True pdf.append(Paragraph(p_contents, discreet)) else: pdf.append(Paragraph(p_contents, styles["Normal"])) elif item_type in ['div']: for i in item.contents: pdf.extend(getContent(i)) elif item_type == 'blockquote': pdf.append(Paragraph(getItemText(item), blockquote)) else: pdf.append(Paragraph(getItemText(item), styles["Normal"])) elif isinstance(item, NavigableString): if item.strip(): pdf.append(Paragraph(item, styles["Normal"])) return pdf # ------------------------------------------------------------------------- # Main body of create PDF # ------------------------------------------------------------------------- # Get document attributes title = self.context.Title() desc = self.context.Description() text = self.context.getText() if isinstance(text, BaseUnit): if hasattr(text, 'raw'): text = text.raw else: text = '' # Number of columns column_count = 2 if hasattr(self.context, 'extension_publication_column_count'): column_count = getattr(self.context, 'extension_publication_column_count', '2') try: column_count = int(column_count) except: column_count = 2 # Grab the publication code publication_code = self.getPublicationCode() # Grab the publication series publication_series = self.getPublicationSeries() # Clean up text text = text.replace(' ', ' ') # Colors - Maybe have presets? #header_rgb = (0.42,0.56,0.07) #header_rgb = (0.12,0.18,0.30) # Blue #header_rgb = (0.33,0.57,0.31) # Green (too light) header_rgb = HexColor('#4B7D45') # Green (dark enough) # Callout Colors callout_background_rgb = HexColor('#F6F6F6') # Styles styles=getSampleStyleSheet() styles['Normal'].spaceBefore = 3 styles['Normal'].spaceAfter = 6 styles['Normal'].fontName = 'Times-Roman' # Series Heading styles.add(ParagraphStyle('SeriesHeading')) styles['SeriesHeading'].spaceBefore = 0 styles['SeriesHeading'].spaceAfter = 2 styles['SeriesHeading'].fontSize = 10 styles['SeriesHeading'].textColor = (0,0,0) styles['SeriesHeading'].leading = 13 styles['SeriesHeading'].fontName = 'Helvetica-Bold' styles['SeriesHeading'].textTransform = 'uppercase' styles['Heading1'].fontSize = 25 styles['Heading1'].fontName = 'Helvetica-Bold' styles['Heading1'].leading = 29 styles['Heading1'].spaceBefore = 2 styles['Heading1'].spaceAfter = 12 styles['Heading1'].textColor = header_rgb styles['Heading2'].allowWidows = 0 styles['Heading2'].fontName = 'Helvetica-Bold' styles['Heading2'].fontSize = 15 styles['Heading2'].leading = 18 styles['Heading2'].spaceAfter = 8 styles['Heading2'].spaceAfter = 2 styles['Heading2'].textColor = header_rgb styles['Heading3'].allowWidows = 0 styles['Heading3'].fontName = 'Helvetica-Bold' styles['Heading3'].fontSize = 12 styles['Heading3'].leading = 14 styles['Heading3'].spaceAfter = 4 styles['Heading3'].textColor = header_rgb styles['Heading4'].allowWidows = 0 styles['Heading4'].fontName = 'Helvetica-Bold' styles['Heading4'].fontSize = 10 styles['Heading4'].leading = 12 styles['Heading4'].spaceAfter = 6 styles['Heading4'].textColor = header_rgb th_cell = ParagraphStyle('TableHeading') th_cell.spaceBefore = 3 th_cell.spaceAfter = 6 th_cell.fontSize = 10 th_cell.fontName = 'Times-Bold' td_cell = ParagraphStyle('TableData') td_cell.spaceBefore = 3 td_cell.spaceAfter = 6 td_cell.fontSize = 10 td_cell.fontName = 'Times-Roman' td_cell_right = ParagraphStyle('TableDataRight') td_cell_right.spaceBefore = 3 td_cell_right.spaceAfter = 6 td_cell_right.fontSize = 10 td_cell_right.fontName = 'Times-Roman' td_cell_right.alignment = TA_RIGHT bullet_list = ParagraphStyle('BulletList') bullet_list.spaceBefore = 4 bullet_list.spaceAfter = 4 bullet_list.fontName = 'Times-Roman' bullet_list.bulletIndent = 5 bullet_list.leftIndent = 17 bullet_list.bulletFontSize = 12 blockquote = ParagraphStyle('Blockquote') blockquote.leftIndent = 12 blockquote.rightIndent = 8 blockquote.spaceAfter = 6 blockquote.fontName = 'Times-Roman' discreet = ParagraphStyle('Discreet') discreet.fontSize = 9 discreet.textColor = HexColor('#717171') discreet.spaceAfter = 12 discreet.spaceBefore = 1 callout = ParagraphStyle('Callout') callout.fontSize = 10 callout.textColor = header_rgb callout.spaceAfter = 20 callout.spaceBefore = 22 callout.backColor = callout_background_rgb callout.borderColor = header_rgb callout.borderWidth = 1 callout.borderPadding = (8, 12, 10, 12) callout.rightIndent = 15 callout.leftIndent = 15 statement = ParagraphStyle('Statement') statement.fontSize = 8 statement.fontName = 'Times-Roman' statement.spaceAfter = 5 statement.leading = 10 description = ParagraphStyle('Description') description.spaceBefore = 6 description.spaceAfter = 8 description.fontSize = 11 description.fontName = 'Helvetica-Bold' description.leading = 13 padded_image = ParagraphStyle('PaddedImage') padded_image.spaceBefore = 12 padded_image.spaceAfter = 12 single_line = ParagraphStyle('SingleLine') single_line.fontSize = 9 single_line.fontName = 'Times-Roman' single_line.spaceBefore = 0 single_line.spaceAfter = 0 single_line_cr = ParagraphStyle('SingleLineCR') single_line_cr.fontSize = 9 single_line_cr.fontName = 'Times-Roman' single_line_cr.spaceBefore = 0 single_line_cr.spaceAfter = 10 # Create document pdf_file = BytesIO() margin = 36 # Debug for formatting boundary showBoundary=0 doc = FactsheetDocTemplate(pdf_file,pagesize=letter, title=title, rightMargin=margin,leftMargin=margin, showBoundary=showBoundary, topMargin=margin,bottomMargin=margin) # Standard padding for document elements element_padding = 6 # Document image setttings max_image_width = doc.width/column_count-(3*element_padding) if column_count <= 1: max_image_width = doc.width/2-(3*element_padding) # Returns a reportlab image object based on a Plone image object def getImage(img_obj, scale=True, reader=False, width=max_image_width, style="", column_count=column_count, caption="", leadImage=False, hAlign=None, body_image=True): if not leadImage and body_image and column_count == 1: # Special case to make one column body images 66% of the page width = 1.33*width img_width = img_obj.width img_height = img_obj.height if scale and (img_width > width): img_height = (width/img_width)*img_height img_width = width if hasattr(img_obj, 'data'): if hasattr(img_obj.data, 'data'): img_data = BytesIO(img_obj.data.data) else: img_data = BytesIO(img_obj.data) elif hasattr(img_obj, '_data'): img_data = BytesIO(img_obj._data) else: img_data = BytesIO('') if reader: img = ImageReader(img_data) else: if caption or leadImage: img = ImageFigure(img_data, caption=caption, width=img_width, height=img_height, align="right", max_image_width=width, column_count=column_count) else: img = Image(img_data, width=img_width, height=img_height) if style: img.style = style if hAlign: img.hAlign = hAlign elif column_count == 1: img.hAlign = TA_LEFT else: img.hAlign = TA_CENTER return img #-------------- calculated coordinates/w/h extension_url_image = self.site.portal_skins.agcommon_images['extension-url.png'] extension_url_image_width = 0.5*max_image_width # Factsheet title title_lines = 3 publication_series_height = 0 if publication_series: # If series heading, only 2 title lines title_lines = 2 # One line for the series heading publication_series_height = styles['SeriesHeading'].spaceBefore + \ styles['SeriesHeading'].spaceAfter + \ styles['SeriesHeading'].leading title_height = styles['Heading1'].spaceBefore + \ styles['Heading1'].spaceAfter + \ (title_lines * styles['Heading1'].leading) + \ publication_series_height + element_padding # Penn State/Extension Footer Image footer_image_width = 222.0 # 72 points/inch * 3.125" footer_image = self.site.portal_skins.agcommon_images['extension-factsheet-footer.png'] footer_image_height = footer_image_width*(1.0*footer_image.height/footer_image.width) # Header and footer on first page def header_footer(canvas,doc): canvas.saveState() # Line under Title canvas.setStrokeColorRGB(0,0,0) line_y=doc.bottomMargin+doc.height-title_height canvas.line(doc.leftMargin+element_padding, line_y, doc.width+doc.leftMargin-element_padding, line_y) # Footer canvas.drawImage(getImage(footer_image, scale=False, reader=True), doc.leftMargin+element_padding, 72.0/2, width=footer_image_width, height=footer_image_height, preserveAspectRatio=True, mask='auto') canvas.restoreState() # Footer for pages 2 and after def footer(canvas,doc): canvas.saveState() canvas.setFont('Times-Roman',9) canvas.drawString(margin, 24, "Page %d" % doc.page) canvas.setFont('Times-Roman',9) canvas.drawRightString(doc.width+margin+element_padding, 24, title) canvas.restoreState() #Two Columns For First (title) page title_y = doc.bottomMargin + doc.height - title_height title_column_y = doc.bottomMargin+footer_image_height+element_padding title_column_height = title_y - title_column_y title_frame_title = Frame(doc.leftMargin, title_y, doc.width, title_height, id='title_title', showBoundary=showBoundary) title_frames = [title_frame_title] for i in range(0,column_count): lm = doc.leftMargin + i * (doc.width/column_count+element_padding) w = doc.width/column_count-element_padding title_frame = Frame(lm, title_column_y, w, title_column_height, id='title_col%d' % i, showBoundary=showBoundary) title_frames.append(title_frame) #Two Columns For remaining page other_frames = [] for i in range(0,column_count): lm = doc.leftMargin + i * (doc.width/column_count+element_padding) w = doc.width/column_count-element_padding other_frame = Frame(lm, doc.bottomMargin, w, doc.height, id='other_col%d' % i, showBoundary=showBoundary) other_frames.append(other_frame) title_template = PageTemplate(id="title_template", frames=title_frames,onPage=header_footer) other_template = PageTemplate(id="other_template", frames=other_frames,onPage=footer) doc.addPageTemplates([title_template,other_template]) doc.handle_nextPageTemplate("other_template") # --------------------------------------------------------------------- # Convert HTML to PDF (Magic goes here) # --------------------------------------------------------------------- # Soupify soup = BeautifulSoup(text) # This list holds the PDF elements pdf = [] # Series, page heading and description in top frame, then framebreak # into two columns. Optionally add the description to the body if the # flag is set. if publication_series: pdf.append(Paragraph(publication_series, styles['SeriesHeading'])) pdf.append(Paragraph(title, styles["Heading1"])) # Move to next frame pdf.append(FrameBreak()) if description: pdf.append(Paragraph(desc, description)) # If we're a news item, append the date if self.context.portal_type in ['News Item']: pdf.append(Paragraph('Posted: %s' % self.context.getEffectiveDate().strftime('%B %d, %Y'), discreet)) # Lead Image and caption as first elements. Not doing News Item image. (IMAGE_FIELD_NAME, IMAGE_CAPTION_FIELD_NAME) = getImageAndCaptionFieldNames(self.context) leadImage_field = self.context.getField(IMAGE_FIELD_NAME) leadImage_caption_field = self.context.getField(IMAGE_CAPTION_FIELD_NAME) show_leadimage = getattr(self.context, 'show_leadimage_context', True) if show_leadimage and leadImage_field and leadImage_caption_field: leadImage = leadImage_field.get(self.context) leadImage_caption = leadImage_caption_field.get(self.context) if leadImage and leadImage.get_size(): if column_count == 1: pdf.append(getImage(leadImage, caption=leadImage_caption, leadImage=True)) else: pdf.append(getImage(leadImage)) if leadImage_caption: pdf.append(Paragraph(leadImage_caption, discreet)) # portal_transforms will let us convert HTML into plain text portal_transforms = getToolByName(self.context, 'portal_transforms') # Equivalent PDF paragraph styles for HTML tag_to_style = { 'h2' : 'Heading2', 'h3' : 'Heading3', 'h4' : 'Heading4', 'h5' : 'Heading5', 'h6' : 'Heading6', 'p' : 'Normal' } # Push headings to the smallest level # If we have an h2, but not an h3 or h4, bump the heading styles down. attrs = ['allowWidows', 'fontName', 'fontSize', 'leading', 'spaceAfter', 'textColor', ] bump_headings = False if '<h2' in text and not '<h3' in text and not '<h4' in text: bump_headings = True heading_tags = sorted([x for x in tag_to_style.keys() if x.startswith('h')]) for i in range(0, len(heading_tags) - 1): from_style = tag_to_style[heading_tags[i]] to_style = tag_to_style[heading_tags[i+1]] for a in attrs: styles[from_style].__dict__[a] = styles[to_style].__dict__[a] # Loop through Soup contents for item in soup.contents: pdf.extend(getContent(item, bump_headings=bump_headings)) # Embed lead images in paragraphs if we're a single column if column_count == 1: for i in range(1,len(pdf)-1): if isinstance(pdf[i], ImageFigureBase): paragraphs = [] for j in range(i+1, len(pdf)-1): if isinstance(pdf[j], Paragraph) or isinstance(pdf[j], HRFlowable): paragraphs.append(pdf[j]) pdf[j] = None else: break if paragraphs: pdf[i].hAlign="RIGHT" img_paragraph = ImageAndFlowables(pdf[i], paragraphs,imageLeftPadding=element_padding) pdf[i] = img_paragraph while None in pdf: pdf.remove(None) # Contributors (as Contact Information) %%% contributors_viewlet = getMultiAdapter((self.context, self.request, self), name='agcommon.contributors') contributors_people = contributors_viewlet.people if contributors_people: # Adding h2 this way so as to take advantage of the underline and the # bump_headings parameter heading = Tag(BeautifulSoup(), 'h2') heading.insert(0, 'Contact Information') pdf.extend(getContent(heading, bump_headings=bump_headings)) for person in contributors_viewlet.people: if person.get('url'): person_name = Paragraph("""<b><a color="blue" href="%(url)s">%(name)s</a></b>""" % person, single_line) else: person_name = Paragraph("""<b>%(name)s</b>""" % person, single_line) person_name.keepWithNext = True person_title = Paragraph("""%(title)s""" % person, single_line) person_title.keepWithNext = True person_email = Paragraph("""<a color="blue" href="mailto:%(email)s">%(email)s</a>""" % person, single_line) person_email.keepWithNext = True person_phone = Paragraph("""%(phone)s""" % person, single_line_cr) pdf.append(person_name) pdf.append(person_title) pdf.append(person_email) pdf.append(person_phone) # All done with contents, appending line and statement pdf.append(HRFlowable(width='100%', spaceBefore=4, spaceAfter=4)) # Extension logo pdf.append(getImage(extension_url_image, scale=True, width=extension_url_image_width, style=padded_image, hAlign='LEFT', body_image=False)) # Choose which statement aa_statement = """Penn State is an equal opportunity, affirmative action employer, and is committed to providing employment opportunities to all qualified applicants without regard to race, color, religion, age, sex, sexual orientation, gender identity, national origin, disability or protected veteran status.""" statement_text = ("""Penn State College of Agricultural Sciences research and extension programs are funded in part by Pennsylvania counties, the Commonwealth of Pennsylvania, and the U.S. Department of Agriculture. Where trade names appear, no discrimination is intended, and no endorsement by Penn State Extension is implied. <b>This publication is available in alternative media on request.</b> %s © The Pennsylvania State University %d """ % (aa_statement, DateTime().year())).split("\n") # Append the publication code, if it exists if publication_code: statement_text.append("Code: %s" % publication_code) # Create paragraphs from the statement text for s in statement_text: if s.strip(): pdf.append(Paragraph(s, statement)) # Create PDF - multibuild instead of build for table of contents # functionality doc.multiBuild(pdf) #doc.build(pdf) # Pull PDF binary bits into variable, close file handle and return pdf_value = pdf_file.getvalue() pdf_file.close() return pdf_value
def __init__(self, data, colWidths=None, rowHeights=None, style=None, repeatRows=0, repeatCols=0, splitByRow=1, emptyTableAction=None): self.hAlign = 'CENTER' self.vAlign = 'MIDDLE' if type(data) not in _SeqTypes: raise ValueError, "%s invalid data type" % self.identity() self._nrows = nrows = len(data) self._cellvalues = [] _seqCW = type(colWidths) in _SeqTypes _seqRH = type(rowHeights) in _SeqTypes if nrows: self._ncols = ncols = max(map(_rowLen,data)) elif colWidths and _seqCW: ncols = len(colWidths) else: ncols = 0 if not emptyTableAction: emptyTableAction = rl_config.emptyTableAction if not (nrows and ncols): if emptyTableAction=='error': raise ValueError, "%s must have at least a row and column" % self.identity() elif emptyTableAction=='indicate': self.__class__ = Preformatted global _emptyTableStyle if '_emptyTableStyle' not in globals().keys(): _emptyTableStyle = ParagraphStyle('_emptyTableStyle') _emptyTableStyle.textColor = colors.red _emptyTableStyle.backColor = colors.yellow Preformatted.__init__(self,'%s(%d,%d)' % (self.__class__.__name__,nrows,ncols), _emptyTableStyle) elif emptyTableAction=='ignore': self.__class__ = Spacer Spacer.__init__(self,0,0) else: raise ValueError, '%s bad emptyTableAction: "%s"' % (self.identity(),emptyTableAction) return self._cellvalues = data if not _seqCW: colWidths = ncols*[colWidths] elif len(colWidths) != ncols: raise ValueError, "%s data error - %d columns in data but %d in grid" % (self.identity(),ncols, len(colWidths)) if not _seqRH: rowHeights = nrows*[rowHeights] elif len(rowHeights) != nrows: raise ValueError, "%s data error - %d rows in data but %d in grid" % (self.identity(),nrows, len(rowHeights)) for i in range(nrows): if len(data[i]) != ncols: raise ValueError, "%s not enough data points in row %d!" % (self.identity(),i) self._rowHeights = self._argH = rowHeights self._colWidths = self._argW = colWidths cellrows = [] for i in range(nrows): cellcols = [] for j in range(ncols): cellcols.append(CellStyle(`(i,j)`)) cellrows.append(cellcols) self._cellStyles = cellrows self._bkgrndcmds = [] self._linecmds = [] self._spanCmds = [] self.repeatRows = repeatRows self.repeatCols = repeatCols self.splitByRow = splitByRow if style: self.setStyle(style)
# Paragraph styles ss = getSampleStyleSheet() style_normal = ParagraphStyle('normal', fontName='Helvetica') style_serial = ParagraphStyle('serial', parent=style_normal) style_serial.alignment = 2 #style_normal = styles['Normal'] #style_normal.fontName = 'Helvetica' style_title = ParagraphStyle('title') style_title.fontName = 'Helvetica-Bold' style_title.alignment = styles.TA_CENTER style_labsur = ParagraphStyle('logo', parent=ss['h1']) style_labsur.backColor = colors.silver style_labsur.alignment = styles.TA_CENTER style_address = ParagraphStyle('address', parent=style_normal) # Table Styles base_form_style = TableStyle([ ('FACE', (0, 0), (0, -1), 'Helvetica-Bold'), ('FACE', (1, 0), (1, -1), 'Helvetica'), ('SIZE', (0, 0), (-1, -1), 10), #('LEFTPADDING', (0, 0), (0, -1), 0), #('LEFTPADDING', (1, 0), (1, -1), cm/3), ('RIGHTPADDING', (0, 0), (-1, -1), 0), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), ])