def makeDocument(): u"""Demo Bitcount Reference composer.""" # Set some values of the default template (as already generated by the document). # Make squential unique names for the flow boxes inside the templates coverTitleId = 'coverTitleId' # To find the placement of the cover title. coverAuthorId = 'coverAuthorId' # Find the placement for the author name. tocId = 'toc' # Id of target textBox, containing the table of content. flowId1 = MAIN_FLOW + '1' flowIds = [flowId1] # Names of boxes that contain footnote text in flow. footnotesId = 'footnotes' # Id of target textBox containing footnotes per page. literatureIndexId = 'literatureIndex' imageIndexId = 'imageIndex' pageNumberId = 'pageNumberId' # Template for Cover page templateCover = Template() # Create new template newColTextBox(0, 0, w=W, h=H, fill=(1, 0, 0), parent=templateCover) # Placement of first <h1> in the Galley, holding the Thesis title. newColTextBox('Title of the page', 1, 1, 6, 5, eId=coverTitleId, fill=BOX_COLOR, parent=templateCover) # Placement of first <h4> in the Galley, holding the author name(s) newColTextBox('Subhead of the page', 1, 8, 6, 5, eId=coverAuthorId, fill=BOX_COLOR, parent=templateCover) # Template for Table of Content templateToc = Template() # Create template for Table of Content newColTextBox('\nTable of Content', 3, 0, 4, 1, fill=BOX_COLOR, fontSize=32, parent=templateToc) newColTextBox('', 3, 1, 4, 8, eId=tocId, fill=BOX_COLOR, parent=templateToc) # Template for literature reference index. templateLiteratureIndex = Template( ) # Create template for Table of Content newColTextBox('\nLiterature index', 3, 0, 4, 1, fill=BOX_COLOR, fontSize=32, parent=templateLiteratureIndex) newColTextBox('', 3, 1, 4, 8, eId=literatureIndexId, fill=BOX_COLOR, parent=templateLiteratureIndex) # Template for image reference index. templateImageIndex = Template() # Create template for Table of Content newColTextBox('\nImage index', 3, 0, 4, 1, fill=BOX_COLOR, fontSize=32, parent=templateImageIndex) newColTextBox('', 3, 1, 4, 8, eId=imageIndexId, fill=BOX_COLOR, parent=templateImageIndex) # Template 1 template1 = Template() # Create template of main size. Front page only. # Create empty image place holders. To be filled by running content on the page. # In this templates the images fill the left column if there is a reference on the page. newColPlacer(0, 0, 3, 3, parent=template1) # Empty image element, cx, cy, cw, ch newColPlacer(0, 3, 3, 3, parent=template1) newColPlacer(0, 6, 3, 3, parent=template1) # Create linked text boxes. Note the "nextPage" to keep on the same page or to next. newColTextBox('ABC', 3, 0, 4, 9, eId=flowId1, nextBox=flowId1, nextPage=1, fill=BOX_COLOR, parent=template1) newColTextBox('', 3, 9, 3, 2, eId=footnotesId, fill=BOX_COLOR, parent=template1) # Create page number box. Pattern pageNumberMarker is replaced by FormattedString of actual page number. # Mark the text box, so we can find it back later. newColTextBox(['pageIdMarker'], 6, 9, 1, 1, eId=pageNumberId, font=BOOK, fontSize=12, fill=BOX_COLOR, xAlign=RIGHT, parent=template1) # Create new document with (w,h) and fixed amount of pages. # Make number of pages with default document size. # Initially make all pages default with template2 doc = Document(autoPages=5, template=template1) rs = doc.getRootStyle() rs['openTypeFeatures'] = dict(zero=Slashed_Zero, smcp=Smallcaps, c2sc=Caps_As_Smallcaps, ss08=Italic_Shapes, ss07=Condensed, ss01=Extended_Ascenders, ss02=Extended_Capitals, ss03=Extended_Descenders, ss04=Contrast_Pixel, ss09=Alternative_g, onum=LC_Figures) # Cache some values from the root style that we need multiple time to create the tag styles. fontSize = rs['fontSize'] leading = rs['leading'] rLeading = rs['rLeading'] listIndent = rs['listIndent'] language = rs['language'] # Add styles for whole document and text flows. # Note that some values are defined here for clarity, even if their default root values # are the same. doc.newStyle(name='chapter', font=BOOK) doc.newStyle(name='title', fontSize=3 * fontSize, font=BOLD) doc.newStyle(name='subtitle', fontSize=2.6 * fontSize, font=BOOK_ITALIC) doc.newStyle(name='author', fontSize=2 * fontSize, font=BOOK, fill=(1, 0, 0)) doc.newStyle(name='h1', fontSize=7 * fontSize, font=SEMIBOLD_CONDENSED, fill=(1, 0, 0), leading=7.2 * fontSize, tracking=H1_TRACK, prefix='', postfix='\n') doc.newStyle(name='h2', fontSize=1.5 * fontSize, font=SEMIBOLD_CONDENSED, fill=0, leading=1.6 * fontSize, rLeading=0, rTracking=H2_TRACK, prefix='\n', postfix='\n', paragraphTopSpacing=U) doc.newStyle(name='h3', fontSize=1.1 * fontSize, font=MEDIUM, fill=0, paragraphTopSpacing=2 * U, paragraphBottomSpacing=U, leading=leading, rLeading=0, rNeedsBelow=2 * rLeading, rTracking=H3_TRACK, prefix='\n', postfix='\n') doc.newStyle(name='h4', fontSize=1.1 * fontSize, font=BOOK, fill=0, leading=leading, rLeading=0, rNeedsBelow=2 * rLeading, rTracking=H3_TRACK, paragraphTopSpacing=U, paragraphBottomSpacing=U, prefix='\n', postfix='\n') # Spaced paragraphs. doc.newStyle( name='p', fontSize=fontSize, font=BOOK, fill=0.1, prefix='', postfix='\n', rTracking=P_TRACK, leading=14, rLeading=0, xAlign=LEFT, hyphenation=True, indent=0, firstLineIndent=2 * U, firstParagraphIndent=0) # TODO: Make firstParagraphIndent to work. # Inline tags need to refined prefix and postfix as non-\n, otherwise they # will inherit these attributes from the parent <p> doc.newStyle(name='b', font=SEMIBOLD, prefix='', postfix='') doc.newStyle(name='em', font=BOOK_ITALIC, textFill=(1, 0, 0), prefix='', postfix='') doc.newStyle(name='hr', stroke=(1, 0, 0), strokeWidth=4) doc.newStyle(name='br', postfix='\n') # Simplest way to make <br/> show newline doc.newStyle(name='a', prefix='', postfix='') # Literature reference. doc.newStyle(name='literatureref', textFill=0.3, fontSize=fontSize - 1) # Footnote reference index. doc.newStyle(name='sup', font=MEDIUM, baselineShift=2, prefix='', postfix=' ', fontSize=fontSize - 2) doc.newStyle( name='li', fontSize=fontSize, font=BOOK, rTracking=P_TRACK, leading=leading, hyphenation=True, # Lists need to copy the listIndex over to the regalar style value. tabs=[(listIndent, LEFT)], indent=listIndent, firstLineIndent=1, postfix='\n') doc.newStyle(name='ul', prefix='', postfix='') doc.newStyle(name='footnote', fill=0, fontSize=0.9 * fontSize, font=BOOK, rTracking=P_TRACK, tabs=[(listIndent, LEFT)], indent=listIndent, firstLineIndent=1, postfix='\n') # Image & captions doc.newStyle( name='img', stroke=0.3, fill=None, rTracking=P_TRACK, language=language, textFill=0.2, strokeWidth=1, leading=leading * 0.8, fontSize=0.8 * fontSize, font=BOOK_ITALIC, hyphenation=True, indent=0, firstLineIndent=0, # Use style['fill'] = transparant color as overlay on image. ) # Generic document layout # Page 1 Cover # Page 2 Title # Page 3 Table of Content # Page 4+ Content (footnotes are shown on the page of their reference) # Page -1 Alphabetical literature reference. # Change template of cover page. # Create filtered Galley for cover page. # See https://docs.python.org/2/library/xml.etree.elementtree.html#xpath-support # for XPath filter syntax. gTitle = Galley() t = Typesetter(doc, gTitle) #t.typesetFile(MD_PATH, style=dict(textFill=1, fontSize=80, font=MEDIUM, leading=84), # xPath='h1') gAuthor = Galley() t = Typesetter(doc, gAuthor) #t.typesetFile(MD_PATH, style=dict(textFill=1, fontSize=24, font=MEDIUM), # xPath='h4') # First one is the author coverPage = doc[1] coverPage.applyTemplate(templateCover) c = Composer(doc) #c.compose(gTitle, coverPage, coverTitleId) #c.compose(gAuthor, coverPage, coverAuthorId) # Change template of Table of Content page tocPage = doc[2] tocPage.applyTemplate(templateToc) mainPage = doc[3] # Create main Galley for this page, for pasting the sequence of elements. g = Galley() t = Typesetter(doc, g) t.typesetFile(MD_PATH) # Fill the main flow of text boxes with the ML-->XHTML formatted text. c = Composer(doc) c.compose(g, mainPage, flowId1) # Now all text is composed on pages, scan for the pages that contain footnotes. # TODO: This will be implemented a function inside Composer in a later version. # Assume the tocBox (Table of Content) to be available on the first page. literatureRefs = {} tocBox, (_, _) = tocPage[tocId] for pageId, page in sorted(doc.pages.items()): if page in (tocPage, coverPage): # Skip these for toc collect and footnotes. continue # Get page box for footnotes fnBox, (_, _) = page[footnotesId] assert fnBox is not None # Otherwise there is a template error. Footnote box needs to exist. for flowId in flowIds: # BUG: Need to check if the marker was really found in the textbox area. # If it is part of the overflow, then it should not be found here. flow, _ = page[flowId] for marker, arguments in findMarkers(flow.fs): if marker == 'footnote': footNoteIsInOverflow = False # Process the foot note. footnoteId = int(arguments) # Footnode ids are numbers. # @@@ Hack to check if the marker is in the overflow text. # In that case, ignore it. for overFlowMarker, overFlowArguments in findMarkers( flow.getOverflow()): # If this marker is a footnote and one that we are looking for, # we can ignore it, because it is in the overflow part of the flow.fs if overFlowMarker == 'footnote' and footnoteId == int( overFlowArguments): footNoteIsInOverflow = True break if not footNoteIsInOverflow: # We found a footnote that is visible on this page and # not in one of the overflow texts. # Process the footnote id and content, usng the “footnote“ content style. # We are re-using the typesetter here. This may become a separate typesetter, if this code # becomes a method of the composer. # TODO: Make this into Galley, in case footnote <p> has child nodes. footnoteText = doc.context.newString( '%d\t%s\n' % (footnoteId, doc.footnotes[footnoteId]['p'].text), page, t.getCascadedStyle(doc.getStyle('footnote'))) # Add the footnote content to the box (it may not be the first to be added. fnBox.append(footnoteText) elif marker in ('h1', 'h2', 'h3', 'h4'): # For now we want them all in the TOC #doc.addToc(marker) pass elif marker == 'literature': # The "arguments" contains the refId, so we can find it in the collected literature references # and then add this page number. # @@@ TODO: check if reference marker is in overflow. Then ignore processing it. doc.literatureRefs[int(arguments)]['pageIds'].append( pageId) # Build the alphabetical literature reference page. # Scan the created pages for literature references and build an index on a new page. literatureIndexPage = doc.newPage(template=templateLiteratureIndex) # Make an alfabetic sorted list of name-->(reference, (pageNumber, ...)) references = {} for refIndex, item in doc.literatureRefs.items(): references[item['nodeId']] = item literatureRefBox = literatureIndexPage.getElement(literatureIndexId) for refId, item in sorted(references.items()): # Now we have a sorted list of reference items, we need to make it into a galley. # Several ways of doing it: Create MarkDown, HTML/XML or directly writing FormattedText. pageNumbers = [] for pageNumber in item['pageIds']: pageNumbers.append( ` pageNumber `) literatureRefBox.append(u'%s – %s\n' % (refId, ', '.join(pageNumbers))) print refId, item['nodeId'], item['node'], item['p'], item['pageIds'] # Build the alphabetical image reference page. # Scan the created pages for image references and build an index on a new page. imageIndexPage = doc.newPage(template=templateImageIndex) # Make an alfabetic sorted list of name-->(reference, (pageNumber, ...)) references = {} for refIndex, item in doc.imageRefs.items(): references[item['nodeId']] = item for imageRefId, item in sorted(references.items()): print imageRefId, item['nodeId'], item['node'], item['p'], item[ 'pageIds'] # Set all pagenumbers and other page-based info for pageId, page in sorted(doc.pages.items()): for e in page.elements: if e.eId == pageNumberId: e.setText('%s' % pageId) break return doc
def makeDocument(): """Make a new document.""" W = H = PageSize # Create a new document, default to the defined page size. doc = Document(w=W, h=H, originTop=False, title='Text Flow', autoPages=2) rs = doc.getRootStyle() rs['fill'] = (1, 1, 0) # Yellow background for debugging rs['font'] = 'Verdana' rs['fontSize'] = 14 rs['textFill'] = 1 #textBoxStyle = doc.addStyle('textbox', dict(fill=color(0, 0, 0, 0.7), # padding=40)) pStyle = doc.addStyle('p', dict(textFill=blackColor)) h1Style = doc.addStyle('h1', dict(fontSize=24, textFill=(0, 0, 1))) #h2Style = doc.addStyle('h2', dict(fontSize=18, textFill=(0, 1, 0))) view = doc.getView() view.padding = 0 # Aboid showing of crop marks, etc. view.showCropMarks = True view.showRegistrationMarks = True view.showFrame = True view.showPadding = True view.showOrigin = True view.showDimensions = False # Get list of pages with equal y, then equal x. #page = doc[1][0] # Get the single page from the document. page0 = doc.getPage(1) # Get page on pageNumber, # first in row (this is only one now). page0.name = 'Page 1' page0.padding = PagePadding s = doc.context.newString('Headline\n', style=h1Style) for n in range(10): s += doc.context.newString(('(Line %d) Volume of text defines' ' the box height.' ' Volume of text defines' ' the box height. \n') % (n + 1), style=pStyle) h1 = None e1 = newTextBox( s, name='CSSTextBox1', parent=page0, padding=4, x=100, font='Verdana', h=h1, mb=20, mr=10, # Conditions make the element # move to top-left of the page. gridX=((fr(3), px(8)), (fr(2), px(8))), # And the condition that there should be no overflow, # otherwise the text box will try to solve it. conditions=[Left2Left(), Fit2Width(), Float2Top()], # Position of the origin of the element. # Just to show where it is. # Has no effect on the position conditions. yAlign=BOTTOM, xAlign=LEFT, leading=5, fontSize=9, textFill=blackColor, strokeWidth=pt(0.5), fill=color(0.9), stroke=noColor) print(e1.style) newTextBox( s, # Empty box, will get the overflow # from e1, if there is any. name='CSSTextBox2', # Flow reference by element.name parent=page0, padding=4, x=100, h=200, conditions=[Left2Left(), Fit2Width(), Float2Top()], yAlign=TOP, fill=whiteColor, stroke=noColor) score = doc.solve() # Try to solve all pages. if score.fails: print(score.fails) return doc # Answer the doc for further doing.