Example #1
0
 def _get_tailIndent(self):
     fontSize = self.nsFont.pointSize()
     return em(self.nsParagraphStyle.tailIndent() / fontSize, base=fontSize)
 def _get_descender(self):
     """Returns the current font descender as Em, based on the current font
     and fontSize."""
     fontSize = upt(self.fontSize)
     return em(self.s.fontDescender()/fontSize, base=fontSize)
 def _get_leading(self):
     """Returns the current font leading, based on the current font and fontSize."""
     fontSize = upt(self.fontSize)
     return em(self.s.fontLeading()/fontSize, base=fontSize)
Example #4
0
sequenceAxes = font.axes.keys()
sequenceLength = 3 # Seconds per sequences
sequences = len(sequenceAxes)
duration = sequenceLength * sequenceAxes # Total duration of animation
framesPerSecond = 10
frames = duration * framesPerSecond # Total number of frames
axisFrames = sequenceLength * framesPerSecond

doc = Document(w=w, h=h, originTop=False, frameDuration=1/framesPerSecond, 
    autoPages=frames, context=c)
sample = font.info.familyName #'Decovar'

pn = 1
for axisTag in font.axes.keys():
    axisFrames = 
    minValue, defaultValue, maxValue = font.axes[axisTag]
    for frameIndex in range(1, len(font.axes)):
        page = doc[pn]
        axisRange = maxValue - minValue
        phisin = sin(radians(frameIndex/self.frames * 360))
        phicos = cos(radians(self.frameIndex/self.frames * 360))
        
        location = {phisin*wdthRange/2+wdthRange/2+wdthMin, wght=phisin*wghtRange/2+wghtRange/2+wghtMin)
        style = dict(leading=em(1.4), fontSize=400, xTextAlign=RIGHT, fill=blackColor)
        af = AnimatedBannerFrame(font, frames, pn, parent=page, padding=20, style=style, 
            sampleText=sample, w=page.pw, h=page.ph, context=c)
        pn += 1


doc.export('_export/%s_%s.gif' % (font.info.familyName, sample))
Example #5
0
Parents want us to live an amazing, safe life. But if you want to do anything worthwhile, there’s a little risk involved. You just have to chase that, and hopefully the people around you will be supportive. 
Exactly. I do have supportive people in my life, and I’m incredibly thankful for that. My husband has been a huge supporter of mine since I was 16. My family, his family, and all of our siblings have been equally supportive. Everyone who has worked at RoAndCo has also helped to push me along and make decisions that I never would have made on my own.

They’re looking to you to lead. 
Yeah! They’re not only looking to me, but some of them are also helping me lead and telling me what we should do and what the next step is. Sometimes I’m risk-averse or not ready to move on, but they’re there to say, “No, you’re ready. Let’s do it!”

Do you feel a responsibility to contribute to something bigger than yourself, or outside of yourself? 
Definitely. As I’ve gotten older, I’ve embraced that I’m part of a larger graphic design community, and I get satisfaction from being involved in it. I’m on the board of directors for the AIGA/NY chapter and it’s amazing to sit around a table with other designers and business owners who’ve experienced similar challenges, successes, and situations. I’m so excited to be a part of that. Aside from serving on the board, I also like giving back to the community by hosting events and moderating panels with other designers.
With age and perspective—and since having my daughter—I’ve grown to look at the world differently. My very selfish world has been turned on its head. I no longer think about my personal achievements. Instead, I think about the success of my business and the employees who work at RoAndCo. I’m working on helping them evolve as individuals and grow into their roles, beyond their initial expectations. That has been a wonderful experience.

What have you learned over the years that you would want to share with your younger self? There’s a lot of advice I would give to my younger self. Thinking about it now, I should have taken stock and appreciated what I had along the way. I was constantly concerned with wanting more. I had an inherent determination to keep going forward, to keep trying to succeed and quickly move on. I didn’t take a step back to think, “I’m so grateful for what I currently have.” I also didn’t take the time to thank the people who helped me as often as I should have. I guess we take a lot for granted when we’re young."""

font = findFont('Georgia')
style = dict(font=font,
             fontSize=9.4,
             leading=em(1.4),
             textFill=0.2,
             hyphenation=True)
t = context.newString(text, style=style)

# Quote Style
text2 = """I want to be a good role model for her. It’s important that she can look back at what I’ve done and feel empowered to do whatever she wants to do. I want my daughter to dream big and achieve each and every goal. """
text2 = text2.upper()
font2 = findFont('Druk Medium')
style2 = dict(font=font2,
              fontSize=23,
              leading=em(1),
              textFill=0.3,
              hyphenation=True)
t2 = context.newString(text2, style=style2)
Example #6
0
PH = H - 2 * PADDING  # Usable padded page height
CW = (PW - G) / 2  # Column width
CH = PH
# Hard coded grid, will be automatic in later examples.
GRIDX = ((CW, G), (CW, G))
GRIDY = ((CH, 0), )

# Dummy text, combining some articles to create the length we need for this example
text = ' '.join(sampleContent.articles[:2])

font = findFont('PageBot-Regular')
print(font)

style = dict(font=font,
             fontSize=24,
             leading=em(1.4),
             textFill=0.3,
             hyphenation=True)
# Make long text to force box overflow
t = context.newString(text, style=style)
# Create a new document with 1 page. Set overall size and padding.
# TODO: View drawing for OriginTop=True does not work properly
doc = Document(w=W,
               h=H,
               padding=PADDING,
               gridX=GRIDX,
               gridY=GRIDY,
               context=context,
               originTop=False)
# Get the default page view of the document and set viewing parameters
view = doc.view
Example #7
0
class Typesetter:
    """Mostly used by the Composer, fhe Typesetter takes one or more markdown files or a sequence
    of markdown strings and builds a galley, using a dictionary of styles for the formatted string
    attributes. The result of the typesetting is a self.galley, that contains a sequence of Element
    instances, such as formatted images, textboxes (with BabelStrings), ruler elements and other
    nested galleys.
    """
    IMAGE_CLASS = Image
    TEXTBOX_CLASS = TextBox
    RULER_CLASS = Ruler
    GALLEY_CLASS = Galley
    CODEBLOCK_CLASS = CodeBlock

    DEFAULT_BULLET = u'•' # Used if no valid bullet string can be found in styles.
    SKIP_TAGS = ('document', 'pre')

    # Default styles for Typesetter, based on the standard markdown HTML-tags
    # Some ugly colors to show that we're in default mode here, for the user to
    # supply a better set.
    DEFAULT_STYLES = dict(
        body=dict(font='Georgia', fontSize=pt(10), leading=em(1.2), textFill=blackColor),
        h1=dict(font='Verdana', fontSize=pt(18), leading=em(1.2), textFill=color(1, 0, 0)),
        h2=dict(font='Verdana', fontSize=pt(16), leading=em(1.2), textFill=color(1, 0, 0.5)),
        h3=dict(font='Georgia', fontSize=pt(14), leading=em(1.2), textFill=color(1, 0.5, 0.5)),
        h4=dict(font='Georgia', fontSize=pt(12), leading=em(1.2), textFill=color(0, 1, 1)),
        h5=dict(font='Georgia-Bold', fontSize=pt(10), leading=em(1.2), textFill=(1, 0, 1)),
        p=dict(font='Georgia', fontSize=pt(10), leading=em(1.2), textFill=(0.5, 1, 0.5)),
        li=dict(font='Verdana', fontSize=pt(10), leading=em(1.2), textFill=color(0.5)),
        em=dict(font='Georgia-Bold'),
    )
    MARKDOWN_EXTENSIONS = [ 
        # These extension are needed to make PageBot markdown compatible with 
        # default MacDown behavior.
        InlineExtension(), 
        FencedCodeExtension(), 
        FootnoteExtension(), 
        LiteratureExtension(), 
        Nl2BrExtension(),
    ]

    def __init__(self, context, styles=None, galley=None, skipTags=None,
            imageAsElement=False, tryExcept=True):
        """
        The Typesetter instance interprets an XML or Markdown file (.md) and converts it into
        a Galley instance, with formatted string depending on the current context.

        >>> from pagebot import getResourcesPath
        >>> from pagebot.toolbox.units import em, pt
        >>> from pagebot.toolbox.color import color, blackColor
        >>> from pagebot.contexts.htmlcontext import HtmlContext
        >>> context = HtmlContext()
        >>> h1Style = dict(font='Verdana', fontSize=pt(24), textFill=color(1, 0, 0))
        >>> h2Style = dict(font='Georgia', fontSize=pt(18), textFill=color(1, 0, 0.5))
        >>> h3Style = dict(font='Georgia', fontSize=pt(14), textFill=color(0, 1, 0))
        >>> pStyle = dict(font='Verdana', fontSize=pt(10), leading=em(1.4), textFill=blackColor)
        >>> styles = dict(h1=h1Style, h2=h2Style, p=pStyle)
        >>> t = Typesetter(context, styles=styles) # Create a new typesetter for this context
        >>> mdText = '''
        ... ~~~Python
        ... box = page.select['content']
        ... ~~~
        ... # H1 header
        ... ## H2 header
        ... ### H3 header
        ... ~~Delete~~
        ... _Underline_
        ... ==Mark==
        ... *Em*
        ... "Quote"
        ... **Strong**
        ... //Emphasis//
        ... ^Sup
        ... !!Sub
        ... '''
        >>> galley = t.typesetMarkdown(mdText)
        >>> len(galley.elements)
        3
        >>> galley.elements[1].bs # Rendered by HtmlContext 
        box = page.select['content']
        <BLANKLINE>
        >>> galley.elements[2].bs # Rendered by HtmlContext
        <BLANKLINE>
        <BLANKLINE>
        <h1>H1 header</h1>
        <h2>H2 header</h2>
        <h3>H3 header</h3>
        <p><del>Delete</del>
        <u>Underline</u>
        <mark>Mark</mark>
        <em>Em</em>
        <q>Quote</q>
        <strong>Strong</strong>
        <emphasis>Emphasis</emphasis>
        ^Sup
        !!Sub</p>
        """
        self.context = context
        # Find the context, in case no doc has be defined yet.
        if galley is None:
            galley = self.GALLEY_CLASS(context=context)
        self.galley = galley

        if styles is None:
            styles = self.DEFAULT_STYLES
        self.styles = styles # Style used, in case the current text box does not have them.

        self.imageAsElement = imageAsElement # If True, add the image as element. Otherwise embed as tag.

        # Stack of graphic state as cascading styles. Last is template for the next.
        self.gState = []
        self.tagHistory = []
        # Save some flags in case the typesetter is running in Python try-except mode.
        self.tryExcept = tryExcept
        # If True add tags to the output, otherwise ignore. Can be overwritten by caller for debugging.
        self.writeTags = context.useTags
        self.root = None # Will contain the root node after executing typesetFile.

        # Some MarkDown generated tags need to be skipped on output, while their content still is processed.
        if skipTags is None:
            skipTags = self.SKIP_TAGS
        self.skipTags = skipTags

    def node_h1(self, node, e):
        """Handle the <h1> tag."""
        # Add line break to whatever style/content there was before.
        # Add invisible h1-marker in the string, to be retrieved by the composer.
        #headerId = self.document.addTocNode(node) # Store the node in the self.document.toc for later TOC composition.
        #self.append(getMarker(node.tag, headerId)) # Link the node tag with the TOC headerId.
        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_h2(self, node, e):
        """Handle the <h2> tag."""
        # Add line break to whatever style/content there was before.
        # Add invisible h2-marker in the string, to be retrieved by the composer.
        #headerId = self.document.addTocNode(node) # Store the node in the self.document.toc for later TOC composition.
        #self.append(getMarker(node.tag, headerId)) # Link the node tag with the TOC headerId.
        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_h3(self, node, e):
        """Handle the <h3> tag."""
        # Add line break to whatever style/content there was before.
        # Add invisible h3-marker in the string, to be retrieved by the composer.
        #headerId = self.document.addTocNode(node) # Store the node in the self.document.toc for later TOC composition.
        #self.append(getMarker(node.tag, headerId)) # Link the node tag with the TOC headerId.
        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_h4(self, node, e):
        """Handle the <h4> tag."""
        # Add line break to whatever style/content there was before.
        # Add invisible h4-marker in the string, to be retrieved by the composer.
        #headerId = self.document.addTocNode(node) # Store the node in the self.document.toc for later TOC composition.
        #self.append(getMarker(node.tag, headerId)) # Link the node tag with the TOC headerId.
        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_h5(self, node, e):
        """Handle the <h5> tag."""
        # Add line break to whatever style/content there was before.
        # Add invisible h4-marker in the string, to be retrieved by the composer.
        #headerId = self.document.addTocNode(node) # Store the node in the self.document.toc for later TOC composition.
        #self.append(getMarker(node.tag, headerId)) # Link the node tag with the TOC headerId.
        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_hr(self, node, e):
        """Add Ruler instance to the Galley."""
        if self.peekStyle() is None and e is not None:
            # Root of stack is empty style, to force searching on the e.parent line.
            self.pushStyle({}) # Define top level for styles.
        hrStyle = self.getNodeStyle(node.tag) # Merge found tag style with current top of stack
        self.RULER_CLASS(e, style=hrStyle, parent=self.galley) # Make a new Ruler instance in the Galley
        
    def getStyleValue(self, name, e=None, style=None, default=None):
        """Answers the best style value match for *name*, depending on the status of *style*, *e* and *default*,
        on that order. Answer None if everything failes."""
        value = None
        
        if style is not None:
            value = style.get(name)
        if value is None and e is not None:
            value = e.css(name)
        if value is None:
            value = default
        return value

    # Solve <br/> best by simple style with: doc.newStyle(name='br', postfix='\n')

    def node_br(self, node, e):
        """Add newline instance to the Galley."""
        # For now, just ignore, as <br/> already get a break in MarkDown, as part of the exclosing tag.
        # TODO: now <br/> makes the same vertical spacing as <p>
        """
        if self.peekStyle() is None and e is not None:
            # Root of stack is empty style, to force searching on the e.parent line.
            self.pushStyle({}) # Define top level for styles.
        brStyle = self.getNodeStyle(node.tag) # Merge found tag style with current top of stack
        s = self.getStyleValue('prefix', e, brStyle, default='') + '\n' + self.getStyleValue('postfix', e, brStyle, default='')
        bs = self.context.newString(s, e=e, style=brStyle)
        self.append(bs) # Add newline in the current setting of FormattedString
        """
    def node_a(self, node, e):
        """Ignore links, but process the block"""
        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_sup(self, node, e):
        """Collect footnote references on their page number.
        And typeset the superior footnote index reference."""
        nodeId = node.attrib.get('id')
        # Check if this is a footnote reference
        if nodeId is not None and nodeId.startswith('fnref'): # This is a footnote reference.
            footnotes = self.getFootnotes(e)
            if footnotes is not None:
                nodeId = nodeId.split(':')[1]
                index = len(footnotes)+1
                # Footnode['p'] content node will be added if <div class="footnote">...</div> is detected.
                footnotes[index] = dict(nodeId=nodeId, index=index, node=node, e=e, p=None)
                # Add invisible mark, so we can scan the text after page composition to find
                # on which page it ended up.
                #self.append(getMarker('footnote', index))

        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_literatureref(self, node, e):
        """Collect literature references."""
        # Typeset the block of the tag.
        # Check if this is a literature reference
        nodeId = node.attrib.get('id')
        if nodeId.startswith('litref:'): # It is a literature reference.
            literatureRefs = self.getLiteratureRefs(e)
            if literatureRefs:
                nodeId = nodeId.split(':')[1]
                index = len(literatureRefs)+1
                # Warning if the reference id is already used.
                assert not nodeId in literatureRefs
                # Make literature reference entry. Content <p> and split fields will be added later.
                literatureRefs[index] = dict(nodeId=nodeId, node=node, e=e, p=None, pageIds=[])
                #self.append(getMarker('literature', index))

        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_div(self, node, e):
        """MarkDown generates <div class="footnote">...</div> and <div class="literature">...</div>
        as output at the end of the HTML export. We will handle them separately by looking them up
        in the XML-tree. So we'll skip them in the regular flow process."""

        if node.attrib.get('class') == 'footnote':
            # Find the content of the footnotes. Store the content and add marker.
            footnotes = self.getFootnotes(e)
            if footnotes is not None:
                for index, p in enumerate(node.findall('./ol/li/p')):
                    if index+1 in footnotes:
                        # Store the content as node, so we can process it with a Typesetter in case of child nodes.
                        footnotes[index+1]['p'] = p
                    else:
                        print('### Warning: %d footnote reference not found. %s' % (index+1, footnotes.keys()))
            result = None # Nothing to return, we handled the references

        elif node.attrib.get('class') == 'literature':
            literatureRefs = self.getLiteratureRefs(e)
            if literatureRefs:
                for index, p in enumerate(node.findall('./ol/li/p')):
                    if index+1 in literatureRefs:
                        # Store the content as node, so we can process it with a Typesetter in case of child nodes.
                        # Spltting fields inside the p content will be done by the calling application or Composer.
                       literatureRefs[index+1]['p'] = p
                    else:
                        print('### Warning: %d literature reference not found. %s' % (index+1, literatureRefs.keys()))

        else:
            self.typesetNode(node, e)


    def node_li(self, node, e):
        """Generate bullet/Numbered list item."""
        context = self.galley.context
        bullet = self.DEFAULT_BULLET # Default, in case doc or css does not exist.
        style = self.styles.get('bullet') or self.styles.get('li') or self.styles.get('p')
        bulletString = context.newBulletString(bullet, e=e, style=style) # Get styled string with bullet.
        if bulletString is not None: # HtmlContext does not want a bullet character.
            self.append(bulletString) # Append the bullet as defined in the style.
        # Typeset the block of the tag.
        self.typesetNode(node, e)

    def node_img(self, node, e):
        """Process the image. adding the img tag or a new image element to the galley.
        The alt attribute can contain additional information for the Image element."""
        # Typeset the empty block of the img, which creates the HTML tag.
        if self.imageAsElement:
            self.galley.appendElement(self.IMAGE_CLASS(path=node.attrib.get('src'), 
                alt=node.attrib.get('alt'), index=0))
        else:
            self.htmlNode_(node)

    def node_pre(self, node, e):
        """<pre> is part of the code block. Ignore the tag and create a CodeBlock element instance
        on the <code> node."""
        self.typesetNode(node, e)

    def node_code(self, node, e):
        """Create a NodeBlock element, that contains the code source, to be executed by
        the Composer in sequence of composition."""
        self.CODEBLOCK_CLASS(node.text, parent=self.galley)

    def pushStyle(self, tag):
        """Push the cascaded style on the gState stack. Make sure that the style is not None and that it
        is a cascaded style, otherwise it cannot be used as source for child styles. Answer the cascaded
        style as convenience for the caller. """
        self.gState.append(tag)

    def popStyle(self):
        """Pop the cascaded style from the gState stack and answer the next style that is on top.
        Make sure that there still is a style to pop, otherwise raise an error. """
        assert self.gState
        self.gState.pop()
        return self.peekStyle()

    def peekStyle(self):
        """Answers the top cascaded style, without changing the stack."""
        if not self.gState: # It's empty, answer None
            return None
        return self.gState[-1]

    def addHistory(self, tag):
        """Add the *tag* to the history."""
        if not self.tagHistory or tag != self.tagHistory[-1]:
            self.tagHistory.append(tag)

    def getHistory(self):
        return self.tagHistory

    def getFootnotes(self, e):
        """Answers the footnotes dictionary from the e.lib (derived from the root document)"""
        if self.doc is not None:
            lib = self.doc.lib
            if lib is not None:
                if not 'footnotes' in lib:
                    lib['footnotes'] = {}
                return lib['footnotes']
        return None

    def getLiteratureRefs(self, e):
        """Answers the literature reference dictionary from the e.lib (derived from the root document)"""
        if self.doc is not None:
            lib = self.doc.lib
            if lib is not None:
                if not 'literatureRefs' in lib:
                    lib['literatureRefs'] = {}
                return lib['literatureRefs']
        return None

    def getImageRefs(self, e):
        """Answers the image reference dictionary from the e.lib (derived from the root document)
        if it exists. Otherwise create an empty e.lib['imageRefs'] and answer it as empty dictionary.
        Answer None if e.lib does not exist."""
        lib = e.lib
        if lib is not None:
            if not 'imageRefs' in lib:
                lib['imageRefs'] = {}
            return lib['imageRefs']
        return None

    def _strip(self, s, prefix=None, postfix=None, forceRightStrip=False):
        """Strip the white space from string *s* if *prefix* and/or *postfix* are not None.
        Otherwise answer the untouched *s*."""
        if prefix is not None: # Strip if prefix is not None. Otherwise don't touch.
            s = prefix + (s or '').lstrip() # Force s to empty string in case it is None, to add prefix.
        elif forceRightStrip:
            s = (s or '').rstrip() # Force s to empty string in case it is None.
        elif postfix is not None: # Strip if postfix is not None. Otherwise don't touch.
            s = (s or '').rstrip() + postfix # Force s to empty string in case it is None, to add postfix.
        return s

    def getMatchingStyleNames(self, tag):
        """Answers the list of matching style, with decreasing relevance."""
        revHistory = self.tagHistory[:]
        revHistory.reverse()
        matches = []
        for n in range(len(revHistory)):
            styleName = revHistory[:n+1]
            styleName.reverse()
            styleName = ' '.join(styleName)
            style = self.getNamedStyle(styleName)
            if style:
                matches.append(styleName)
        matches.reverse()
        return matches

    def getNamedStyle(self, styleName):
        """Answers the named style and otherwise an empty style dict if the named style
        does not exist."""
        return self.styles.get(styleName, {})

    def getNodeStyle(self, tag):
        """Make a copy of the top of the style graphics state and mew *style* into it. Answer the new style."""
        if self.peekStyle() is None: # Not an initialized stack, use doc.rootStyle as default.
            self.pushStyle(self.getNamedStyle('root')) # Happens if calling directly, without check on e
        mergedStyle = copy.copy(self.peekStyle())
        # Find the best matching style for tag on order of relevance,
        # considering the possible HTML tag parents and the history.
        for styleName in self.getMatchingStyleNames(tag):
            nodeStyle = self.getNamedStyle(styleName)
            if nodeStyle: # Not None and not empty
                for name, value in nodeStyle.items():
                    mergedStyle[name] = value
                break
        return mergedStyle

    def append(self, bs):
        """Append the string (or BabelString instance) to the last textbox in galley,
        if it exists. Otherwise create a new TextBox and add it to self.galley."""
        if self.galley.elements and self.galley.elements[-1].isTextBox:
            self.galley.elements[-1].bs += bs
        else:
            self.TEXTBOX_CLASS(bs, parent=self.galley)

    def htmlNode(self, node, end=False):
        """Open the tag in HTML output and copy the node attributes if there are any."""
        htmlTag = u'<%s' % node.tag
        attrs = []
        for name, value in node.items():
            if name == 'src' and value.startswith('docs/'): # Exception hack to bridge the .md --> img url.
                value = value[5:]
            attrs.append('%s="%s"' % (name, value))
        if attrs:
            htmlTag += u' '+u' '.join(attrs)
        if end:
            htmlTag += '/'
        htmlTag += '>'
        self.append(htmlTag)

    def _htmlNode(self, node):
        """Close the html tag of node."""
        self.append('</%s>' % node.tag)

    def htmlNode_(self, node):
        """Opem+close the html tag of node."""
        self.htmlNode(node, end=True)

    def typesetString(self, sOrBs, e=None, style=None):
        """If s is a formatted string, then it is placed untouched. If it is a plain string, then
        use the optional *style* or element *e* (using *e.css(name)*) for searching style parameters.
        Answer the new formatted string for convenience of the caller. e.g. to measure its size."""
        # Only convert if not yet BabelString instance.
        bs = self.context.newString(sOrBs, e=e, style=style)
        self.append(bs)
        return bs

    def typesetNode(self, node, e=None):
        """Recursively typeset the etree *node*, using a reference to element *e* or the cascading *style*.
        If *e* is None, then the tag style is merged on top of the doc.rootStyle. If *e* is defined, then
        rootstyle of the stack starts with an empty dictionary, leaving root searching for the e.parent path."""

        # Ignore <pre> tag output, as it is part of a ~~~Pyhton code block
        if self.writeTags and not node.tag in self.skipTags:
            # Open the node in HTML export for this node
            self.htmlNode(node)
        # Add this tag to the tag-history line. It is used to connect to the right style in case
        # we are rendering towards a FormattedString or another context-equivalent.
        self.addHistory(node.tag)

        # If e is undefined, then we make sure that the stack contains the doc.rootStyle on top.
        # If e is defined then root queries for style should follow the e.parent path.
        if self.peekStyle() is None and e is not None:
            # Root of stack is empty style, to force searching on the e.parent line.
            self.pushStyle({}) # Define top level for styles.
        nodeStyle = self.getNodeStyle(node.tag) # Merge found tag style with current top of stack
        self.pushStyle(nodeStyle) # Push this merged style on the stack

        # XML-nodes are organized as: node - node.text - node.children - node.tail
        # If there is no text or if the node does not have tail text, these are None.
        # Still we want to be able to add the prefix to the node.text, so then the text is changed to an empty string.

        nodeText = self._strip(node.text)
        if nodeText: # Not None and still has content after stripping?
            # Don't cache the context from self.galley as variable, as it may become dynamically updated by code blocks.
            # The galley context will define the type of BabelStrings generated by the Typesetter.
            bs = self.context.newString(nodeText, e=e, style=nodeStyle)
            self.append(bs)

        # Type set all child node in the current node, by recursive call.
        for child in node:
            hook = 'node_'+child.tag
            # Method will handle the styled body of the element, but not the tail.
            if hasattr(self, hook):
                # There is a hook for this node, let this method do the work.
                getattr(self, hook)(child, e) # Hook must be able to derive styles from e.
                # We are in tail mode now, but we don't know what happened in the child block.
            else:
                # If no method hook defined, then just solve recursively. Child node will get the style.
                self.typesetNode(child, e)
            # XML-nodes are organized as: node - node.text - node.children - node.tail
            # If there is no text or if the node does not have tail text, these are None.
            # Still we want to be able to add the postfix to the tail, so then the tail is changed
            # to empty string?
            childTail = child.tail #self._strip(child.tail, postfix=self.getStyleValue('postfix', e, nodeStyle, ''))
            if childTail: # Any tail left after stripping, then append to the galley.
                # Don't cache the context from self.galley as variable, as it may become dynamically updated by code blocks.
                bs = self.context.newString(childTail, e=e, style=nodeStyle)
                self.append(bs)

        # Ignore </pre> tag output, as it is part of a ~~~Pyhton code block
        if self.writeTags and not node.tag in self.skipTags:
            # Close the HTML tag of this node.
            self._htmlNode(node)

        # Now restore the graphic state at the end of the element content processing to the
        # style of the parent in order to process the tail text. Back to the style of the parent,
        # which was in nodeStyle.
        self.popStyle()

    def markDown2XmlFile(self, fileName, mdText, mdExtensions=None):
        """Take the markdown source, convert to HTML/XML and save in the file called fileName.
        If the fileName does not end with ".xml" extension, then add it. Answer the (new) fileName.

        >>> from pagebot.contexts.htmlcontext import HtmlContext
        >>> md = '''## Subtitle at start\\n\\n~~~\\npage = page.next\\n~~~\\n\\n# Title\\n\\n##Subtitle\\n\\nPlain text'''
        >>> context = HtmlContext()
        >>> t = Typesetter(context)
        >>> fileName = t.markDown2XmlFile('/tmp/PageBot_Typesetter_test.xml', md)
        >>> os.remove(fileName)
        """
        if mdExtensions is None:
            mdExtensions = self.MARKDOWN_EXTENSIONS
        xmlBody = markdown.markdown(mdText, extensions=mdExtensions)
        xml = u'<?xml version="1.0" encoding="utf-8"?>\n<document>%s</document>' % xmlBody
        xml = xml.replace('&nbsp;', ' ')
        if not fileName.endswith('.xml'):
            fileName = fileName + '.xml' # Make sure file name has xml extension.
        f = codecs.open(fileName, mode="w", encoding="utf-8") # Save the XML as unicode.
        f.write(xml)
        f.close()
        return fileName

    def typesetMarkdown(self, mdText, mdExtensions=None, e=None, xPath=None):
        tmpPath = '/tmp/PageBot_Typesetter.xml'
        fileName = self.markDown2XmlFile(tmpPath, mdText, mdExtensions)
        self.typesetFile(fileName, e=e, xPath=xPath)
        os.remove(tmpPath)
        return self.galley

    def typesetFile(self, fileName, e=None, xPath=None):
        """Read the XML document and parse it into a tree of document-chapter nodes. Make the typesetter
        start at page pageNumber and find the name of the flow in the page template.
        The optional filter can be a list of tag names that need to be included in the
        composition, ignoring the rest.
        The optional rootStyle can be defined as style for the root tag, cascading force all
        child elements. Answer the root node for convenience of the caller."""
        fileExtension = fileName.split('.')[-1]
        if fileExtension == 'md':
            # If we have MarkDown content, convert to XML (XHTML)
            f = codecs.open(fileName, mode="r", encoding="utf-8")
            mdText = f.read() # Read the raw MarkDown source
            f.close()
            fileName = self.markDown2XmlFile(fileName, mdText) # Translate MarkDown to HTML and save in file.
        tree = ET.parse(fileName)
        self.root = tree.getroot() # Get the root element of the tree and store for later retrieval.
        # If there is XSL filtering defined, they get the filtered nodes.
        if xPath is not None:
            filteredNodes = self.root.findall(xPath)
            if filteredNodes:
                # How to handle if we got multiple result nodes?
                self.typesetNode(filteredNodes[0], e)
        else:
            # Collect all flowing text in one formatted string, while simulating the page/flow, because
            # we need to keep track on which page/flow nodes results get positioned (e.g. for toc-head
            # reference, image index and footnote placement.
            self.typesetNode(self.root, e)

        # Answer the self.galley as convenience for the caller.
        return self.galley
Example #8
0
    #getFamily('Bungee'),
    #getFamily('Roboto'),
    #getFamily('AmstelvarAlpha')
)
#print('Proforma', FAMILIES[1].getStyles().keys())

#labelFamily = getFamily('Roboto')
labelFamily = getFamily('Upgrade')
labelFont = labelFamily.findRegularFont(
)  # Ask family to find the most regular font.
labelItalicFont = labelFamily.findRegularFont(
    italic=True)  # Ask family to find the most regular font.

labelStyle = dict(font=labelFont.path,
                  fontSize=7,
                  leading=em(1),
                  paragraphTopSpacing=4,
                  paragraphBottomSpacing=4)
fontSetStyle = dict(font=labelItalicFont.path,
                    fontSize=9,
                    xTextAlign=CENTER,
                    leading=em(1.25))
charSetStyle = dict(font=labelFont.path,
                    fontSize=10,
                    xTextAlign=CENTER,
                    leading=em(1.25))
descriptionStyle = dict(font=labelFont.path,
                        fontSize=12,
                        xTextAlign=CENTER,
                        leading=em(1.25))
Example #9
0
def buildSpecimenPages(page, family):
    page.padding = PADDING
    page.gridX = GRID_X
    pageTitle = family.name
    # Add filling rectangle for background color of the old paper book.
    # Set z-azis != 0, to make floating elements not get stuck at the background
    newRect(z=-10, w=W, h=H, parent=page, fill=PAPER_COLOR)
    # During development, draw the template scan as background
    # Set z-azis != 0, to make floating elements not get stuck at the background
    if SHOW_TEMPLATE:
        newImage(FB_PATH_L, x=0, y=0, z=-10, w=W / 2, parent=page)
        newImage(FB_PATH_R, x=W / 2, y=0, z=-10, w=W / 2, parent=page)

    # Left and right family name the current font.
    titleBs = context.newString(pageTitle,
                                style=dict(font=labelFont.path,
                                           fontSize=16,
                                           xTextAlign=LEFT,
                                           textFill=0))
    titleBox = newTextBox(titleBs,
                          parent=page,
                          h=3 * U,
                          w=C3,
                          conditions=[Top2Top(), Left2Left()],
                          fill=DEBUG_COLOR0)

    titleBs = context.newString(pageTitle,
                                style=dict(font=labelFont.path,
                                           fontSize=16,
                                           xTextAlign=RIGHT,
                                           textFill=0))
    titleBox = newTextBox(titleBs,
                          parent=page,
                          h=3 * U,
                          w=C3,
                          conditions=[Top2Top(), Right2Right()],
                          fill=DEBUG_COLOR0)

    lineL = newLine(parent=page,
                    w=C3,
                    h=1,
                    mb=U,
                    strokeWidth=1,
                    stroke=0,
                    conditions=(Float2Top(), Left2Left()))
    lineR = newLine(parent=page,
                    w=C3,
                    h=1,
                    mb=U,
                    strokeWidth=1,
                    stroke=0,
                    conditions=(Float2Top(), Right2Right()))

    descriptionFont = family.findRegularFont()
    description = ''
    if descriptionFont.info.description:
        description += descriptionFont.info.description + ' '
    if descriptionFont.info.trademark:
        description += descriptionFont.info.trademark
    if description:
        description = context.newString(description, style=descriptionStyle)
        _, descriptionH = context.textSize(description, w=C3)
    else:
        descriptionH = 0

    # Get the weightClass-->fonts dictionary, sorted by weight.
    weightClasses = family.getWeights()

    # Text samples on the right
    y = 300  #lineR.bottom
    for weightClass, fonts in sorted(weightClasses.items()):
        for font in fonts:
            if font.isItalic():
                continue
            sample = context.newString(blurb.getBlurb('article'),
                                       style=dict(font=font.path,
                                                  fontSize=9,
                                                  leading=em(1.1)))
            h = H / len(family) + L
            newTextBox(sample,
                       parent=page,
                       w=C3,
                       h=h,
                       conditions=(Right2Right(), Float2Top()),
                       fill=DEBUG_COLOR1)
            y -= h
            if y <= PB + descriptionH:
                break

    if description:
        newTextBox(description,
                   parent=page,
                   w=C3,
                   h=descriptionH,
                   conditions=(Right2Right(), Bottom2Bottom()),
                   fill=DEBUG_COLOR1)

    weightNames = getWeightNames(family)

    charSetString = context.newString(weightNames + '\n\n', style=fontSetStyle)
    charSetString += context.newString(GLYPH_SET, style=charSetStyle)
    _, charSetStringH = context.textSize(charSetString, w=C3)

    newTextBox(charSetString,
               parent=page,
               w=C3,
               h=charSetStringH,
               conditions=(Left2Left(), Bottom2Bottom()))

    page.solve()  # So far with conditional placement.

    # It's easier for this example to position the elements by y-coordinate now, because there
    # is mismatch between the position of the pixel image of the lines and the content of text
    # boxes. Although it is possible to build by floating elements or by on single text, which
    # will show in another proof-revival example.

    y = lineL.bottom - U  # Position at where this went to by solving the layout conditions.
    # Stacked lines on the left, by separate elements, so we can squeeze them by pixel image size.
    for n in range(100):  # That's enough
        headline = blurb.getBlurb('_headline',
                                  cnt=choice(
                                      (2, 3, 4, 4, 4, 4, 4, 5, 6, 7, 8)))
        if random() <= 0.2:
            headline = headline.upper()
        stackLine = context.newString(headline,
                                      style=dict(font=choice(
                                          context.installedFonts()),
                                                 leading=em(-0.2),
                                                 paragraphTopSpacing=0,
                                                 paragraphBottomSpacing=0),
                                      w=C3,
                                      pixelFit=False)
        _, by, bw, bh = stackLine.bounds()
        tw, th = context.textSize(charSetString)
        if y - bh < PB + th:  # Reserve space for glyph set
            break  # Filled the page.
        newTextBox(stackLine,
                   parent=page,
                   x=PL,
                   y=y - bh - by - U,
                   w=C3,
                   h=th + 2,
                   fill=DEBUG_COLOR1)
        y -= bh + by + U
        page = page.nextc
Example #10
0
for n in range(ID_COUNT):
    logo, name = companyName()
    theme = ThemeClasses[choice(themeNames)]()
    ID_DATA.append(dict(logo=logo, name=name, theme=theme))

for idData in ID_DATA:
    # For all the identities, create a sheets with filled business cards

    name = idData['name']
    theme = idData['theme']
    theme.selectMood('light')
    mood = theme.mood
    style = mood.getStyle('logo')
    style['font'] = 'Upgrade-Bold'
    style['fontSize'] = pt(32)
    style['leading'] = em(0.8)

    #style['fill'] = color(spot=300)
    style['textFill'] = mood.logo = color(spot=300)

    style = mood.getStyle('body')
    style['font'] = 'Upgrade-Medium'
    style['leading'] = em(1.2)
    style['xTextAlign'] = CENTER

    style = mood.getStyle('caption')
    style['font'] = 'Upgrade-Italic'
    style['leading'] = em(1.1)
    style['xTextAlign'] = CENTER

    ci = CorporateIdentity(name=name, theme=theme)
Example #11
0
class Site(Publication):
    u"""Build a website, similar to the original template by Kirsten Langmuur.

    """


SITE = [
    ('index', 'PageBot Responsive Home'),
    ('content', 'PageBot Responsive Content'),
    ('page3', 'PageBot Responsive Page 3'),
    ('page4', 'PageBot Responsive Page 4'),
    ('page5', 'PageBot Responsive Page 5'),
]
style = dict(
    fill=color(1, 0, 0),
    margin=em(0),
    padding=em(0),
)
doc = Site(viewId='Site', autoPages=len(SITE), style=style)
view = doc.view
view.resourcePaths = ('css', 'fonts', 'images', 'js')
view.jsUrls = (URL_JQUERY, URL_MEDIA, 'js/main.js')
view.cssUrls = ('fonts/webfonts.css', 'css/normalize.css', 'css/style.css')

for pn, (name, title) in enumerate(SITE):
    page = doc[pn + 1]
    page.name, page.title = name, title
    page.description = 'PageBot SimpleSite is a basic generated template for responsive web design'
    page.keyWords = 'PageBot Python Scripting Simple Demo Site Design Design Space'
    page.viewPort = 'width=device-width, initial-scale=1.0, user-scalable=yes'
    currentPage = name + '.html'
Example #12
0
 def _get_minimumLineHeight(self):
     fontSize = self.nsFont.pointSize()
     return em(self.nsParagraphStyle.minimumLineHeight() / fontSize,
               base=fontSize)
Example #13
0
 def _get_lineHeightMultiple(self):
     fontSize = self.nsFont.pointSize()
     return em(self.nsParagraphStyle.lineHeightMultiple() / fontSize,
               base=fontSize)
Example #14
0
 def _get_firstLineHeadIndent(self):
     fontSize = self.nsFont.pointSize()
     return em(self.nsParagraphStyle.firstLineHeadIndent() / fontSize,
               base=fontSize)
from pagebot.contexts.platform import getContext

from pagebot.fonttoolbox.objects.font import findFont
from pagebot.document import Document
from pagebot.elements import *  # Import all types of page-child elements for convenience
from pagebot.toolbox.color import color
from pagebot.toolbox.units import em, pt
from pagebot.conditions import *  # Import all conditions for convenience.
from pagebot.constants import *  # Import all constants for convenience

#context = FlatContext()
context = getContext()

W = H = pt(1000)  # Document size optionally defined as units
PADDING = pt(80)  # Page padding on all sides
BASELINE = em(1.4)

text = """Considering the fact that the application allows individuals to call a phone number and leave a voice mail, which is automatically translated into a tweet with a hashtag from the country of origin. """

# Get the Font instances, so they can be queried for metrics.
font = findFont('Roboto-Regular')
bold = findFont('Roboto-Bold')

# Defined styles
headStyle = dict(font=bold,
                 fontSize=125,
                 leading=BASELINE,
                 textFill=0.1,
                 hyphenation=False,
                 paragraphBottomSpacing=em(0.2))
style = dict(font=font,
Example #16
0
W = H = pt(1000) # Document size for square pages.
PADDING = pt(100) # Page padding on all sides
G = p(2) # 2 Pica gutter
PW = W - 2*PADDING # Usable padded page width
PH = H - 2*PADDING # Usable padded page height
CW = (PW - 3*G)/4 # Column width
CH = (PH - 3*G)/4 # Column height, same as with in this example, because page is square.
# Hard coded grid, will be automatic in later examples.
GRIDX = ((CW, G), (CW, G), (CW, G), (CW, G))
GRIDY = ((CH, G), (CH, G), (CH, G), (CH, G))

text = """Considering the fact that the application allows individuals to call a phone number and leave a voice mail, which is automatically translated into a tweet with a hashtag from the country of origin. """

font = findFont('Roboto-Regular')

style = dict(font=font, fontSize=12, leading=em(1.4), textFill=0.3, hyphenation=True)
# Make long text to force box overflow
t = context.newString(text * 30, style=style)
# Create a new document with 1 page. Set overall size and padding.
doc = Document(w=W, h=H, padding=PADDING, gridX=GRIDX, gridY=GRIDY, context=context, originTop=True)
# Get the default page view of the document and set viewing parameters
view = doc.view
view.showTextOverflowMarker = True # Shows as [+] marker on bottom-right of page.
# Set types of grid lines to show on foreground/background
view.showGrid = [GRID_COL, GRID_ROW_BG, GRID_SQR_BG]
view.showBaselines = False # Show default setting of baseline grid of the column lines.
#view.padding = inch(1)
#view.showFrame = True
#view.showCropMarks = True
#view.showColorBars = True
Example #17
0
        pw = page.pw # Usable page/frame area, without paddind
        ph = page.ph
        if sequenceIndex == 0:
            x = y = 0
            ww = pw/4 + pw*3/4*phicos
            hh = ph
        elif sequenceIndex == 1:
            x = y = 0
            ww = pw
            hh = ph/4 + ph*3/4*phicos
        elif sequenceIndex == 2:
            x = 0
            y = ph/2 - ph/2*phicos
            ww = pw
            hh = ph - y
        else:
            x = pw/2 - pw/2*phicos
            y = 0
            ww = pw - x
            hh = ph
            
        style = dict(leading=em(1.4), font=font, xTextAlign=RIGHT, textFill=whiteColor, 
            fill=blackColor, roundVariableFitLocation=False)

        af = AnimatedBannerFrame(sample, font, frameCnt, frameIndex, parent=page, style=style, 
            x=x+M, y=y+M, w=ww, h=hh, context=c)
        frameIndex += 1 # Prepare for the next frame

doc.solve()
doc.export('_export/%s_%s.gif' % (font.info.familyName, sample))
def drawAnimation():
    for angle in range(0, 360, int(360/FRAMES)):
        newPage(W, H)
        drawBackground()
        x, y = 100, 360
        dSquare = 80

        radX = -sin(radians(-angle))
        radY = cos(radians(-angle))
        locRadX = -sin(radians(-angle+45))
        locRadY = cos(radians(-angle+45))

        # Reset scale drawing of all icons.
        for icon in icons:
            icon.scale = S
        # Grid
        fill(None)
        stroke(0.6)
        rect(x-dSquare+skiaIcon.w/2, y-dSquare+skiaIcon.w/2, dSquare, dSquare)
        rect(x+skiaIcon.w/2, y-dSquare+skiaIcon.w/2, dSquare, dSquare)
        rect(x-dSquare+skiaIcon.w/2, y+skiaIcon.w/2, dSquare, dSquare)
        rect(x+skiaIcon.w/2, y+skiaIcon.w/2, dSquare, dSquare)

        # Draw icons
        skiaIcon.draw(x, y)
        lightIcon.draw(x-dSquare, y)
        boldIcon.draw(x+dSquare, y)
        condIcon.draw(x, y-dSquare)
        wideIcon.draw(x, y+dSquare)

        fill(1, 0, 0, 0.5)
        stroke(None)
        markerSize = 8
        oval(x+skiaIcon.w/2+dSquare*locRadX*0.9-markerSize/2, y+skiaIcon.w/2+dSquare*locRadY*0.9-markerSize/2, markerSize, markerSize)

        px, py = 280, 220
        d = 250
        sy = 0.5
        fill(None)
        stroke(0.6)
        strokeWidth(1.5)
        # Draw Q-map
        xl, yl = px-d, py*sy
        xt, yt = px, (py+d)*sy
        xr, yr = px+d, py*sy
        xb, yb = px, (py-d)*sy
        line((xl, yl), (xt, yt))
        line((xt, yt), (xr, yr))
        line((xr, yr), (xb, yb))
        line((xb, yb), (xl, yl))
        line(((xl+xt)/2, (yl+yt)/2), ((xr+xb)/2, (yr+yb)/2))
        line(((xl+xb)/2, (yl+yb)/2), ((xr+xt)/2, (yr+yt)/2))

        bs = context.newString('Weight %0.1f' % wghtMin,
                               style=dict(font=f.path,
                                          textFill=blackColor,
                                          tracking=em(0.02),
                                          fontSize=12))
        tw, th = bs.size
        context.text(bs, ((xl+xt)/2-tw-20, (yl+yt)/2))

        bs = context.newString('Width %0.1f' % wdthMin,
                               style=dict(font=f.path,
                                          textFill=blackColor,
                                          tracking=em(0.02),
                                          fontSize=12))
        tw, th = bs.size
        context.text(bs, ((xl+xb)/2-tw-20, (yl+yb)/2))

        bs = context.newString('Width %0.1f' % wdthMax,
                               style=dict(font=f.path,
                                          textFill=blackColor,
                                          tracking=em(0.02),
                                          fontSize=12))
        context.text(bs, ((xr+xt)/2+20, (yr+yt)/2))

        bs = context.newString('Weight %0.1f' % wghtMax,
                               style=dict(font=f.path,
                                          textFill=blackColor,
                                          tracking=em(0.02),
                                          fontSize=12))
        context.text(bs, ((xb+xr)/2+20, (yb+yr)/2))

        dd = d*0.6
        stroke(0.7)
        markerSize = 16
        oval(px-(px-xl)*0.6, (py-(py-yb)*0.6-markerSize/2)*sy, (xr-xl)*0.6, (yt-yb)*0.6)

        lx, ly = px + radX*dd, sy*(py + radY*dd)

        context.fill((1, 0, 0))
        context.stroke(None)
        context.oval(lx-markerSize/2, ly-markerSize/2*sy, markerSize, markerSize*sy)

        context.stroke((1, 0, 0))
        context.fill(None)
        context.line((lx, ly), (lx, ly+20))

        for icon in icons:
            icon.scale = 0.6
        skiaIcon.draw(px-skiaIcon.w/2, py*sy, drawLabel=False)
        lightIcon.draw((xl+xt)/2-lightIcon.w/2, (yl+yt)/2, drawLabel=False)
        boldIcon.draw((xr+xb)/2-boldIcon.w/2, (yr+yb)/2, drawLabel=False)
        condIcon.draw((xl+xb)/2-condIcon.w/2, (yl+yb)/2, drawLabel=False)
        wideIcon.draw((xt+xr)/2-wideIcon.w/2, (yt+yr)/2, drawLabel=False)

        if locRadX < 0:
            wdthLoc = wdthDef + (wdthDef-wdthMin)*locRadX
        else:
            wdthLoc = wdthDef + (wdthMax-wdthDef)*locRadX
        if locRadY < 0:
            wghtLoc = wghtDef + (wghtDef-wghtMin)*locRadY
        else:
            wghtLoc = wghtDef + (wghtMax-wghtDef)*locRadY

        #wdthLoc = 1#wghtDef#locRadX
        #wghtLoc = locRadY

        bs = context.newString(('angle %0.2f rx %0.2f'
                                ' ry %0.2f wdth %0.2f'
                                ' wght %0.2f') % (angle, locRadX, locRadY,
                                                  wdthLoc, wghtLoc),
                               style=dict(font=f.path,
                                          textFill=blackColor,
                                          tracking=em(0.02),
                                          fontSize=12))
        context.text(bs, (200, 480))

        location = dict(wght=wghtLoc, wdth=wdthLoc)
        locFont = getVarFontInstance(f, location, styleName='Location', normalize=True)
        #print(locFont.info.location)
        #print(getVarLocation(f, location, normalize=False))
        """
        stroke(None)
        fill(0)
        drawGlyphPath(locFont, 'Q', lx-tw/2+20, ly+20, s=0.05, fillColor=0)
        """
        bs = context.newString('Q',
                               style=dict(font=locFont.path,
                                          textFill=blackColor,
                                          tracking=em(0.02),
                                          fontSize=80))
        tw, th = bs.size
        context.text(bs, (lx-tw/2, ly+20))

        bs = context.newString('#PageBot',
                               style=dict(font=f.path,
                                          textFill=0.5,
                                          tracking=em(0.02),
                                          fontSize=10))
        tw, th = bs.size
        context.text(bs, (W-tw-10, 10))

    saveImage('_export/SkiaPointJump.gif')
Example #19
0
def makeDocument():
    """Demo random book cover generator."""

    # 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 template
    # One page, just the cover.
    doc = Document(w=W, h=H, title='A Demo Book Cover', autoPages=1, originTop=False)

    page = doc[1] # Get the first/single page of the document.
    page.name = 'Cover'

    # Get the current view of the document. This allows setting of
    # parameters how the document is represented on output.
    view = doc.view
    view.w, view.h = W, H
    # Set view options. Full list is in elements/views/baseviews.py
    view.padding = 40 # Showing cropmarks and registration marks
                      # need >= 20 padding of the view.
    view.showRegistrationMarks = True
    view.showCropMarks = True
    view.showFrame = True
    view.showPadding = False
    view.showNameInfo = True
    view.showTextOverflowMarker = False

    context = view.context

    C1 = color(r=random()*0.2, g=random()*0.2, b=random()*0.9)

    # Make background element, filling the page color and bleed.
    colorRect1 = newRect(z=-10, name='Page area', parent=page,
                         conditions=[Top2TopSide(),
                                     Left2LeftSide(),
                                     Fit2RightSide(),
                                     Fit2BottomSide()],
                         fill=C1)
    colorRect1.bleed = BLEED
    colorRect1.solve() # Solve element position, before we can make
                       # other elements depend on position and size.

    M = BLEED + 64
    colorRect2 = newRect(z=-10, name='Frame 2', parent=colorRect1,
            conditions=[Center2Center(), Middle2Middle()],
            fill=C1.darker(0.5), # Default parameter:
                                  # 50% between background color and white
            stroke=noColor,
            w=colorRect1.w-M, h=colorRect1.h-M,
            xAlign=CENTER, yAlign=MIDDLE)

    # Make random blurb name and titles
    title = blurb.getBlurb('book_phylosophy_title')
    subTitle = blurb.getBlurb('book_pseudoscientific').capitalize()
    if random() < 0.2: # 1/5 chance to add editions text
        subTitle += '\nEdition '+blurb.getBlurb('edition')
    authorName = blurb.getBlurb('name', noTags=True)
    if random() < 0.33: # 1/3 chance for a second author name
        authorName += '\n' + blurb.getBlurb('name')

    titleStyle = dict(font=fontBold.path, fontSize=40, leading=em(1.2),
        xTextAlign=CENTER, textFill=whiteColor, hyphenate=False)
    subTitleStyle = dict(font=fontRegular.path, fontSize=32,
        xTextAlign=CENTER, textFill=(1, 1, 1, 0.5), hyphenation=False)
    authorStyle = dict(font=fontItalic.path, fontSize=24, tracking=em(0.025),
        xTextAlign=CENTER, textFill=(1, 0.5, 1,0.7))

    # Add some title (same width, different height) at the "wrongOrigin" position.
    # They will be repositioned by solving the colorConditions.
    title = context.newString(title+'\n\n', style=titleStyle)
    title += context.newString(subTitle + '\n\n', style=subTitleStyle)
    title += context.newString(authorName, style=authorStyle)
    newTextBox(title, parent=colorRect2, name='Other element',
            conditions=[Fit2Width(), Center2Center(), Top2Top()],
            xAlign=CENTER, yAlign=TOP)

    typoIllustration = context.newString('&', style=dict(font=ampersandFont.path, fontSize=300, xTextAlign=CENTER, textFill=(1, 0.5, 1,0.7)))
    newTextBox(typoIllustration, parent=page,
            conditions=[Fit2Width(), Center2Center(), Bottom2Bottom()],
            xAlign=CENTER, yAlign=TOP)

    # Evaluate again, result should now be >= 0
    score = page.evaluate()
    if score.fails: # There is new "failing" elements. Solve their layout.
        page.solve()

    return doc
Example #20
0
bookFont = findFont('Upgrade-Book')

headline = findFont('Upgrade-Medium')
headline2 = findFont('Upgrade-Regular')
headlineItalic = findFont('Upgrade-Italic')
bodyText = findFont('Proforma-Book')
bosyTextBold = findFont('Proforma-Semibold')
bodyTextItalic = findFont('Proforma-BookItalic')

headline = findFont('PageBot-Light')

styles = dict(
    h1=dict(name='h1', font=titleBold, fontSize=48),
    h2=dict(name='h2', font=titleBold, fontSize=36, uppercase=True, textFill=color(rgb=0x676A6A)),
    h3=dict(name='h3', font=headline2, fontSize=16),
    p=dict(name='p', font=bodyText, fontSize=12, leading=em(1.4)),
    b=dict(name='b', font=bosyTextBold, fontSize=12, leading=em(1.4)),
    i=dict(name='i', font=bodyTextItalic, fontSize=12, leading=em(1.4)),
    
    pnLeft=dict(name='pnLeft', font=titleBold, fontSize=pt(14), xTextAlign=LEFT),
    pnRight=dict(name='pnRIght', font=titleBold, fontSize=pt(14), xTextAlign=RIGHT),
    
    title=dict(name='title', font=titleFont, fontSize=pt(100)),
    titleBold=dict(name='titleBold', font=titleBold, fontSize=pt(62)),
    lead=dict(name='lead', font=titleBold, fontSize=pt(18)),
    function=dict(name='function', font=bookFont, fontSize=pt(11)),
    functionName=dict(name='functionName', font=titleBold, fontSize=pt(12)),
    
    designerName=dict(name='designerName', font=titleBold, fontSize=pt(36)),
    designAnswer=dict(name='designAnswer', font=titleSemibold, fontSize=pt(12)),
    typeTitleLeft=dict(name='typeTitleLeft', font=titleRegular, fontSize=pt(9), xTextAlign=LEFT,
class FontIcon:
    W = pt(30)
    H = pt(40)
    L = pt(2)
    E = pt(8)
    LABEL_RTRACKING = em(0.02)
    LABEL_RLEADING = em(1.3)

    def __init__(self, f, name=None, label=None, title=None, eId=None, c='F', s=1, line=None,
            labelFont=None, titleFont=None, x=0, y=0, show=True):
        self.f = f # Font instance
        self.labelFont = labelFont or f
        self.titleFont = titleFont, labelFont or f
        self.title = title
        self.name = name # Name below the icon
        self.label = label # Optiona second label line
        self.c = c # Character(s) in the icon.
        self.scale = s
        self.line = line or self.L
        self.x = x
        self.y = y
        self.show = show
        self.eId = eId

    def _get_w(self):
        return self.W*self.scale
    w = property(_get_w)

    def _get_ih(self):
        """Answer scaled height of the plain icon without name label."""
        return self.H*self.scale
    ih = property(_get_ih)

    def _get_h(self):
        h = self.ih
        if self.name:
            h += self.E*self.scale*1.4 # Extra vertical space to show the name.
        if self.label:
            h += self.E*self.scale*1.4 # Extra vertical space to show the name.
        if self.title:
            h += self.E*self.scale*1.4 # Extra vertical space to show the name.
        return h
    h = property(_get_h)

    def draw(self, orgX, orgY):
        if not self.show:
            return
        w = self.w # Width of the icon
        h = self.ih # Height of the icon
        e = self.E*self.scale # Ear size
        l = self.L*self.scale # Line
        x = self.x + orgX
        y = self.y + orgY

        context.newPath()
        context.moveTo((0, 0))
        context.lineTo((0, h))
        context.lineTo((w-e, h))
        context.lineTo((w, h-e))
        context.lineTo((w, 0))
        context.lineTo((0, 0))
        context.closePath()
        context.moveTo((w-e, h))
        context.lineTo((w-e, h-e))
        context.lineTo((w, h-e))

        context.save()
        context.fill(1)
        context.stroke(0)
        context.strokeWidth(self.line)
        context.translate(x, y)
        context.drawPath()

        labelSize = e
        bs = context.newString(self.c,
                               style=dict(font=self.f.path,
                                          textFill=blackColor,
                                          fontSize=h*2/3))
        tw, th = bs.size
        context.text(bs, (w/2-tw/2, h/2-th/3.2))

        if self.title:
            bs = context.newString(self.title,
                                   style=dict(font=self.labelFont.path,
                                              textFill=blackColor,
                                              tracking=self.LABEL_RTRACKING,
                                              fontSize=labelSize))
            tw, th = bs.size
            context.text(bs, (w/2-tw/2, self.ih+th/2))

        y -= upt(self.LABEL_RLEADING, base=labelSize)
        if self.name:
            bs = context.newString(self.name,
                                   style=dict(font=self.labelFont.path,
                                              textFill=blackColor,
                                              tracking=self.LABEL_RTRACKING,
                                              fontSize=labelSize))
            tw, th = bs.size
            context.text(bs, (w/2-tw/2, y))
            y -= upt(self.LABEL_RLEADING, base=labelSize)
            
        if self.label:
            bs = context.newString(self.label,
                                   style=dict(font=self.labelFont.path,
                                              textFill=blackColor,
                                              tracking=self.LABEL_RTRACKING,
                                              fontSize=labelSize))
            tw, th = bs.size
            context.text(bs, (w/2-tw/2, y))
        context.restore()
Example #22
0
class FontIcon(Element): 
    """Showing the specified font(sub variable font) in the form of an icon 
    showing optional information in different sizes and styles.
    
    >>> from pagebot.fonttoolbox.objects.font import getFont
    >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
    >>> path = getTestFontsPath() + '/google/roboto/Roboto-Regular.ttf' # We know this exists in the PageBot repository
    >>> font = getFont(path)
    >>> fi = FontIcon(font, w=120, h=160, title="Roboto Regular")
    >>> fi.title
    'Roboto Regular'
    >>> fi.size
    (120, 160, 1)

    """
    LABEL_RTRACKING = em(0.02)
    LABEL_RLEADING = em(1.3)

    def __init__(self, f, name=None, label=None, title=None, eId=None, c='F', s=1, strokeWidth=None, stroke=noColor,
            earSize=None, earLeft=True, earFill=None, cFill=0, cStroke=None, cStrokeWidth=None,
            labelFont=None, labelFontSize=None, titleFont=None, titleFontSize=None, show=True, **kwargs):
        """    
        >>> from pagebot.fonttoolbox.objects.font import getFont
        >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
        >>> from pagebot.contexts.drawbotcontext import DrawBotContext
        >>> from pagebot.elements import newRect
        >>> from pagebot.document import Document
        >>> c = DrawBotContext()
        >>> w, h = 300, 400
        >>> doc = Document(w=w, h=h, autoPages=1, padding=30, originTop=False, context=c)
        >>> page = doc[1]
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-Regular.ttf' # We know this exists in the PageBot repository
        >>> font = getFont(path)
        >>> iw, ih = w/4, h/4
        >>> x, y = w/8, h/8
        >>> fi = FontIcon(font, x=x, y=y, w=iw, h=ih, name="40k", earSize=0.3, earLeft=True, parent=page, stroke=0, strokeWidth=3)
        >>> bg = newRect(x=w/2, w=w/2, h=h/2, fill=blackColor,parent=page)
        >>> fi = FontIcon(font, x=x, y=y, w=iw, h=ih, name="40k", c="H", cFill=0.5, earSize=0.3, earLeft=True, earFill=None, fill=color(1,0,0,0.5), parent=bg, stroke=whiteColor, strokeWidth=3)
        >>> doc.export('_export/FontIconTest.pdf')
        """

        Element.__init__(self,  **kwargs)
        self.f = f # Font instance
        if title is not None:
            self.title = title or "%s %s" % (f.info.familyName, f.info.styleName) 
        self.titleFont = titleFont, labelFont or f 
        self.titleFontSize = 28
        self.labelFont = labelFont or f
        self.labelFontSize = labelFontSize or 10
        self.label = label # Optiona second label line
        self.c = c # Character(s) in the icon.
        self.cFill = cFill
        self.cStroke = cStroke
        self.cStrokeWidth = cStrokeWidth
        self.scale = s
        self.show = show
        if stroke is not None:
            self.style["stroke"] = stroke
        if strokeWidth is not None:
            self.style["strokeWidth"] = strokeWidth
        self.earSize = earSize or 0.25 # 1/4 of width
        self.earLeft = earLeft
        if earFill is None:
            earFill = self.css("fill")
        self.earFill = earFill 


    def build(self, view, origin, drawElements=True):
        """Default drawing method just drawing the frame.
        Probably will be redefined by inheriting element classes."""
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now.

        self.draw(view, p)
        if self.drawBefore is not None: # Call if defined
            self.drawBefore(self, view, p)

        if drawElements:
            # If there are child elements, recursively draw them over the pixel image.
            self.buildChildElements(view, p)

        if self.drawAfter is not None: # Call if defined
            self.drawAfter(self, view, p)

        self._restoreScale(view)
        view.drawElementInfo(self, origin) # Depends on flag 'view.showElementInfo'

    def draw(self, view, p):
        if not self.show:
            return
        w = self.w # Width of the icon
        h = self.h # Height of the icon
        e = self.earSize*w # Ear size fraction of the width

        x,y = p[0], p[1]
        c = self.context

        c.newPath()
        c.moveTo((0, 0))
        if self.earLeft: 
            c.lineTo((0, h-e))
            c.lineTo((e, h))
            c.lineTo((w, h))
            
        else:
            c.lineTo((0, h))
            c.lineTo((w-e, h))
            c.lineTo((w, h-e))
        c.lineTo((w, 0))
        c.lineTo((0, 0))
        c.closePath()
        c.save()
        c.fill(self.css("fill"))
        c.stroke(self.css("stroke"), self.css("strokeWidth"))
        c.translate(x, y)
        c.drawPath()

        c.newPath()
        if self.earLeft:
            #draw ear
            c.moveTo((e, h))
            c.lineTo((e, h-e))
            c.lineTo((0, h-e))
            c.lineTo((e, h))

        else:
            #draw ear
            c.moveTo((w-e, h))
            c.lineTo((w-e, h-e))
            c.lineTo((w, h-e))
            c.lineTo((w-e, h))
        c.closePath()
        c.fill(self.earFill)
        c.lineJoin("bevel")
        c.drawPath()

        labelSize = e
        bs = c.newString(self.c,
                               style=dict(font=self.f.path,
                                          textFill=self.cFill,
                                          textStroke=self.cStroke,
                                          textStrokeWidth=self.cStrokeWidth,
                                          fontSize=h*2/3))
        tw, th = bs.size
        c.text(bs, (w/2-tw/2, h/2-th/3.2))

        if self.title:
            bs = c.newString(self.title,
                                   style=dict(font=self.labelFont.path,
                                              textFill=blackColor,
                                              tracking=self.LABEL_RTRACKING,
                                              fontSize=labelSize))
            tw, th = bs.size
            c.text(bs, (w/2-tw/2, self.h+th/2))

        y -= upt(self.LABEL_RLEADING, base=labelSize)
        if self.name:
            bs = c.newString(self.name,
                                   style=dict(font=self.labelFont.path,
                                              textFill=blackColor,
                                              tracking=self.LABEL_RTRACKING,
                                              fontSize=labelSize))
            tw, th = bs.size
            c.text(bs, (w/2-tw/2, y))
            y -= upt(self.LABEL_RLEADING, base=labelSize)
        if self.label:
            bs = c.newString(self.label,
                                   style=dict(font=self.labelFont.path,
                                              textFill=blackColor,
                                              tracking=self.LABEL_RTRACKING,
                                              fontSize=labelSize))
            tw, th = bs.size
            c.text(bs, (w/2-tw/2, y))
        c.restore()
Example #23
0
PW = W - 2 * PADDING  # Usable padded page width
PH = H - 2 * PADDING  # Usable padded page height
CW = (PW - G) / 2  # Column width
CH = PH
# Hard coded grid, will be automatic in later examples.
GRIDX = ((CW, G), (CW, 0))
GRIDY = ((CH, 0), )
BASELINE = pt(18)

# Get the Font instances, so they can be queried for metrics.
font = findFont('Georgia')

# Defined styles
style = dict(font=font,
             fontSize=125,
             leading=em(1.1),
             textFill=0.1,
             hyphenation=False,
             paragraphBottomSpacing=em(0.2))
captionStyle = copy(style)
captionStyle['fontSize'] = pt(10)
captionStyle['leading'] = em(1)

# Make BabelString from multiple cascading styles
t = context.newString('Hkpx', style=style)  # Start with headline
# Create a new document with 1 page. Set overall size and padding.
# FIX: Float conditions only seem to work for originTop=False
doc = Document(w=W,
               h=H,
               originTop=False,
               padding=PADDING,
titleFont = findFont('Upgrade-Thin')
lightFont = findFont('Upgrade-Light')
bookFont = findFont('Upgrade-Book')

headline = findFont('Upgrade-Medium')
headline2 = findFont('Upgrade-Regular')
headlineItalic = findFont('Upgrade-Italic')
bodyText = findFont('Proforma-Book')
bosyTextBold = findFont('Proforma-Semibold')
bodyTextItalic = findFont('Proforma-BookItalic')

headline = findFont('PageBot-Light')

styles = dict(
    h1=dict(name='h1', font=titleBold, fontSize=48),
    h2=dict(name='h2', font=titleBold, fontSize=36, uppercase=True, textFill=color(rgb=0x676A6A), leading=em(0.8)),
    h3=dict(name='h3', font=bookFont, fontSize=11, leading=em(1.3)),
    p=dict(name='p', font=titleSemibold, fontSize=12, leading=em(1.3)),
    b=dict(name='b', font=bosyTextBold, fontSize=12, leading=em(1.3)),
    i=dict(name='i', font=bodyTextItalic, fontSize=12, leading=em(1.3)),
    
    pnLeft=dict(name='pnLeft', font=titleBold, fontSize=pt(14), xTextAlign=LEFT),
    pnRight=dict(name='pnRIght', font=titleBold, fontSize=pt(14), xTextAlign=RIGHT),
    
    title=dict(name='title', font=titleFont, fontSize=pt(100)),
    titleBold=dict(name='titleBold', font=titleBold, fontSize=pt(62)),
    lead=dict(name='lead', font=titleBold, fontSize=pt(18)),
    function=dict(name='function', font=bookFont, fontSize=pt(11)),
    functionName=dict(name='functionName', font=titleBold, fontSize=pt(12)),
    
    designerName=dict(name='designerName', font=titleBold, fontSize=pt(36)),
 def _get_ascender(self):
     """Returns the current font ascender as relative Em, based on the
     current font and fontSize."""
     fontSize = upt(self.fontSize)
     return em(self.s.fontAscender() / fontSize, base=fontSize)
Example #26
0
logoBackgroundColor = color(1, 1, 0)
coloredSectionColor = color(0.9)
footerBackgroundColor = color(0.8)
footerColor = blackColor

siteDescription = [
    ('index', 'PageBot Responsive Home'),
    ('content', 'PageBot Responsive Content'),
    ('page3', 'PageBot Responsive Page 3'),
    ('page4', 'PageBot Responsive Page 4'),
    ('page5', 'PageBot Responsive Page 5'),
]
styles = dict(
    body=dict(
        fill=whiteColor,
        margin=em(0),
        padding=em(3),
        fontSize=pt(12),
        leading=em(1.4),
    ),
    br=dict(leading=em(1.4)
    ),
)
def makeNavigation(header, currentPage):
    navigation = Navigation(parent=header, fill=navigationBackgroundColor)
    # TODO: Build this automatic from the content of the pages table.
    menu = TopMenu(parent=navigation)
    menuItem1 = MenuItem(parent=menu, href='index.html', label='Home', current=currentPage=='index.html')
    menuItem2 = MenuItem(parent=menu, href='content.html', label='Internal page demo', current=currentPage=='content.html')
    menuItem3 = MenuItem(parent=menu, href='page3.html', label='menu item 3', current=currentPage=='page3.html')
    menuItem4 = MenuItem(parent=menu, href='page4.html', label='menu item 4', current=currentPage=='page4.html')
 def _get_capHeight(self):
     """Returns the current font cap height as Em, based on the current font
     and fontSize."""
     fontSize = upt(self.fontSize)
     return em(self.s.fontCapHeight()/fontSize, base=fontSize)
EXPORT_TYPE = DO_MAMP

CLEAR_MAMP = False # If True, make a clean copy by removing all old files first.

NUM_CONTENT = 2 # Number of content elements on a page.
NUM_SIDES = 1 # Number of side elements next to a main content element,

# Max image size of scaled cache (used mulitplied by resolution per image type DEFAULT_RESOLUTION_FACTORS
MAX_IMAGE_WIDTH = 800 


styles = dict(
    body=dict(
        fill=whiteColor,
        ml=9, mr=0, mt=0, mb=0,
        pl=em(3), pr=em(3), pt=em(3), pb=em(3),
        fontSize=pt(12),
        leading=em(1.4),
    ),
    br=dict(leading=em(1.4)
    ),
)

def makeNavigation(doc):
    """After all pages of the site are generated, we can use the compiled page tree
    from doc to let all Navigation elements build the menu for each page.
    """
    for pages in doc.pages.values():
        for page in pages:  
            navigation = page.select('Navigation')
            if navigation is not None:
 def _get_lineHeight(self):
     """Returns the current line height, based on the current font and fontSize.
     If a lineHeight is set, this value will be returned."""
     fontSize = upt(self.fontSize)
     return em(self.s.fontLineHeight()/fontSize, base=fontSize)
Example #30
0
 def _get_paragraphSpacingBefore(self):
     fontSize = self.nsFont.pointSize()
     return em(self.nsParagraphStyle.paragraphSpacingBefore() / fontSize,
               base=fontSize)