def render(self, width, height, st, at):
        self.width = width
        self.height = height

        self.at_st_offset = at - st

        return Render(width, height)
    def render(self, width, height, st, at):

        color = self.color or self.style.color
        
        rv = Render(width, height)

        if color is None or width <= 0 or height <= 0:
            return rv

        SIZE = 10
        
        si = renpy.display.im.SolidImage(color, SIZE, SIZE)
        sr = render(si, SIZE, SIZE, st, at)

        rv.forward = Matrix2D(1.0 * SIZE / width, 0, 0, 1.0 * SIZE / height)
        rv.reverse = Matrix2D(1.0 * width / SIZE, 0, 0, 1.0 * height / SIZE)
        rv.blit(sr, (0, 0))

        return rv
Esempio n. 3
0
    def render(self, width, height, st, at):

        rv = Render(width, height)
        self.offsets = self._list_type()

        for c in self.children:
            cr = render(c, width, height, st, at)
            offset = c.place(rv, 0, 0, width, height, cr)
            self.offsets.append(offset)

        return rv
Esempio n. 4
0
    def render(self, width, height, st, at):

        color = self.color or self.style.color

        rv = Render(width, height)

        if color is None or width <= 0 or height <= 0:
            return rv

        SIZE = 10

        if width < SIZE or height < SIZE:
            tex = renpy.display.draw.solid_texture(width, height, color)
        else:
            tex = renpy.display.draw.solid_texture(SIZE, SIZE, color)
            rv.forward = Matrix2D(1.0 * SIZE / width, 0, 0, 1.0 * SIZE / height)
            rv.reverse = Matrix2D(1.0 * width / SIZE, 0, 0, 1.0 * height / SIZE)

        rv.blit(tex, (0, 0))

        return rv
Esempio n. 5
0
    def render(self, width, height, st, at):

        width = max(self.style.xminimum, width)
        height = max(self.style.yminimum, height)

        color = self.color or self.style.color

        rv = Render(width, height)

        if color is None or width <= 0 or height <= 0:
            return rv

        SIZE = 10

        if width < SIZE or height < SIZE:
            tex = renpy.display.draw.solid_texture(width, height, color)
        else:
            tex = renpy.display.draw.solid_texture(SIZE, SIZE, color)
            rv.forward = Matrix2D(1.0 * SIZE / width, 0, 0,
                                  1.0 * SIZE / height)
            rv.reverse = Matrix2D(1.0 * width / SIZE, 0, 0,
                                  1.0 * height / SIZE)

        rv.blit(tex, (0, 0))

        return rv
Esempio n. 6
0
    def render(self, width, height, st, at):
        self.width = width
        self.height = height

        return Render(width, height)
Esempio n. 7
0
File: image.py Progetto: wjl/renpy
def wrap_render(child, w, h, st, at):
    rend = render(child, w, h, st, at)
    rv = Render(rend.width, rend.height)
    rv.blit(rend, (0, 0))
    return rv
Esempio n. 8
0
def wrap_render(child, w, h, st, at):
    rend = render(child, w, h, st, at)
    rv = Render(rend.width, rend.height)
    rv.blit(rend, (0, 0))
    return rv
Esempio n. 9
0
    def render(self, width, height, st, at):

        child = self.style.child
        if child is None:
            child = self.child

        self.parent_width = width
        self.parent_height = height

        cr = render(child, width, height, st, at)
        cw, ch = cr.get_size()

        rv = Render(cw, ch)
        rv.blit(cr, (0, 0))

        self.w = cw
        self.h = ch

        position = (self.style.xpos, self.style.ypos, self.style.xanchor, self.style.yanchor, self.style.xoffset, self.style.yoffset)

        # If we don't have a position, then look for it in a drag group.
        if (self.x is None) and (self.drag_group is not None) and (self.drag_name is not None):
            if self.drag_name in self.drag_group.positions:
                dgp = self.drag_group.positions[self.drag_name]
                if len(dgp) == 3:
                    self.x, self.y, self.old_position = dgp
                else:
                    self.x, self.y = dgp
                    self.old_position = position

        if self.old_position != position:
            place = True
        elif self.x is None:
            place = True
        else:
            place = False

        # If we don't have a position, run the placement code and use
        # that to compute our placement.
        if place:
            # This is required to get get_placement to work properly.
            self.x = None

            place_x, place_y = self.place(None, 0, 0, width, height, rv)

            self.x = int(place_x)
            self.y = int(place_y)

            self.target_x = None

            self.old_position = position

        if self.target_x is None:
            self.target_x = self.x
            self.target_y = self.y
            self.target_at = at

        # Determine if we need to do the snap animation.
        if at >= self.target_at:
            self.x = self.target_x
            self.y = self.target_y
        else:
            done = (at - self.at) / (self.target_at - self.at)
            self.x = absolute(self.x + done * (self.target_x - self.x))
            self.y = absolute(self.y + done * (self.target_y - self.y))
            redraw(self, 0)

        if self.draggable or self.clicked is not None:

            fx, fy, fw, fh = self.drag_handle

            if isinstance(fx, float):
                fx = int(fx * cw)

            if isinstance(fy, float):
                fy = int(fy * ch)

            if isinstance(fw, float):
                fw = int(fw * cw)

            if isinstance(fh, float):
                fh = int(fh * ch)

            rv.add_focus(self, None, fx, fy, fw, fh, fx, fy, cr.subsurface((fx, fy, fw, fh)))

        self.last_x = self.x
        self.last_y = self.y
        self.at = at

        return rv
Esempio n. 10
0
        def draw(x0, x1, y0, y1):

            # Compute the coordinates of the left, right, top, and
            # bottom sides of the region, for both the source and
            # destination surfaces.

            # left side.
            if x0 >= 0:
                dx0 = x0
                sx0 = x0
            else:
                dx0 = dw + x0
                sx0 = sw + x0

            # right side.
            if x1 > 0:
                dx1 = x1
                sx1 = x1
            else:
                dx1 = dw + x1
                sx1 = sw + x1

            # top side.
            if y0 >= 0:
                dy0 = y0
                sy0 = y0
            else:
                dy0 = dh + y0
                sy0 = sh + y0

            # bottom side
            if y1 > 0:
                dy1 = y1
                sy1 = y1
            else:
                dy1 = dh + y1
                sy1 = sh + y1

            # Quick exit.
            if sx0 == sx1 or sy0 == sy1:
                return

            # Compute sizes.
            csw = sx1 - sx0
            csh = sy1 - sy0
            cdw = dx1 - dx0
            cdh = dy1 - dy0

            if csw <= 0 or csh <= 0 or cdh <= 0 or cdw <= 0:
                return

            # Get a subsurface.
            cr = crend.subsurface((sx0, sy0, csw, csh))

            # Scale or tile if we have to.
            if csw != cdw or csh != cdh:

                if self.tile:
                    newcr = Render(cdw, cdh)
                    newcr.xclipping = True
                    newcr.yclipping = True

                    for x in xrange(0, cdw, csw):
                        for y in xrange(0, cdh, csh):
                            newcr.blit(cr, (x, y))

                    cr = newcr

                else:

                    newcr = Render(cdw, cdh)
                    newcr.forward = Matrix2D(1.0 * csw / cdw, 0, 0,
                                             1.0 * csh / cdh)
                    newcr.reverse = Matrix2D(1.0 * cdw / csw, 0, 0,
                                             1.0 * cdh / csh)
                    newcr.blit(cr, (0, 0))

                    cr = newcr

            # Blit.
            rv.blit(cr, (dx0, dy0))
            return
Esempio n. 11
0
    def render(self, width, height, st, at):

        child = self.style.child
        if child is None:
            child = self.child

        self.parent_width = width
        self.parent_height = height

        cr = render(child, width, height, st, at)
        cw, ch = cr.get_size()

        rv = Render(cw, ch)
        rv.blit(cr, (0, 0))

        self.w = cw
        self.h = ch

        # If we don't have a position, then look for it in a drag group.
        if (self.x is None) and (self.drag_group
                                 is not None) and (self.drag_name is not None):
            if self.drag_name in self.drag_group.positions:
                self.x, self.y = self.drag_group.positions[self.drag_name]

        # If we don't have a position, run the placement code and use
        # that to compute our placement.
        if self.x is None:
            self.x, self.y = self.place(None, 0, 0, width, height, rv)
            self.x = int(self.x)
            self.y = int(self.y)

        if self.target_x is None:
            self.target_x = self.x
            self.target_y = self.y
            self.target_at = at

        # Determine if we need to do the snap animation.
        if at >= self.target_at:
            self.x = self.target_x
            self.y = self.target_y
        else:
            done = (at - self.at) / (self.target_at - self.at)
            self.x = absolute(self.x + done * (self.target_x - self.x))
            self.y = absolute(self.y + done * (self.target_y - self.y))
            redraw(self, 0)

        if self.draggable or self.clicked is not None:

            fx, fy, fw, fh = self.drag_handle

            if isinstance(fx, float):
                fx = int(fx * cw)

            if isinstance(fy, float):
                fy = int(fy * ch)

            if isinstance(fw, float):
                fw = int(fw * cw)

            if isinstance(fh, float):
                fh = int(fh * ch)

            rv.add_focus(self, None, fx, fy, fw, fh, fx, fy,
                         cr.subsurface((fx, fy, fw, fh)))

        self.last_x = self.x
        self.last_y = self.y
        self.at = at

        return rv
Esempio n. 12
0
        def draw(x0, x1, y0, y1):

            # Compute the coordinates of the left, right, top, and
            # bottom sides of the region, for both the source and
            # destination surfaces.

            # left side.
            if x0 >= 0:
                dx0 = x0
                sx0 = x0
            else:
                dx0 = dw + x0
                sx0 = sw + x0

            # right side.
            if x1 > 0:
                dx1 = x1
                sx1 = x1
            else:
                dx1 = dw + x1
                sx1 = sw + x1

            # top side.
            if y0 >= 0:
                dy0 = y0
                sy0 = y0
            else:
                dy0 = dh + y0
                sy0 = sh + y0

            # bottom side
            if y1 > 0:
                dy1 = y1
                sy1 = y1
            else:
                dy1 = dh + y1
                sy1 = sh + y1

            # Quick exit.
            if sx0 == sx1 or sy0 == sy1:
                return

            # Compute sizes.
            csw = sx1 - sx0
            csh = sy1 - sy0
            cdw = dx1 - dx0
            cdh = dy1 - dy0

            if csw <= 0 or csh <= 0 or cdh <= 0 or cdw <= 0:
                return

            # Get a subsurface.
            cr = crend.subsurface((sx0, sy0, csw, csh))

            # Scale or tile if we have to.
            if csw != cdw or csh != cdh:

                if self.tile:
                    newcr = Render(cdw, cdh)
                    newcr.xclipping = True
                    newcr.yclipping = True

                    for x in xrange(0, cdw, csw):
                        for y in xrange(0, cdh, csh):
                            newcr.blit(cr, (x, y))

                    cr = newcr

                else:

                    newcr = Render(cdw, cdh)
                    newcr.forward = Matrix2D(1.0 * csw / cdw, 0, 0, 1.0 * csh / cdh)
                    newcr.reverse = Matrix2D(1.0 * cdw / csw, 0, 0, 1.0 * cdh / csh)
                    newcr.blit(cr, (0, 0))

                    cr = newcr

            # Blit.
            rv.blit(cr, (dx0, dy0))
            return
Esempio n. 13
0
    def render(self, width, height, st, at):

        child = self.style.child
        if child is None:
            child = self.child

        self.parent_width = renpy.display.render.render_width
        self.parent_height = renpy.display.render.render_height

        cr = render(child, width, height, st, at)
        cw, ch = cr.get_size()

        rv = Render(cw, ch)
        rv.blit(cr, (0, 0))

        self.w = cw
        self.h = ch

        position = (self.style.xpos, self.style.ypos, self.style.xanchor,
                    self.style.yanchor, self.style.xoffset, self.style.yoffset)

        # If we don't have a position, then look for it in a drag group.
        if (self.x is None) and (self.drag_group
                                 is not None) and (self.drag_name is not None):
            if self.drag_name in self.drag_group.positions:
                dgp = self.drag_group.positions[self.drag_name]
                if len(dgp) == 3:
                    self.x, self.y, self.old_position = dgp
                else:
                    self.x, self.y = dgp
                    self.old_position = position

        if self.old_position != position:
            place = True
        elif self.x is None:
            place = True
        else:
            place = False

        # If we don't have a position, run the placement code and use
        # that to compute our placement.
        if place:
            # This is required to get get_placement to work properly.
            self.x = None

            place_x, place_y = self.place(None, 0, 0, width, height, rv)

            self.x = int(place_x)
            self.y = int(place_y)

            self.target_x = None

            self.old_position = position

        if self.target_x is None:
            self.target_x = self.x
            self.target_y = self.y
            self.target_at = at

        # Determine if we need to do the snap animation.
        if self.target_at_delay:
            # Snap starts now
            self.target_at = at + self.target_at_delay
            self.target_at_delay = 0
            redraw(self, 0)
        elif at >= self.target_at:
            # Snap complete
            self.x = self.target_x
            self.y = self.target_y
        else:
            # Snap in progress
            done = (at - self.at) / (self.target_at - self.at)
            self.x = absolute(self.x + done * (self.target_x - self.x))
            self.y = absolute(self.y + done * (self.target_y - self.y))
            redraw(self, 0)

        if self.draggable or self.clicked is not None:

            fx, fy, fw, fh = self.drag_handle

            if isinstance(fx, float):
                fx = int(fx * cw)

            if isinstance(fy, float):
                fy = int(fy * ch)

            if isinstance(fw, float):
                fw = int(fw * cw)

            if isinstance(fh, float):
                fh = int(fh * ch)

            mask = self.style.focus_mask

            if mask is True:
                mask = cr.subsurface((fx, fy, fw, fh))
            elif mask is not None:
                try:
                    mask = renpy.display.render.render(mask, fw, fh, st, at)
                except:
                    if callable(mask):
                        mask = mask
                    else:
                        raise Exception(
                            "Focus_mask must be None, True, a displayable, or a callable."
                        )

            if mask is not None:
                fmx = 0
                fmy = 0
            else:
                fmx = None
                fmy = None

            rv.add_focus(self, None, fx, fy, fw, fh, fmx, fmy, mask)

        self.last_x = self.x
        self.last_y = self.y
        self.at = at

        return rv
    def render(self, width, height, st, at):

        child = self.style.child
        if child is None:
            child = self.child            
        
        self.parent_width = width
        self.parent_height = height
        
        cr = render(child, width, height, st, at)
        cw, ch = cr.get_size()
        
        rv = Render(cw, ch)
        rv.blit(cr, (0, 0))

        self.w = cw
        self.h = ch

        # If we don't have a position, then look for it in a drag group.
        if (self.x is None) and (self.drag_group is not None) and (self.drag_name is not None):
            if self.drag_name in self.drag_group.positions:                
                self.x, self.y = self.drag_group.positions[self.drag_name]
        
        # If we don't have a position, run the placement code and use
        # that to compute our placement.
        if self.x is None:
            self.x, self.y = self.place(None, 0, 0, width, height, rv)
            self.x = int(self.x)
            self.y = int(self.y)

        if self.target_x is None:
            self.target_x = self.x
            self.target_y = self.y
            self.target_at = at

        # Determine if we need to do the snap animation.
        if at >= self.target_at:
            self.x = self.target_x
            self.y = self.target_y
        else:
            done = (at - self.at) / (self.target_at - self.at)
            self.x = absolute(self.x + done * (self.target_x - self.x))
            self.y = absolute(self.y + done * (self.target_y - self.y))
            redraw(self, 0)

        if self.draggable or self.clicked is not None:
            
            fx, fy, fw, fh = self.drag_handle

            if isinstance(fx, float):
                fx = int(fx * cw)

            if isinstance(fy, float):
                fy = int(fy * ch)

            if isinstance(fw, float):
                fw = int(fw * cw)

            if isinstance(fh, float):
                fh = int(fh * ch)

            rv.add_focus(self, None, fx, fy, fw, fh, fx, fy, cr.subsurface((fx, fy, fw, fh)))

        self.last_x = self.x
        self.last_y = self.y
        self.at = at
        
        return rv
Esempio n. 15
0
    def render(self, width, height, st, at):

        child = self.style.child
        if child is None:
            child = self.child

        self.parent_width = width
        self.parent_height = height

        cr = render(child, width, height, st, at)
        cw, ch = cr.get_size()

        rv = Render(cw, ch)
        rv.blit(cr, (0, 0))

        self.w = cw
        self.h = ch

        position = (self.style.xpos, self.style.ypos, self.style.xanchor, self.style.yanchor, self.style.xoffset, self.style.yoffset)

        # If we don't have a position, then look for it in a drag group.
        if (self.x is None) and (self.drag_group is not None) and (self.drag_name is not None):
            if self.drag_name in self.drag_group.positions:
                dgp = self.drag_group.positions[self.drag_name]
                if len(dgp) == 3:
                    self.x, self.y, self.old_position = dgp
                else:
                    self.x, self.y = dgp
                    self.old_position = position

        if self.old_position != position:
            place = True
        elif self.x is None:
            place = True
        else:
            place = False

        # If we don't have a position, run the placement code and use
        # that to compute our placement.
        if place:
            # This is required to get get_placement to work properly.
            self.x = None

            place_x, place_y = self.place(None, 0, 0, width, height, rv)

            self.x = int(place_x)
            self.y = int(place_y)

            self.target_x = None

            self.old_position = position

        if self.target_x is None:
            self.target_x = self.x
            self.target_y = self.y
            self.target_at = at

        # Determine if we need to do the snap animation.
        if self.target_at_delay:
            # Snap starts now
            self.target_at = at + self.target_at_delay
            self.target_at_delay = 0
            redraw(self, 0)
        elif at >= self.target_at:
            # Snap complete
            self.x = self.target_x
            self.y = self.target_y
        else:
            # Snap in progress
            done = (at - self.at) / (self.target_at - self.at)
            self.x = absolute(self.x + done * (self.target_x - self.x))
            self.y = absolute(self.y + done * (self.target_y - self.y))
            redraw(self, 0)

        if self.draggable or self.clicked is not None:

            fx, fy, fw, fh = self.drag_handle

            if isinstance(fx, float):
                fx = int(fx * cw)

            if isinstance(fy, float):
                fy = int(fy * ch)

            if isinstance(fw, float):
                fw = int(fw * cw)

            if isinstance(fh, float):
                fh = int(fh * ch)

            mask = self.style.focus_mask

            if mask is True:
                mask = cr.subsurface((fx, fy, fw, fh))
            elif mask is not None:
                try:
                    mask = renpy.display.render.render(mask, fw, fh, st, at)
                except:
                    if callable(mask):
                        mask = mask
                    else:
                        raise Exception("Focus_mask must be None, True, a displayable, or a callable.")

            if mask is not None:
                fmx = 0
                fmy = 0
            else:
                fmx = None
                fmy = None

            rv.add_focus(self, None, fx, fy, fw, fh, fmx, fmy, mask)

        self.last_x = self.x
        self.last_y = self.y
        self.at = at

        return rv
Esempio n. 16
0
        def draw(x0, x1, y0, y1):

            # Compute the coordinates of the left, right, top, and
            # bottom sides of the region, for both the source and
            # destination surfaces.

            # left side.
            if x0 >= 0:
                dx0 = x0
                sx0 = x0
            else:
                dx0 = dw + x0
                sx0 = sw + x0

            # right side.
            if x1 > 0:
                dx1 = x1
                sx1 = x1
            else:
                dx1 = dw + x1
                sx1 = sw + x1

            # top side.
            if y0 >= 0:
                dy0 = y0
                sy0 = y0
            else:
                dy0 = dh + y0
                sy0 = sh + y0

            # bottom side
            if y1 > 0:
                dy1 = y1
                sy1 = y1
            else:
                dy1 = dh + y1
                sy1 = sh + y1

            # Quick exit.
            if sx0 == sx1 or sy0 == sy1:
                return

            # Compute sizes.
            csw = sx1 - sx0
            csh = sy1 - sy0
            cdw = dx1 - dx0
            cdh = dy1 - dy0

            if csw <= 0 or csh <= 0 or cdh <= 0 or cdw <= 0:
                return

            # Get a subsurface.
            cr = crend.subsurface((sx0, sy0, csw, csh))

            # Scale or tile if we have to.
            if csw != cdw or csh != cdh:

                if self.tile:
                    ctw, cth = cdw, cdh

                    xtiles = max(1, cdw // csw + (1 if cdw % csw else 0))
                    ytiles = max(1, cdh // csh + (1 if cdh % csh else 0))

                    if cdw % csw or cdh % csh:
                        # Area is not an exact integer number of tiles

                        if self.tile == "integer":
                            if cdw % csw / float(csw) < self.tile_ratio:
                                xtiles = max(1, xtiles - 1)
                            if cdh % csh / float(csh) < self.tile_ratio:
                                ytiles = max(1, ytiles - 1)

                            # Set size of the used tiles (ready to scale)
                            ctw, cth = csw * xtiles, csh * ytiles

                    newcr = Render(ctw, cth)
                    newcr.xclipping = True
                    newcr.yclipping = True

                    for x in range(0, xtiles):
                        for y in range(0, ytiles):
                            newcr.blit(cr, (x * csw, y * csh))

                    csw, csh = ctw, cth
                    cr = newcr

                if csw != cdw or csh != cdh:
                    # Subsurface needs scaling
                    newcr = Render(cdw, cdh)
                    newcr.forward = Matrix2D(1.0 * csw / cdw, 0, 0,
                                             1.0 * csh / cdh)
                    newcr.reverse = Matrix2D(1.0 * cdw / csw, 0, 0,
                                             1.0 * cdh / csh)
                    newcr.blit(cr, (0, 0))

                    cr = newcr

            # Blit.
            rv.blit(cr, (dx0, dy0))
            return
Esempio n. 17
0
    def render(self, width, height, st, at):

        width = max(self.style.xminimum, width)
        height = max(self.style.yminimum, height)

        image = self.style.child or self.image
        crend = render(image, width, height, st, at)

        sw, sh = crend.get_size()
        sw = int(sw)
        sh = int(sh)

        dw = int(width)
        dh = int(height)

        bw = self.left + self.right
        bh = self.top + self.bottom

        xborder = min(bw, sw - 2, dw)
        if xborder and bw:
            left = self.left * xborder / bw
            right = self.right * xborder / bw
        else:
            left = 0
            right = 0

        yborder = min(bh, sh - 2, dh)
        if yborder and bh:
            top = self.top * yborder / bh
            bottom = self.bottom * yborder / bh
        else:
            top = 0
            bottom = 0

        if renpy.display.draw.info["renderer"] == "sw":
            return self.sw_render(crend, dw, dh, left, top, right, bottom)

        def draw(x0, x1, y0, y1):

            # Compute the coordinates of the left, right, top, and
            # bottom sides of the region, for both the source and
            # destination surfaces.

            # left side.
            if x0 >= 0:
                dx0 = x0
                sx0 = x0
            else:
                dx0 = dw + x0
                sx0 = sw + x0

            # right side.
            if x1 > 0:
                dx1 = x1
                sx1 = x1
            else:
                dx1 = dw + x1
                sx1 = sw + x1

            # top side.
            if y0 >= 0:
                dy0 = y0
                sy0 = y0
            else:
                dy0 = dh + y0
                sy0 = sh + y0

            # bottom side
            if y1 > 0:
                dy1 = y1
                sy1 = y1
            else:
                dy1 = dh + y1
                sy1 = sh + y1

            # Quick exit.
            if sx0 == sx1 or sy0 == sy1:
                return

            # Compute sizes.
            csw = sx1 - sx0
            csh = sy1 - sy0
            cdw = dx1 - dx0
            cdh = dy1 - dy0

            if csw <= 0 or csh <= 0 or cdh <= 0 or cdw <= 0:
                return

            # Get a subsurface.
            cr = crend.subsurface((sx0, sy0, csw, csh))

            # Scale or tile if we have to.
            if csw != cdw or csh != cdh:

                if self.tile:
                    newcr = Render(cdw, cdh)
                    newcr.xclipping = True
                    newcr.yclipping = True

                    for x in xrange(0, cdw, csw):
                        for y in xrange(0, cdh, csh):
                            newcr.blit(cr, (x, y))

                    cr = newcr

                else:

                    newcr = Render(cdw, cdh)
                    newcr.forward = Matrix2D(1.0 * csw / cdw, 0, 0,
                                             1.0 * csh / cdh)
                    newcr.reverse = Matrix2D(1.0 * cdw / csw, 0, 0,
                                             1.0 * cdh / csh)
                    newcr.blit(cr, (0, 0))

                    cr = newcr

            # Blit.
            rv.blit(cr, (dx0, dy0))
            return

        rv = Render(dw, dh)

        self.draw_pattern(draw, left, top, right, bottom)

        return rv
Esempio n. 18
0
    def render(self, width, height, st, at):

        child = self.style.child
        if child is None:
            child = self.child

        self.parent_width = width
        self.parent_height = height

        cr = render(child, width, height, st, at)
        cw, ch = cr.get_size()

        rv = Render(cw, ch)
        rv.blit(cr, (0, 0))

        self.w = cw
        self.h = ch

        position = (self.style.xpos, self.style.ypos, self.style.xanchor, self.style.yanchor, self.style.xoffset, self.style.yoffset)

        # If we don't have a position, then look for it in a drag group.
        if (self.x is None) and (self.drag_group is not None) and (self.drag_name is not None):
            if self.drag_name in self.drag_group.positions:
                dgp = self.drag_group.positions[self.drag_name]
                if len(dgp) == 3:
                    self.x, self.y, self.old_position = dgp
                else:
                    self.x, self.y = dgp
                    self.old_position = position

        if self.old_position != position:
            place = True
        elif self.x is None:
            place = True
        else:
            place = False

        # If we don't have a position, run the placement code and use
        # that to compute our placement.
        if place:
            # This is required to get get_placement to work properly.
            self.x = None

            place_x, place_y = self.place(None, 0, 0, width, height, rv)

            self.x = int(place_x)
            self.y = int(place_y)

            self.target_x = None

            self.old_position = position

        if self.target_x is None:
            self.target_x = self.x
            self.target_y = self.y
            self.target_at = at

        # Determine if we need to do the snap animation.
        if at >= self.target_at:
            self.x = self.target_x
            self.y = self.target_y
        else:
            done = (at - self.at) / (self.target_at - self.at)
            self.x = absolute(self.x + done * (self.target_x - self.x))
            self.y = absolute(self.y + done * (self.target_y - self.y))
            redraw(self, 0)

        if self.draggable or self.clicked is not None:

            fx, fy, fw, fh = self.drag_handle

            if isinstance(fx, float):
                fx = int(fx * cw)

            if isinstance(fy, float):
                fy = int(fy * ch)

            if isinstance(fw, float):
                fw = int(fw * cw)

            if isinstance(fh, float):
                fh = int(fh * ch)

            rv.add_focus(self, None, fx, fy, fw, fh, fx, fy, cr.subsurface((fx, fy, fw, fh)))

        self.last_x = self.x
        self.last_y = self.y
        self.at = at

        return rv