예제 #1
0
파일: page.py 프로젝트: oakhope/PageBot
    def build(self, view, origin=ORIGIN, **kwargs):
        """Draws all elements of this page in DrawBot. Note that this method is
        only used in case pages are drawn as element on another page. In normal
        usage, pages get drawn by PageView.build"""
        p = pointOffset(self.origin, origin)  # Ignore z-axis for now.

        view.drawPageMetaInfo(self, p, background=True)

        # If there are child elements, draw them over the text. Build child
        # elements, depending in context build implementations.
        self.buildChildElements(view, p, **kwargs)

        # Draw addition page info, such as crop-mark, registration crosses,
        # etc. if parameters are set.
        view.drawPageMetaInfo(self, p, background=False)
예제 #2
0
    def build(self, view, origin=ORIGIN, **kwargs):
        """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.
        pt, pr, pb, pl = self.padding
        self._applyRotation(view, p)
        self.buildFrame(view, p) # Draw optional frame or borders.

        # Let the view draw frame info for debugging, in case view.showFrame == True
        # and self.isPage or if self.showFrame. Mark that we are drawing background here.
        view.drawPageMetaInfoBackground(self, p)

        if self.clipPath is not None:
            # If there is a clipPath defined, use it.
            clipPath = self.clipPath
        else:
            # Otherwise use self.box as clipRect when drawing the child elements.
            clipPath = self.context.newPath()
            # move to a point
            clipPath.moveTo(upt(px+pl, py+pb))
            # line to points of the clip rect.
            clipPath.lineTo(upt(px+pl, py+pb+self.ph))
            clipPath.lineTo(upt(px+pl+self.pw, py+pr+self.ph))
            clipPath.lineTo(upt(px+pl+self.pw, py+pb))
            clipPath.lineTo(upt(px+pl, py+pb))
            # close the path
            clipPath.closePath()

        #self.context.fill((0, 1, 0))
        #self.context.drawPath(clipPath)
        self.context.save()
        # set the path as a clipping path
        #self.context.clipPath(clipPath)
        # Build the child elements. Default this is the ImageData instance, but there
        # may be other elemnents added too in any particular order.
        self.buildChildElements(view, p)
        self.context.restore()

        # Let the view draw frame info for debugging, in case view.showFrame == True
        # and self.isPage or if self.showFrame. Mark that we are drawing foreground here.
        view.drawPageMetaInfo(self, p)
        self._restoreRotation(view, p)
        self._restoreScale(view)
        view.drawElementInfo(self, origin) # Depends on flag 'view.showElementInfo'
예제 #3
0
    def build(self, view, origin=ORIGIN, **kwargs):
        """Default drawing method just drawing the frame. Probably will be
        redefined by inheriting element classes."""
        c = self.context
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        p = self._applyAlignment(p)  # Ignore z-axis for now.
        self.buildFrame(view,
                        p)  # Draw optional background fill, frame or borders.

        # Let the view draw frame info for debugging, in case view.showFrame == True
        view.drawElementFrame(self, p)
        # Draw that actual content of the element by stacked specimen rectangles.
        self.drawStacked(view, p, **kwargs)
        self._restoreScale(view)
        view.drawElementInfo(self,
                             origin)  # Depends on flag 'view.showElementInfo'
예제 #4
0
    def build_html(self, view, origin=None, drawElements=True):

        p = pointOffset(self.origin, origin)
        p = self._applyScale(p)    
        px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now.

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

        if drawElements:
            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 css flag 'showElementInfo'
예제 #5
0
    def drawMissingElementRect(self, e, origin):
        """When designing templates and pages, this will draw a filled
        rectangle on the element bounding box (if self.css('missingElementFill'
        is defined) and a cross, indicating that this element has missing
        content (as in unused image frames). Only draw if the list self.showGrid
        contains proper types of grid names.

        >>> from pagebot import getContext
        >>> context = getContext()
        >>> from pagebot.elements.element import Element
        >>> from pagebot.style import getRootStyle
        >>> from pagebot.elements.views.pageview import PageView
        >>> style = getRootStyle() # Get default values
        >>> e = Element(style=style) # Works on generic elements as well as pages.
        >>> view = PageView(context=context, style=style)
        >>> view.showMissingElement = True
        >>> view.drawMissingElementRect(e, (0, 0))
        """
        if (self.showMissingElement and e.isPage) or e.showMissingElement:
            context = self.context

            p = pointOffset(e.origin, origin)
            p = self._applyScale(e, p)
            px, py, _ = e._applyAlignment(p) # Ignore z-axis for now.

            context.saveGraphicState()
            context.setShadow(self.shadow)

            sMissingElementFill = self.css('viewMissingElementFill', noColor)
            if sMissingElementFill is not noColor:
                context.fill(sMissingElementFill)
                context.stroke(noColor)
                context.rect(px, py, self.w, self.h)
            # Draw crossed rectangle.
            context.fill(noColor)
            context.stroke(blackColor, pt(0.5))
            context.rect(px, py, self.w, self.h)
            context.newPath()
            context.moveTo((px, py))
            context.lineTo((px + self.w, py + self.h))
            context.moveTo((px + self.w, py))
            context.lineTo((px, py + self.h))
            context.drawPath()

            context.restoreGraphicState()
            e._restoreScale(self)
예제 #6
0
    def draw(self, view, origin):
        c = self.doc.context

        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)    
        px, py, _ = self._applyAlignment(p) # Ignore z-axis for now.

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

        fillColor = self.style.get('fill')
        if fillColor is not None:
            c.fill(fillColor)
        c.stroke(None)

        stepX = self.w / (self.sizeX+1)
        stepY = self.h / (self.sizeY+1)
        """Add more parametric layout behavior here."""
        for indexX in range(self.sizeX+1):
            for indexY in range(self.sizeY+1):
                ox = 30
                oy = 25
                ppx = ox + px + indexX * stepX
                ppy = oy + py + indexY * stepY
                if self.locations is not None:
                    location = choice(self.locations)
                else:
                    location = self.getRandomLocation()
                glyphPathScale = self.fontSize/self.font.info.unitsPerEm
                fillColor = self.style.get('textFill') or (0, 0, 0)
                c.drawGlyphPath(self.font.ttFont, self.glyphNames[0],
                              px, py, location, s=glyphPathScale,
                              fillColor=fillColor)
                if self.recipeAxes:
                    recipe = self.location2Recipe(location)
                    bs = c.newString(recipe, fontSize=4, fill=blackColor)
                    w, h = bs.size()
                    c.text(bs, ppx - stepX/4, ppy - 24) # Bit of hack, we need the width of the glyph here.
                    if len(self.recipeAxes) > 3:
                        recipe = self.location2Recipe(location, 3, 6)
                        bs = c.newString(recipe, fontSize=4, fill=blackColor)
                        w, h = bs.size()
                        c.text(bs, point=(ppx - stepX/4 + 30, ppy - 24)) # Bit of hack, we need the width of the glyph here.

        if self.drawAfter is not None: # Call if defined
            self.drawAfter(self, view, p)
예제 #7
0
 def build(self, view, origin=ORIGIN, **kwargs):
     c = self.context
     p = pointOffset(self.origin, origin)
     p = self._applyScale(view, p)
     px, py, _ = self._applyAlignment(p)  # Ignore z-axis for now.
     view.drawElementFrame(self, p, **kwargs)
     fillColor = self.style.get('fill')
     #fillColor = (0, 0, 0)
     #if fillColor is not None:
     #    c = self.doc.context
     #    c.setFillColor(fillColor)
     #    c.setStrokeColor(None)
     #else:
     #    fillColor = (0, 0, 0)
     glyphPathScale = self.fontSize / self.font.info.unitsPerEm
     context.drawGlyphPath(c, self.font.ttFont, self.glyphNames[0], px, py,
                           self.location, glyphPathScale, fillColor)
     self.buildChildElements(view, p)
예제 #8
0
    def build(self, view, origin=ORIGIN, **kwargs):
        """Draws the circle info-graphic, showing most info about the variable
        font as can be interpreted from the file."""
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = self._applyAlignment(p) # Ignore z-axis for now.

        # Let the view draw frame info for debugging, in case view.showFrame == True
        view.drawElementFrame(self, p)

        # Draw actual circle
        self._drawFontCircle(px, py)

        for e in self.elements:
            e.build(view, p, **kwargs)

        self._restoreScale(view)
        view.drawElementInfo(self, origin) # Depends on css flag 'showElementInfo'
예제 #9
0
    def build_drawBot(self, view, origin):
        """This method is called if the view is used as a placable element
        inside another element, such as a Page or Template. """
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now.

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

        self.drawElementFrame(view, p) # In case the view itself is used on a page.
        for page in self.elements:
            page.build(view, p)

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

        self._restoreScale(view)
예제 #10
0
    def build(self, view, origin=ORIGIN, drawElements=True):
        """Draw the image in the calculated scale. Since we need to use the
        image by scale transform, all other measure (position, lineWidth) are
        scaled back to their original proportions.

        If stroke is defined, then use that to draw a frame around the image.
        Note that the (sx, sy) is already scaled to fit the padding position
        and size."""

        context = self.context # Get current context and builder.

        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now.

        self._applyRotation(view, p)

        if self.path is None or not os.path.exists(self.path) or not self.iw or not self.ih:
            # TODO: Also show error, in case the image does not exist, to differ from empty box.
            print('Cannot display image %s' % self)
            _, _, pb, pl = self.padding
            context.stroke(0.5, 0.5)
            context.fill(0.8)
            context.rect(px+pl, py+pb, self.pw, self.ph)
        else:
            #sx = self.w / self.iw
            #sy = self.h / self.ih
            #context.scale(sx.rv, sy.rv)

            if self.imo is not None:
                self.imo.image(self.path, (0, 0), alpha=self._getAlpha())
                context.image(self.imo, p=(px, py), w=self.w, h=self.h, alpha=self._getAlpha())
            else:
                context.image(self.path, p=(px, py), w=self.w, h=self.h, alpha=self._getAlpha())
            # TODO: Draw optional (transparant) forground color?

        if drawElements:
            self.buildChildElements(view, p)

        self._restoreRotation(view, p)

        self._restoreScale(view)
        view.drawElementInfo(self, origin)
예제 #11
0
파일: pbpaths.py 프로젝트: jkim828/PageBot
    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._applyRotation(view, p)

        # No automatic frame drawing on Paths elements
        #self.buildFrame(view, p) # Draw optional frame or borders.

        # Let the view draw frame info for debugging, in case view.showFrame == True
        # and self.isPage or if self.showFrame. Mark that we are drawing background here.
        view.drawPageMetaInfo(self, p, background=True)

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

        for path in self.paths:
            # Get the style file/stroke if defined in the path. Otherwise use the settings of self.
            context = self.context
            context.fill(path.style.get('fill', self.fill))
            context.stroke(path.style.get('stroke', self.stroke),
                           path.style.get('strokeWidth', self.strokeWidth))
            context.drawPath(path, p=p, sx=self.scaleX, sy=self.scaleY)

        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)

        # Let the view draw frame info for debugging, in case view.showFrame == True
        # and self.isPage or if self.showFrame. Mark that we are drawing foreground here.
        view.drawPageMetaInfo(self, p, background=False)

        self._restoreRotation(view, p)
        self._restoreScale(view)
        view.drawElementInfo(self,
                             origin)  # Depends on flag 'view.showElementInfo'
예제 #12
0
    def build(self, view, origin=ORIGIN, drawElements=True):
        """Like "rolled pasteboard" galleys can draw themselves, if the
        Composer decides to keep them in tact, instead of select, pick & choose
        elements, until the are all part of a page. In that case the w/h must
        have been set by the Composer to fit the containing page."""
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = self._applyAlignment(p) # Ignore z-axis for now.

        # Let the view draw frame info for debugging, in case
        # view.showFrame == True
        view.drawElementFrame(self, p)

        if self.drawBefore is not None:
            self.drawBefore(self, view, p)

        self.context.fill(self.css('fill')) # Find old-paper background color
        gw, gh = self.getSize()
        self.context.rect(px, py, gw, gh)

        if drawElements:
            hook = 'build_' + self.context.b.PB_ID
            # Don't call self.buildElements, we want to track the vertical
            # positions.
            gy = 0
            for e in self.elements:
                if not e.show:
                    continue
                # @@@ Find space and do more composition
                if hasattr(e, hook):
                    getattr(e, hook)(view, (px, py + gy))
                else:
                    # No implementation for this context, call default building
                    # method for this element.
                    e.build(view, (px, py + gy))
                gy += e.h

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

        self._restoreScale(view)
        view.drawElementInfo(self, origin)
예제 #13
0
    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'
예제 #14
0
    def build(self, view, origin=ORIGIN, drawElements=True):

        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)    
        px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now.

        self.drawFrame(view, p) # Draw optional frame or borders.

        # Let the view draw frame info for debugging, in case view.showFrame == True
        view.drawElementFrame(self, p) 

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

        if drawElements:
            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 css flag 'showElementInfo'
예제 #15
0
    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.buildFrame(view, p) # Draw optional frame or borders.

        # Let the view draw frame info for debugging, in case view.showFrame == True
        view.drawElementFrame(self, p)

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

        self.drawMatrix(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'
예제 #16
0
    def drawFlowConnections(self, e, origin):
        """If rootStyle.showFlowConnections is True, then draw the flow connections
        on the page, using their stroke/width settings of the style."""

        context = self.context
        p = pointOffset(e.origin, origin)
        p = e._applyScale(self, p)
        px, py, _ = p = e._applyAlignment(p)  # Ignore z-axis for now.

        if (self.showFlowConnections and e.isPage) or e.showFlowConnections:

            fmf = 0.15  #self.css('viewFlowCurvatureFactor', 0.15)
            for startE in e.elements:
                nextE = startE.next
                if nextE is not None:
                    # For all the flow sequences found in the page, draw flow arrows at offset (ox, oy)
                    # This offset is defined by optional
                    sx = startE.right
                    sy = startE.bottom
                    nx = nextE.left
                    ny = nextE.top

                    xm = (nx + sx) / 2
                    ym = (ny + sy) / 2
                    xb1 = xm * upt(ny - sy) * fmf
                    yb1 = ym * upt(nx - sx) * fmf
                    xb2 = xm * upt(ny - sy) * fmf
                    yb2 = ym * upt(nx - sx) * fmf

                    context.fill(noColor)
                    context.stroke(color(0), 1)

                    context.newPath()
                    context.moveTo((sx, sy))
                    context.curveTo(
                        (xb1, yb1), (xb2, yb2), (nx, ny)
                    )  #((ax1+ax2)/2, (ay1+ay2)/2)) # End in middle of arrow head.
                    context.drawPath()
예제 #17
0
파일: mask.py 프로젝트: oakhope/PageBot
    def build(self, view, origin=ORIGIN, **kwargs):
        context = self.context  # Get current context and builder.
        b = context.b  # This is a bit more efficient than self.b once we got context
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p)  # Ignore z-axis for now.
        self._applyRotation(view, p)

        doDraw = False
        if self.fill not in (None, noColor):
            context.fill(self.fill)
            doDraw = True

        if self.stroke not in (None, noColor) and self.strokeWidth:
            context.stroke(self.stroke)
            context.strokeWidth(self.strokeWidth)
            doDraw = True

        if doDraw:
            context.rect(px, py, self.w, self.h)

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

        # Let the view draw frame info for debugging, in case view.showFrame ==
        # True and self.isPage or if self.showFrame. Mark that we are drawing
        # foreground here.
        view.drawPageMetaInfo(self, p)

        # Supposedly drawing outside rotation/scaling mode, so the origin of
        # the element is visible.
        view.drawElementOrigin(self, origin)

        self._restoreRotation(view, p)
        self._restoreScale(view)
        view.drawElementInfo(self,
                             origin)  # Depends on flag 'view.showElementInfo'
예제 #18
0
    def drawElementOrigin(self, e, origin):
        if not (self.showOrigin or e.showOrigin):
            return

        context = self.context
        px, py, _ = pointOffset(e.origin, origin)

        S = e.css('viewInfoOriginMarkerSize', pt(5))
        # Draw origin of the element
        fill = e.css('viewInfoOriginMarkerFill', noColor)
        stroke = e.css('viewInfoOriginMarkerStroke', blackColor)
        width = e.css('viewInfoOriginMarkerStrokeWidth', pt(0.25))
        context.fill(fill) # Transparant fill, so we can see the marker on dark backgrounds.
        context.stroke(stroke, width)
        context.oval(px-S, py-S, 2*S, 2*S)
        context.line((px-S, py), (px+S, py))
        context.line((px, py-S), (px, py+S))

        if (self.showDimensions and e.isPage) or e.showDimensions:
            bs = context.newString(e.xy, style=dict(font=self.css('viewInfoFont'),
                fontSize=self.css('viewInfoFontSize'), leading=self.css('viewInfoLeading'),
                textFill=color(0.1)))
            w, h = bs.size
            context.text(bs, (px - w/2, py + S*1.5))
예제 #19
0
    def build(self, view, origin=ORIGIN, drawElements=True):
        """Draw the oval in the current context canvas.

        >>> e = Oval(x=0, y=20, w=500, h=3)
        >>> e.xy
        (0pt, 20pt)
        >>> e.size
        (500pt, 3pt)
        """
        context = self.context # Get current context and builder.
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now.

        #self.buildFrame(view, p) # Draw optional frame or borders.

        # Let the view draw frame info for debugging, in case
        # view.showFrame == True
        view.drawElementFrame(self, p)

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

        context.fill(self.css('fill', noColor))
        context.stroke(self.css('stroke', noColor), self.css('strokeWidth'))
        context.oval(px, py, self.w, self.h)

        if drawElements:
            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)
예제 #20
0
    def draw(self, view, origin):
        c = self.doc.context

        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = self._applyAlignment(p)  # Ignore z-axis for now.

        fillColor = self.style.get('fill')
        if fillColor is not None:
            c.fill(fillColor)

        c.stroke((0.8, 0.8, 0.8), 0.5)
        c.rect(px, py, self.w, self.h)
        if len(self.dimensions) == 1:
            raise ValueError('Not supporting 1 axis now')
        if len(self.dimensions) > 2:
            raise ValueError('Not supporting >2 axis now')

        axisNames = sorted(self.dimensions.keys())
        axisX = axisNames[0]
        sizeX = self.dimensions[axisX]
        axisY = axisNames[1]
        sizeY = self.dimensions[axisY]
        stepX = self.w / (sizeX + 1)
        stepY = self.h / (sizeY + 1)
        """Add more parametric layout behavior here."""
        RANGE = 1000
        for indexX in range(sizeX + 1):
            for indexY in range(sizeY + 1):
                ox = 30
                oy = 25
                ppx = ox + px + indexX * stepX
                ppy = oy + py + indexY * stepY
                self.location[axisX] = indexX * RANGE / sizeX
                self.location[axisY] = indexY * RANGE / sizeY
                glyphPathScale = self.fontSize / self.font.info.unitsPerEm

                c.drawGlyphPath(c,
                                self.font.ttFont,
                                self.glyphNames[0],
                                ppx,
                                ppy,
                                self.location,
                                s=glyphPathScale,
                                fillColor=(0, 0, 0))

                bs = c.newString('%s %d\n%s %d' %
                                 (axisX, indexX * RANGE / sizeX, axisY,
                                  indexY * RANGE / sizeY),
                                 fontSize=6,
                                 fill=blackColor)
                w, h = bs.size()

                c.text(bs, ppx - stepX / 4, ppy - 16)
                # Bit of hack, we need the width of the glyph here.

        bs = c.newString('Other axes: %s' % self.location,
                         fontSize=6,
                         fill=blackColor)
        w, h = bs.size()
        c.text(bs, px, py - 16)
예제 #21
0
    def build(self, view, origin, drawElements=True):
        """Draw the text on position (x, y). Draw background rectangle and/or
        frame if fill and/or stroke are defined."""
        context = view.context  # Get current context

        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p)  # Ignore z-axis for now.

        self._applyRotation(view, p)

        # Let the view draw frame info for debugging, in case view.showFrame == True
        view.drawElementFrame(self, p)

        self.buildFrame(view, p)  # Draw optional background, frame or borders.

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

        # self has its own baseline drawing, derived from the text, instace of self.baselineGrid.
        self.drawBaselines(
            view, px, py,
            background=True)  # In case there is baseline at the back

        # Draw the text with horizontal and vertical alignment
        tw, th = self.bs.size
        xOffset = yOffset = 0
        if self.css('yTextAlign') == MIDDLE:
            yOffset = (self.h - self.pb - self.pt - th) / 2
        elif self.css('yTextAlign') == BOTTOM:
            yOffset = self.h - self.pb - self.pt - th
        if self.css('xTextAlign') == CENTER:
            xOffset = (self.w - self.pl - self.pr - tw) / 2
        elif self.css('xTextAlign') == RIGHT:
            xOffset = self.w - self.pl - self.pr - tw

        textShadow = self.textShadow
        if textShadow:
            context.saveGraphicState()
            context.setShadow(textShadow)

        # Set the hyphenation flag from style, as in DrawBot this is set by a global function,
        # not as FormattedString attribute.
        context.language(self.css('language', DEFAULT_LANGUAGE))
        context.hyphenation(bool(self.css('hyphenation')))
        context.textBox(
            self.bs,
            (px + self.pl + xOffset, py + self.pb - yOffset, self.pw, self.ph))

        if textShadow:
            context.restoreGraphicState()

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

        # self has its own baseline drawing, derived from the text, instace of self.baselineGrid.
        self.drawBaselines(
            view, px, py,
            background=False)  # In case there is baseline at the front

        if view.showTextOverflowMarker and self.isOverflow():
            # TODO: Make this work for FlatContext too
            self._drawOverflowMarker_drawBot(view, px, py)

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

        self._restoreRotation(view, p)
        self._restoreScale(view)
        view.drawElementInfo(self,
                             origin)  # Depends on css flag 'showElementInfo'
예제 #22
0
    def build(self, view, origin=ORIGIN, **kwargs):
        """Draws the text on position (x, y). Draws a background rectangle and
        / or frame if fill and / or stroke are defined.

        >>> from pagebot.document import Document
        >>> from pagebot.elements import *
        >>> from pagebot.contexts import getContext
        >>> from pagebot.toolbox.units import pt, em
        >>> context = getContext()
        >>> W, H = 500, 400
        >>> doc = Document(w=W, h=H, context=context)
        >>> page = doc[1]
        >>> fontSize = pt(100)
        >>> style = dict(font='PageBot-Regular', fontSize=fontSize, leading=fontSize, textFill=(1, 0, 0), xAlign=CENTER)
        >>> bs = context.newString('Hkpx\\nHkpx', style)
        >>> t = Text(bs, x=W/2, y=H/2, parent=page, showOrigin=True, fill=0.9, yAlign=MIDDLE)
        >>> l = Line(x=t.x-t.w/2, y=t.y, w=t.w, h=0, stroke=(0, 0, 0.5), parent=page)
        >>> l = Line(x=t.x-t.w/2, y=t.y+t.bs.capHeight, w=t.w, h=0, stroke=(0, 0, 0.5), parent=page)
        >>> l = Line(x=t.x-t.w/2, y=t.y+t.bs.ascender, w=t.w, h=0, stroke=(0, 0, 0.5), parent=page)
        >>> l = Line(x=t.x-t.w/2, y=t.y+t.bs.xHeight, w=t.w, h=0, stroke=(0, 0, 0.5), parent=page)
        >>> l = Line(x=t.x-t.w/2, y=t.y+t.bs.descender, w=t.w, h=0, stroke=(0, 0, 0.5), parent=page)
        >>> doc.export('_export/Text-build1.pdf')

        >>> W, H = 700, 100
        >>> doc = Document(w=W, h=H, context=context)
        >>> view = doc.view
        >>> view.showOrigin = True
        >>> view.padding = pt(30)
        >>> view.showCropMarks = True
        >>> view.showFrame = True
        >>> style = dict(font='PageBot-Regular', leading=em(1), fontSize=pt(18), textFill=(0, 0, 0.5), xAlign=CENTER)
        >>> txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit valim mecto trambor.'
        >>> bs = context.newString(txt, style) # Creates a BabelString with context reference.
        >>> bs.context is context
        True
        >>> t = Text(bs, x=W/2, y=H/2, parent=doc[1], yAlign=MIDDLE_X)
        >>> t.context is context
        True
        >>> doc.export('_export/Text-build2.pdf')
        """
        if not self.bs:
            return

        context = view.context  # Get current context

        # Stores scaled x-value first; text is already aligned.
        p = pointOffset(self.origin, origin)
        x, _, _, = self._applyScale(view, p)

        # Determines frame position.
        p = self.getPosition(view, origin)
        px, py, _ = p

        # TODO: Add Element clipping stuff here.
        # FIXME: needs some restructuring, text box width and BabelString width
        # can be different now.

        # Let the view draw frame info for debugging, in case view.showFrame ==
        # True.
        view.drawElementFrame(self, p, **kwargs)
        assert self.w, self.h
        context.fill(self.css('fill', noColor))
        context.stroke(self.css('stroke', noColor), self.css('strokeWidth'))
        context.rect(px, py, self.w, self.h)
        px1 = px + self.pl
        py1 = py - self.pt
        pw1 = self.w - self.pr
        ph1 = self.h - self.pb
        context.drawText(self.bs, (px1, py1, pw1, ph1))
        self.buildFrame(view, (px, py, self.w, self.h))

        if self.showMargin:
            view.drawMargin(self, (px, py))

        if self.showPadding:
            view.drawPadding(self, (px, py))

        self._restoreRotation(view, p)
        self._restoreScale(view)
        self.drawMeta(view, origin)
예제 #23
0
파일: pbline.py 프로젝트: jkim828/PageBot
    def build(self, view, origin=ORIGIN, drawElements=True):
        """Draw a line on the current context canvas.

        >>> from pagebot.toolbox.units import pt
        >>> from pagebot.contexts.drawbotcontext import DrawBotContext
        >>> from pagebot.document import Document
        >>> c = DrawBotContext()
        >>> w, h = pt(300, 400)
        >>> doc = Document(w=w, h=h, autoPages=1, padding=30, originTop=False, context=c)
        >>> page = doc[1]
        >>> e = Line(parent=page, x=0, y=20, w=page.w, h=0)
        >>> e.x, e.y, e.w, e.h
        (0pt, 20pt, 300pt, 0pt)
        >>> e.build(doc.getView(), pt(0, 0))
        >>> e.xy
        (0pt, 20pt)
        >>> e.size
        (300pt, 0pt)
        >>> view = doc.getView()
        >>> e.build(view, pt(0, 0))

        >>> from pagebot.contexts.flatcontext import FlatContext
        >>> from pagebot.document import Document
        >>> c = FlatContext()
        >>> doc = Document(w=w, h=h, autoPages=1, padding=30, originTop=False, context=c)
        >>> page = doc[1]
        >>> e = Line(parent=page, x=0, y=20, w=page.w, h=3)
        >>> # Allow the context to create a new document and page canvas. Normally view does it.
        >>> c.newPage(w, h)
        >>> e.build(doc.getView(), (0, 0))
        >>> e.xy
        (0pt, 20pt)
        >>> e.size3D
        (300pt, 3pt, 100pt)
        """
        context = self.context # Get current context and builder.
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now.
        s = self.css('stroke', noColor)
        w = self.css('strokeWidth')

        context.stroke(s, w)
        context.newPath()
        context.moveTo((px, py))
        context.lineTo((px + self.w, py + self.h))
        context.closePath()
        context.drawPath()

        # Let the view draw frame info for debugging, in case view.showFrame == True
        view.drawElementFrame(self, 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)
예제 #24
0
    def drawGrid(self, e, origin, background=False):
        """Draw grid of lines and/or rectangles if colors are set in the style.
        Normally origin is ORIGIN pt(0, 0, 0), but it's possible to give the grid
        a fixed offset.
        If types self.showGrid is set, display the type of grid in forground for
        (GRID_COL, GRID_ROW, GRID_SQR) and draw in background for (GRID_COL_BG,
        GRID_ROW_BG, GRID_SQR_BG)

        >>> from pagebot.contexts.platform import getContext
        >>> context = getContext()
        >>> from pagebot.elements.element import Element
        >>> from pagebot.style import getRootStyle
        >>> style = getRootStyle() # Get default values
        >>> e = Element(style=style) # Works on generic elements as well as pages.
        >>> view = PageView(context=context, style=style)
        >>> view.showGrid = [GRID_COL, GRID_ROW]
        >>> view.drawGrid(e, (0, 0))
        >>> view.showGrid = [GRID_COL_BG]
        >>> view.drawGrid(e, (0, 0), background=True)
        """
        if (self.showGrid and e.isPage):
            showGrid = self.showGrid
        elif e.showGrid:
            showGrid = e.showGrid
        else:
            return

        context = self.context

        p = pointOffset(e.origin, origin)
        p = self._applyScale(e, p)
        px, py, _ = e._applyAlignment(p)  # Ignore z-axis for now.

        # Drawing the grid as vertical lines. Check on foreground/background flags.
        if (background
                and GRID_COL_BG in showGrid) or (not background
                                                 and GRID_COL in showGrid):
            # Set color for vertical grid lines
            context.fill(noColor)
            gridStrokeColor = e.css('viewGridStrokeY', noColor)
            gridStrokeWidth = e.css('viewGridStrokeWidthY', blackColor)
            context.stroke(gridStrokeColor, gridStrokeWidth)

            gridX = e.gridX
            if gridX:
                x = px + e.pl  # Position on left padding of page/e
                y1 = py + e.pb
                y2 = y1 + e.ph
                for cw in gridX:
                    if isinstance(cw, (tuple, list)):
                        cw, gx = cw
                    else:
                        gx = 0
                    context.line((x, y1), (x, y2))
                    if gx:
                        context.line((x + cw, y1), (x + cw, y2))
                    x += cw + gx

        # Drawing the grid as horizontal lines. Check on foreground/background flags.
        if (background
                and GRID_ROW_BG in showGrid) or (not background
                                                 and GRID_ROW in showGrid):
            # Set color for vertical grid lines
            context.fill(noColor)
            gridStrokeColor = e.css('viewGridStrokeX', noColor)
            gridStrokeWidth = e.css('viewGridStrokeWidthX', blackColor)
            context.stroke(gridStrokeColor, gridStrokeWidth)

            gridY = e.gridY
            if gridY:
                x1 = px + e.pl
                x2 = x1 + e.pw
                y = py + e.pb  # Position on bottom padding of page/e
                for ch in gridY:
                    if isinstance(ch, (tuple, list)):
                        ch, gy = ch
                    else:
                        gy = 0
                    context.line((x1, y), (x2, y))
                    if gy:
                        context.line((x1, y + ch), (x2, y + ch))
                    y += ch + gy

        # Drawing the grid as rectangles. Check on foreground/background flags.
        if (background
                and GRID_SQR_BG in showGrid) or (not background
                                                 and GRID_SQR in showGrid):
            # Set color for grid rectangles
            context.fill(e.css('viewGridFill', noColor))
            context.stroke(e.css('viewGridStroke', noColor))

            gridX = e.gridX
            gridY = e.gridY
            if gridX and gridY:
                x = e.pl  # Position on right padding of page/e
                for cw in gridX:
                    if isinstance(cw, (tuple, list)):
                        cw, gx = cw
                    else:
                        gx = 0
                    y = e.pb  # Position on bottom padding of page/e
                    for ch in gridY:
                        if isinstance(ch, (tuple, list)):
                            ch, gy = ch
                        else:
                            gy = 0
                        context.rect(px + x, py + y, cw, ch)
                        y += ch + gy
                    x += cw + gx
예제 #25
0
    def _drawElementsNeedingInfo(self, e):
        b = self.b
        context = self.context
        for e, origin in self.elementsNeedingInfo.values():
            p = pointOffset(e.origin, origin)
            p = e._applyScale(self, p)
            px, py, _ = e._applyAlignment(p)  # Ignore z-axis for now.
            if (self.showElementInfo or e.isPage) or e.showElementInfo:
                # Draw box with element info.
                bs = context.newString(
                    e.getElementInfoString(),
                    style=dict(font=self.css('viewInfoFont'),
                               fontSize=self.css('viewInfoFontSize'),
                               leading=self.css('viewInfoLeading'),
                               textFill=color(0.1)))
                tw, th = bs.size
                Pd = 4  # Padding in box and shadow offset.
                tpx = px - Pd / 2  # Make info box outdent the element. Keeping shadow on the element top left corner.
                tpy = py + e.h - th - Pd

                # Tiny shadow
                context.fill(color(0.3, 0.3, 0.3, 0.5))
                context.stroke(noColor)
                context.rect(tpx + Pd / 2, tpy, tw + 2 * Pd, th + 1.5 * Pd)
                # Frame
                context.fill(self.css('viewInfoFill'))
                context.stroke(color(0.3), w=0.25)
                context.rect(tpx, tpy, tw + 2.5 * Pd, th + 1.5 * Pd)
                context.text(bs, (tpx + Pd, tpy + th))

            if (self.showDimensions or e.isPage) or e.showDimensions:
                # TODO: Make separate arrow functio and better positions
                # Draw width and height measures
                context.fill(noColor)
                context.stroke(blackColor, w=pt(0.25))
                S = self.css('viewInfoOriginMarkerSize', pt(5))
                x1, y1, x2, y2 = px + e.left, py + e.bottom, e.right, e.top

                # Horizontal measure
                context.line((x1, y1 - 0.5 * S), (x1, y1 - 3.5 * S))
                context.line((x2, y1 - 0.5 * S), (x2, y1 - 3.5 * S))
                context.line((x1, y1 - 2 * S), (x2, y1 - 2 * S))
                # Arrow heads
                context.line((x1, y1 - 2 * S), (x1 + S, y1 - 1.5 * S))
                context.line((x1, y1 - 2 * S), (x1 + S, y1 - 2.5 * S))
                context.line((x2, y1 - 2 * S), (x2 - S, y1 - 1.5 * S))
                context.line((x2, y1 - 2 * S), (x2 - S, y1 - 2.5 * S))

                bs = context.newString(
                    asFormatted(x2 - x1),
                    style=dict(font=self.css('viewInfoFont'),
                               fontSize=self.css('viewInfoFontSize'),
                               leading=self.css('viewInfoLeading'),
                               textFill=color(0.1)))
                tw, th = bs.size
                context.text(bs, ((x2 + x1) / 2 - tw / 2, y1 - 1.5 * S))

                # Vertical measure
                context.line((x2 + 0.5 * S, y1), (x2 + 3.5 * S, y1))
                context.line((x2 + 0.5 * S, y2), (x2 + 3.5 * S, y2))
                context.line((x2 + 2 * S, y1), (x2 + 2 * S, y2))
                # Arrow heads
                context.line((x2 + 2 * S, y2), (x2 + 2.5 * S, y2 - S))
                context.line((x2 + 2 * S, y2), (x2 + 1.5 * S, y2 - S))
                context.line((x2 + 2 * S, y1), (x2 + 2.5 * S, y1 + S))
                context.line((x2 + 2 * S, y1), (x2 + 1.5 * S, y1 + S))

                bs = context.newString(
                    asFormatted(y2 - y1),
                    style=dict(font=self.css('viewInfoFont'),
                               fontSize=self.css('viewInfoFontSize'),
                               leading=self.css('viewInfoLeading'),
                               textFill=0.1))
                tw, th = bs.size
                context.text(bs, (x2 + 2 * S - tw / 2, (y2 + y1) / 2))

            e._restoreScale(self)
예제 #26
0
    def build(self, view, origin, drawElements=True):
        """Draw the text on position (x, y). Draw background rectangle and/or
        frame if fill and/or stroke are defined."""
        context = view.context  # Get current context
        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p)  # Ignore z-axis for now.
        self._applyRotation(view, p)

        # Let the view draw frame info for debugging, in case view.showFrame ==
        # True.
        view.drawElementFrame(self, p)

        self.buildFrame(view, p)  # Draw optional background, frame or borders.

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

        # self has its own baseline drawing, derived from the text, instance of
        # self.baselineGrid.
        self.drawBaselines(
            view, px, py,
            background=True)  # In case there is baseline at the back

        # Draw the text with horizontal and vertical alignment.
        tw, th = self.bs.size
        xOffset = yOffset = 0
        if self.css('yTextAlign') == MIDDLE:
            yOffset = (self.h - self.pb - self.pt - th) / 2
        elif self.css('yTextAlign') == BOTTOM:
            yOffset = self.h - self.pb - self.pt - th
        if self.css('xTextAlign') == CENTER:
            xOffset = (self.w - self.pl - self.pr - tw) / 2
        elif self.css('xTextAlign') == RIGHT:
            xOffset = self.w - self.pl - self.pr - tw

        textShadow = self.textShadow
        if textShadow:
            context.saveGraphicState()
            context.setShadow(textShadow)

        # Set the hyphenation flag from style, as in DrawBot this is set by a
        # global function, not as FormattedString attribute. NOTE: textBox
        # needs it's own style dictionary FIXME: take from babel string?
        context.language(self.css('language', DEFAULT_LANGUAGE))
        h = bool(self.css('hyphenation'))
        context.hyphenation(h)
        box = clipPath = None

        if self.clipPath is not None:  # Use the elements as clip path:
            clipPath = self.clipPath
            clipPath.translate((px, py))
            context.textBox(self.bs,
                            clipPath=clipPath,
                            align=self.css('xTextAlign'))

        elif clipPath is None:
            if self.elements:  # If there are child elements, then these are used as layout for the clipping path.
                clipPath = self.childClipPath  # Construct the clip path, so we don't need to restore translate.
                if clipPath is not None:
                    clipPath.translate((self.pl, self.pb))
                clipPath.translate((self.pl, self.pb))
                context.textBox(self.bs,
                                clipPath=clipPath,
                                align=self.css('xTextAlign'))
            else:
                box = px + self.pl, py + self.pb, self.pw, self.ph
                # One of box or clipPath are now defined.
                context.textBox(self.bs, r=box, align=self.css('xTextAlign'))

        if textShadow:
            context.restoreGraphicState()

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

        # self has its own baseline drawing, derived from the text, instace of
        # self.baselineGrid.
        self.drawBaselines(
            view, px, py,
            background=False)  # In case there is baseline at the front

        if view.showTextOverflowMarker and self.isOverflow():
            # TODO: Make this work for FlatContext too
            self._drawOverflowMarker_drawBot(view, px, py)

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

        self._restoreRotation(view, p)
        self._restoreScale(view)
        view.drawElementInfo(self,
                             origin)  # Depends on css flag 'showElementInfo'
예제 #27
0
    def drawBaselines(self, e, origin, background=False):
        """Draw baseline grid if self.showBaselines is True and there is a
        baseline defined > 0. Use the color from style values viewGridStrokeX and
        viewGridStrokeWidthX to make a difference with the baselines drawn by TextBox
        with style values baselineColor and baselineWidth.
        In this method is called by an element, instead of self, the show attribute
        is a way to overwrite the setting of self.showBaselines

        >>> from pagebot.contexts.platform import getContext
        >>> context = getContext()
        >>> from pagebot.elements.element import Element
        >>> from pagebot.style import getRootStyle
        >>> style = getRootStyle() # Get default values
        >>> e = Element(style=style) # Works on generic elements as well as pages.
        >>> view = PageView(context=context, style=style)
        >>> view.showBaselines = [BASE_LINE, BASE_INDEX_LEFT, BASE_Y_LEFT]
        >>> view.drawBaselines(e, pt(0, 0))
        """
        show = e.showBaselines or self.showBaselines

        # Sets the default, in case not drawing or show is True
        if not show:
            return

        context = self.context

        p = pointOffset(e.origin, origin)
        p = self._applyScale(e, p)
        px, py, _ = e._applyAlignment(p)  # Ignore z-axis for now.

        baselineGrid = e.baselineGrid  # Get the baseline grid of this element.
        indexFontSize = max(9, min(16, baselineGrid *
                                   0.5))  # Index size depends on baseline.
        indexGutter = baselineGrid / 4  # Gutter between index marker and element padding

        startY = e.baselineGridStart
        if startY is None:
            startY = e.pt  # Otherwise use the top padding as start Y.
        oy = e.h - startY  # Assumes origin at bottom for context drawing.

        line = 0  # Line index
        baselineColor = e.css('baselineColor', color(0, 7))
        baselineWidth = e.css('baselineWidth', 0.5)

        # Format of line numbers.
        style = dict(font=e.css('viewMarkerFont'),
                     xTextAlign=RIGHT,
                     fontSize=indexFontSize,
                     stroke=noColor,
                     textFill=baselineColor)
        context.fill(noColor)
        context.stroke(baselineColor, baselineWidth)

        while oy > e.pb:  # Run until the padding of the element is reached.
            tl = tr = None
            if not background:
                if BASE_INDEX_LEFT in show:  # Shows line baseline index
                    tl = repr(line)
                elif BASE_Y_LEFT in show:  # Show vertical position marker
                    tl = repr(e.h - oy)

                if BASE_INDEX_RIGHT in show:  # Shows line baseline index
                    tr = repr(line)
                elif BASE_Y_RIGHT in show:  # Show vertical position marker
                    tr = repr(e.h - oy)

            bsl = context.newString(tl, style=style)
            bsr = context.newString(tr, style=style)

            twl, thl = bsl.size
            twr, thr = bsr.size
            if BASE_INSIDE in show:
                if tl:
                    context.text(bsl,
                                 (px + e.pl + indexGutter, py + oy - thl / 5))
                if tr:
                    context.text(bsr, (px + e.pl + e.pw - twr - indexGutter,
                                       py + oy - thr / 5))
                if (background
                        and BASE_LINE_BG in show) or (not background
                                                      and BASE_LINE in show):
                    context.line((px + e.pl + 2 * indexGutter + twl, py + oy),
                                 (px + e.pw - 2 * indexGutter - twr, py + oy))
            else:
                if tl:
                    context.text(
                        bsl,
                        (px + e.pl - twl - indexGutter, py + oy - thl / 5))
                if tr:
                    context.text(
                        bsr,
                        (px + e.pl + e.pw + indexGutter, py + oy - thr / 5))
                if (background
                        and BASE_LINE_BG in show) or (not background
                                                      and BASE_LINE in show):
                    context.line((px + e.pl, py + oy),
                                 (px + e.w - e.pr, py + oy))
            line += 1  # Increment line index.

            oy -= baselineGrid  # Next vertical line position of baseline grid.
예제 #28
0
    def build_drawBot(self, view, origin=ORIGIN, drawElements=True):
        """Draw the image in the calculated scale. Since we need to use the
        image by scale transform, all other measure (position, lineWidth) are
        scaled back to their original proportions.

        If stroke is defined, then use that to draw a frame around the image.
        Note that the (sx, sy) is already scaled to fit the padding position
        and size."""

        context = self.context # Get current context and builder.
        b = context.b # This is a bit more efficient than self.b once we got context

        p = pointOffset(self.origin, origin)
        p = self._applyScale(view, p)
        px, py, _ = p = self._applyAlignment(p) # Ignore z-axis for now.

        self._applyRotation(view, p)

        if self.path is None or not os.path.exists(self.path) or not self.iw or not self.ih:
            # TODO: Also show error, in case the image does not exist, to differ from empty box.
            print('Cannot display image %s' % self)
            # Draw missing element as cross
            xpt, ypt, wpt, hpt = upt(px, py, self.w, self.h)
            b.stroke(0.5)
            b.strokeWidth(0.5)
            b.fill(None)
            b.rect(xpt, ypt, wpt, hpt)
        else:
            context.save()
            sx = self.w / self.iw
            sy = self.h / self.ih
            context.scale(sx, sy)

            # If there is a clipRect defined, create the bezier path
            if self.clipRect is not None:
                clipRect = context.newPath()
                clX, clY, clW, clH = upt(self.clipRect)
                sclX = clX/sx
                sclY = clY/sx
                sclW = clW/sx
                sclH = clH/sy
                # move to a point
                clipRect.moveTo((sclX, sclY))
                # line to a point
                clipRect.lineTo((sclX, sclY+sclH))
                clipRect.lineTo((sclX+sclW, sclY+sclH))
                clipRect.lineTo((sclX+sclW, sclY))
                # close the path
                clipRect.closePath()
                # set the path as a clipping path
                b.clipPath(clipRect)
                # the image will be clipped inside the path
                #b.fill(0, 0, 0.5, 0.5)
                #b.drawPath(clipRect)
            elif self.clipPath is not None:
                #Otherwise if there is a clipPath, then use it.
                b.clipPath(self.clipPath)

            if self.imo is not None:
                with self.imo:
                    b.image(self.path, (0, 0), pageNumber=1, alpha=self._getAlpha())
                b.image(self.imo, upt(px/sx, py/sy), pageNumber=self.index, alpha=self._getAlpha())
            else:
                b.image(self.path, upt(px/sx, py/sy), pageNumber=self.index, alpha=self._getAlpha())
            # TODO: Draw optional (transparant) forground color?
            
            b.clipPath(None)
            context.restore()

        if drawElements:
            self.buildChildElements(view, p)

        self._restoreRotation(view, p)

        self._restoreScale(view)
        view.drawElementInfo(self, origin)