Example #1
0
def tile_is_visible(cr, tx, ty, clip_region, sparse, translation_only):
    if not sparse:
        return True

    # it is worth checking whether this tile really will be visible
    # (to speed up the L-shaped expose event during scrolling)
    # (speedup clearly visible; slowdown measurable when always executing this code)
    N = tiledsurface.N
    if translation_only:
        x, y = cr.user_to_device(tx*N, ty*N)
        bbox = (int(x), int(y), N, N)
    else:
        corners = [(tx*N, ty*N), ((tx+1)*N, ty*N), (tx*N, (ty+1)*N), ((tx+1)*N, (ty+1)*N)]
        corners = [cr.user_to_device(x_, y_) for (x_, y_) in corners]
        bbox = helpers.rotated_rectangle_bbox(corners)

    if pygtkcompat.USE_GTK3:
        c_r = gdk.Rectangle()
        c_r.x, c_r.y, c_r.width, c_r.height = clip_region
        bb_r = gdk.Rectangle()
        bb_r.x, bb_r.y, bb_r.width, bb_r.height = bbox
        intersects, isect_r = gdk.rectangle_intersect(bb_r, c_r)
        if not intersects:
            return False
    else:
        if clip_region.rect_in(bbox) == gdk.OVERLAP_RECTANGLE_OUT:
            return False

    return True
Example #2
0
    def tile_is_visible(self, tx, ty, transformation, clip_region, sparse,
                        translation_only):
        if not sparse:
            return True

        # it is worth checking whether this tile really will be visible
        # (to speed up the L-shaped expose event during scrolling)
        # (speedup clearly visible; slowdown measurable when always executing this code)
        N = tiledsurface.N
        if translation_only:
            x, y = transformation.transform_point(tx * N, ty * N)
            bbox = (int(x), int(y), N, N)
        else:
            corners = [(tx * N, ty * N), ((tx + 1) * N, ty * N),
                       (tx * N, (ty + 1) * N), ((tx + 1) * N, (ty + 1) * N)]
            corners = [
                transformation.transform_point(x_, y_) for (x_, y_) in corners
            ]
            bbox = helpers.rotated_rectangle_bbox(corners)

        c_r = gdk.Rectangle()
        c_r.x, c_r.y, c_r.width, c_r.height = clip_region
        bb_r = gdk.Rectangle()
        bb_r.x, bb_r.y, bb_r.width, bb_r.height = bbox
        intersects, isect_r = gdk.rectangle_intersect(bb_r, c_r)
        return intersects
Example #3
0
    def canvas_modified_cb(self, x, y, w, h):
        if not self.get_window():
            return

        if w == 0 and h == 0:
            # Full redraw (used when background has changed).
            #print 'full redraw'
            self.queue_draw()
            return

        # Create an expose event with the event bbox rotated/zoomed.
        corners = [(x, y), (x+w, y), (x, y+h), (x+w, y+h)]
        corners = [self.model_to_display(x, y) for (x, y) in corners]
        self.queue_draw_area(*helpers.rotated_rectangle_bbox(corners))
Example #4
0
    def canvas_modified_cb(self, x, y, w, h):
        if not self.get_window():
            return

        if w == 0 and h == 0:
            # Full redraw (used when background has changed).
            #logger.debug('Full redraw')
            self.queue_draw()
            return

        # Create an expose event with the event bbox rotated/zoomed.
        corners = [(x, y), (x + w, y), (x, y + h), (x + w, y + h)]
        corners = [self.model_to_display(x, y) for (x, y) in corners]
        self.queue_draw_area(*helpers.rotated_rectangle_bbox(corners))
Example #5
0
    def canvas_modified_cb(self, model, x, y, w, h):
        """Handles area redraw notifications from the underlying model"""

        if not self.get_window():
            return

        if w == 0 and h == 0:
            # Full redraw (used when background has changed).
            #logger.debug('Full redraw')
            self.queue_draw()
            return

        # Create an expose event with the event bbox rotated/zoomed.
        corners = [(x, y), (x+w, y), (x, y+h), (x+w, y+h)]
        corners = [self.model_to_display(x, y) for (x, y) in corners]
        self.queue_draw_area(*helpers.rotated_rectangle_bbox(corners))
Example #6
0
    def canvas_modified_cb(self, x1, y1, w, h):
        if not self.window:
            return

        if w == 0 and h == 0:
            # Full redraw (used when background has changed).
            #print 'full redraw'
            self.queue_draw()
            return

        if self.is_translation_only():
            x, y = self.model_to_display(x1, y1)
            self.queue_draw_area(int(x), int(y), w, h)
        else:
            # Create an expose event with the event bbox rotated/zoomed.
            # OPTIMIZE: This is estimated to cause at least twice as much
            #           rendering work as neccessary.
            # Transform 4 bbox corners to screen coordinates.
            corners = [(x1, y1), (x1+w-1, y1), (x1, y1+h-1), (x1+w-1, y1+h-1)]
            corners = [self.model_to_display(x, y) for (x, y) in corners]
            self.queue_draw_area(*helpers.rotated_rectangle_bbox(corners))
Example #7
0
    def _tile_is_visible(self, tx, ty, transformation, clip_region,
                         translation_only):
        """Tests whether an individual tile is visible.

        This is sometimes worth doing during rendering, but not always.
        Currently we use _render_get_clip_region()'s sparse flag to
        determine whether this is necessary. The original logic for
        this function was documented as...

        > it is worth checking whether this tile really will be visible
        > (to speed up the L-shaped expose event during scrolling)
        > (speedup clearly visible; slowdown measurable when always
        > executing this code)

        but I'm not 100% certain that GTK3 does panning redraws this
        way. So perhaps this method is uneccessary?

        """
        N = tiledsurface.N
        if translation_only:
            x, y = transformation.transform_point(tx * N, ty * N)
            bbox = (int(x), int(y), N, N)
        else:
            corners = [
                (tx * N, ty * N),
                ((tx + 1) * N, ty * N),
                (tx * N, (ty + 1) * N),
                ((tx + 1) * N, (ty + 1) * N),
            ]
            corners = [
                transformation.transform_point(x_, y_) for (x_, y_) in corners
            ]
            bbox = helpers.rotated_rectangle_bbox(corners)

        c_r = gdk.Rectangle()
        c_r.x, c_r.y, c_r.width, c_r.height = clip_region
        bb_r = gdk.Rectangle()
        bb_r.x, bb_r.y, bb_r.width, bb_r.height = bbox
        intersects, isect_r = gdk.rectangle_intersect(bb_r, c_r)
        return intersects
Example #8
0
    def tile_is_visible(self, tx, ty, transformation, clip_region, sparse, translation_only):
        if not sparse:
            return True

        # it is worth checking whether this tile really will be visible
        # (to speed up the L-shaped expose event during scrolling)
        # (speedup clearly visible; slowdown measurable when always executing this code)
        N = tiledsurface.N
        if translation_only:
            x, y = transformation.transform_point(tx*N, ty*N)
            bbox = (int(x), int(y), N, N)
        else:
            corners = [(tx*N, ty*N), ((tx+1)*N, ty*N), (tx*N, (ty+1)*N), ((tx+1)*N, (ty+1)*N)]
            corners = [transformation.transform_point(x_, y_) for (x_, y_) in corners]
            bbox = helpers.rotated_rectangle_bbox(corners)

        c_r = gdk.Rectangle()
        c_r.x, c_r.y, c_r.width, c_r.height = clip_region
        bb_r = gdk.Rectangle()
        bb_r.x, bb_r.y, bb_r.width, bb_r.height = bbox
        intersects, isect_r = gdk.rectangle_intersect(bb_r, c_r)
        return intersects
Example #9
0
    def _tile_is_visible(self, tx, ty, transformation, clip_region,
                         translation_only):
        """Tests whether an individual tile is visible.

        This is sometimes worth doing during rendering, but not always.
        Currently we use _render_get_clip_region()'s sparse flag to
        determine whether this is necessary. The original logic for
        this function was documented as...

        > it is worth checking whether this tile really will be visible
        > (to speed up the L-shaped expose event during scrolling)
        > (speedup clearly visible; slowdown measurable when always
        > executing this code)

        but I'm not 100% certain that GTK3 does panning redraws this
        way. So perhaps this method is uneccessary?

        """
        N = tiledsurface.N
        if translation_only:
            x, y = transformation.transform_point(tx*N, ty*N)
            bbox = (int(x), int(y), N, N)
        else:
            corners = [
                (tx*N, ty*N), ((tx+1)*N, ty*N),
                (tx*N, (ty+1)*N), ((tx+1)*N, (ty+1)*N),
            ]
            corners = [
                transformation.transform_point(x_, y_)
                for (x_, y_) in corners
            ]
            bbox = helpers.rotated_rectangle_bbox(corners)

        c_r = gdk.Rectangle()
        c_r.x, c_r.y, c_r.width, c_r.height = clip_region
        bb_r = gdk.Rectangle()
        bb_r.x, bb_r.y, bb_r.width, bb_r.height = bbox
        intersects, isect_r = gdk.rectangle_intersect(bb_r, c_r)
        return intersects
    def canvas_modified_cb(self, x1, y1, w, h):
        if not self.window:
            return
        
        if w == 0 and h == 0:
            # full redraw (used when background has changed)
            #print 'full redraw'
            self.queue_draw()
            return

        cr = self.get_model_coordinates_cairo_context()

        if self.is_translation_only():
            x, y = cr.user_to_device(x1, y1)
            self.queue_draw_area(int(x), int(y), w, h)
        else:
            # create an expose event with the event bbox rotated/zoomed
            # OPTIMIZE: this is estimated to cause at least twice more rendering work than neccessary
            # transform 4 bbox corners to screen coordinates
            corners = [(x1, y1), (x1+w-1, y1), (x1, y1+h-1), (x1+w-1, y1+h-1)]
            corners = [cr.user_to_device(x, y) for (x, y) in corners]
            self.queue_draw_area(*helpers.rotated_rectangle_bbox(corners))
    def canvas_modified_cb(self, x1, y1, w, h):
        if not self.window:
            return

        if w == 0 and h == 0:
            # full redraw (used when background has changed)
            #print 'full redraw'
            self.queue_draw()
            return

        cr = self.get_model_coordinates_cairo_context()

        if self.is_translation_only():
            x, y = cr.user_to_device(x1, y1)
            self.queue_draw_area(int(x), int(y), w, h)
        else:
            # create an expose event with the event bbox rotated/zoomed
            # OPTIMIZE: this is estimated to cause at least twice more rendering work than neccessary
            # transform 4 bbox corners to screen coordinates
            corners = [(x1, y1), (x1 + w - 1, y1), (x1, y1 + h - 1),
                       (x1 + w - 1, y1 + h - 1)]
            corners = [cr.user_to_device(x, y) for (x, y) in corners]
            self.queue_draw_area(*helpers.rotated_rectangle_bbox(corners))
Example #12
0
    def _tile_is_visible(self, tx, ty, transformation, clip_rect,
                         translation_only):
        """Tests whether an individual tile is visible.

        This is sometimes worth doing during rendering, but not always.
        Currently we use _render_get_clip_region()'s sparse flag to
        determine whether this is necessary. The original logic for
        this function was documented as...

        > it is worth checking whether this tile really will be visible
        > (to speed up the L-shaped expose event during scrolling)
        > (speedup clearly visible; slowdown measurable when always
        > executing this code)

        I'm not 100% certain that GTK3 does panning redraws this way,
        so perhaps this method is uneccessary for those?
        However this method is always used when rendering during
        painting, or other activities that send partial updates.

        """
        N = tiledsurface.N
        if translation_only:
            x, y = transformation.transform_point(tx*N, ty*N)
            bbox = (int(x), int(y), N, N)
        else:
            corners = [
                (tx*N, ty*N), ((tx+1)*N, ty*N),
                (tx*N, (ty+1)*N), ((tx+1)*N, (ty+1)*N),
            ]
            corners = [
                transformation.transform_point(x_, y_)
                for (x_, y_) in corners
            ]
            bbox = helpers.rotated_rectangle_bbox(corners)
        tile_rect = helpers.Rect(*bbox)
        return clip_rect.overlaps(tile_rect)
Example #13
0
    def _tile_is_visible(self, tx, ty, transformation, clip_rect,
                         translation_only):
        """Tests whether an individual tile is visible.

        This is sometimes worth doing during rendering, but not always.
        Currently we use _render_get_clip_region()'s sparse flag to
        determine whether this is necessary. The original logic for
        this function was documented as...

        > it is worth checking whether this tile really will be visible
        > (to speed up the L-shaped expose event during scrolling)
        > (speedup clearly visible; slowdown measurable when always
        > executing this code)

        I'm not 100% certain that GTK3 does panning redraws this way,
        so perhaps this method is uneccessary for those?
        However this method is always used when rendering during
        painting, or other activities that send partial updates.

        """
        N = tiledsurface.N
        if translation_only:
            x, y = transformation.transform_point(tx*N, ty*N)
            bbox = (int(x), int(y), N, N)
        else:
            corners = [
                (tx*N, ty*N), ((tx+1)*N, ty*N),
                (tx*N, (ty+1)*N), ((tx+1)*N, (ty+1)*N),
            ]
            corners = [
                transformation.transform_point(x_, y_)
                for (x_, y_) in corners
            ]
            bbox = helpers.rotated_rectangle_bbox(corners)
        tile_rect = helpers.Rect(*bbox)
        return clip_rect.overlaps(tile_rect)
Example #14
0
    def render_execute(self, cr, surface, sparse, mipmap_level, gdk_clip_region):
        translation_only = self.is_translation_only()
        model_bbox = surface.x, surface.y, surface.w, surface.h

        #print 'model bbox', model_bbox

        # not sure if it is a good idea to clip so tightly
        # has no effect right now because device_bbox is always smaller
        cr.rectangle(*model_bbox)
        cr.clip()

        layers = self.get_visible_layers()

        if self.visualize_rendering:
            surface.pixbuf.fill((int(random.random()*0xff)<<16)+0x00000000)

        tiles = surface.get_tiles()

        background = None
        if self.current_layer_solo:
            background = self.neutral_background_pixbuf
            layers = [self.doc.layer]
            # this is for hiding instead
            #layers.pop(self.doc.layer_idx)
        if self.overlay_layer:
            idx = layers.index(self.doc.layer)
            layers.insert(idx+1, self.overlay_layer)

        for tx, ty in tiles:
            if sparse:
                # it is worth checking whether this tile really will be visible
                # (to speed up the L-shaped expose event during scrolling)
                # (speedup clearly visible; slowdown measurable when always executing this code)
                N = tiledsurface.N
                if translation_only:
                    x, y = cr.user_to_device(tx*N, ty*N)
                    bbox = (int(x), int(y), N, N)
                else:
                    #corners = [(tx*N, ty*N), ((tx+1)*N-1, ty*N), (tx*N, (ty+1)*N-1), ((tx+1)*N-1, (ty+1)*N-1)]
                    # same problem as above: cairo needs to know one extra pixel for interpolation
                    corners = [(tx*N-1, ty*N-1), ((tx+1)*N, ty*N-1), (tx*N-1, (ty+1)*N), ((tx+1)*N, (ty+1)*N)]
                    corners = [cr.user_to_device(x_, y_) for (x_, y_) in corners]
                    bbox = gdk.Rectangle(*helpers.rotated_rectangle_bbox(corners))

                if gdk_clip_region.rect_in(bbox) == gdk.OVERLAP_RECTANGLE_OUT:
                    continue


            dst = surface.get_tile_memory(tx, ty)
            self.doc.blit_tile_into(dst, False, tx, ty, mipmap_level, layers, background)

        if translation_only:
            # not sure why, but using gdk directly is notably faster than the same via cairo
            x, y = cr.user_to_device(surface.x, surface.y)
            self.window.draw_pixbuf(None, surface.pixbuf, 0, 0, int(x), int(y), dither=gdk.RGB_DITHER_MAX)
        else:
            #print 'Position (screen coordinates):', cr.user_to_device(surface.x, surface.y)
            cr.set_source_pixbuf(surface.pixbuf, round(surface.x), round(surface.y))
            pattern = cr.get_source()

            # We could set interpolation mode here (eg nearest neighbour)
            #pattern.set_filter(cairo.FILTER_NEAREST)  # 1.6s
            #pattern.set_filter(cairo.FILTER_FAST)     # 2.0s
            #pattern.set_filter(cairo.FILTER_GOOD)     # 3.1s
            #pattern.set_filter(cairo.FILTER_BEST)     # 3.1s
            #pattern.set_filter(cairo.FILTER_BILINEAR) # 3.1s

            if self.scale > 3.0:
                # pixelize at high zoom-in levels
                pattern.set_filter(cairo.FILTER_NEAREST)

            cr.paint()

        if self.doc.frame_enabled:
            # Draw a overlay for all the area outside the "document area"
            cr.save()
            cr.set_source_rgba(0.25, 0.25, 0.25, 1.0)
            cr.set_operator(cairo.OPERATOR_OVER)
            mipmap_factor = 2**mipmap_level
            frame = self.doc.get_frame()
            cr.rectangle(frame[0]/mipmap_factor, frame[1]/mipmap_factor,
                            frame[2]/mipmap_factor, frame[3]/mipmap_factor)
            cr.rectangle(*model_bbox)
            cr.set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
            cr.fill()
            cr.restore()

        if self.visualize_rendering:
            # visualize painted bboxes (blue)
            cr.set_source_rgba(0, 0, random.random(), 0.4)
            cr.paint()
    def render_execute(self, cr, surface, sparse, mipmap_level,
                       gdk_clip_region):
        translation_only = self.is_translation_only()
        model_bbox = surface.x, surface.y, surface.w, surface.h

        #print 'model bbox', model_bbox

        # not sure if it is a good idea to clip so tightly
        # has no effect right now because device_bbox is always smaller
        cr.rectangle(*model_bbox)
        cr.clip()

        layers = self.get_visible_layers()

        if self.visualize_rendering:
            surface.pixbuf.fill((int(random.random() * 0xff) << 16) +
                                0x00000000)

        tiles = surface.get_tiles()

        background = None
        if self.current_layer_solo:
            background = self.neutral_background_pixbuf
            layers = [self.doc.layer]
            # this is for hiding instead
            #layers.pop(self.doc.layer_idx)
        if self.overlay_layer:
            idx = layers.index(self.doc.layer)
            layers.insert(idx + 1, self.overlay_layer)

        for tx, ty in tiles:
            if sparse:
                # it is worth checking whether this tile really will be visible
                # (to speed up the L-shaped expose event during scrolling)
                # (speedup clearly visible; slowdown measurable when always executing this code)
                N = tiledsurface.N
                if translation_only:
                    x, y = cr.user_to_device(tx * N, ty * N)
                    bbox = (int(x), int(y), N, N)
                else:
                    #corners = [(tx*N, ty*N), ((tx+1)*N-1, ty*N), (tx*N, (ty+1)*N-1), ((tx+1)*N-1, (ty+1)*N-1)]
                    # same problem as above: cairo needs to know one extra pixel for interpolation
                    corners = [(tx * N - 1, ty * N - 1),
                               ((tx + 1) * N, ty * N - 1),
                               (tx * N - 1, (ty + 1) * N),
                               ((tx + 1) * N, (ty + 1) * N)]
                    corners = [
                        cr.user_to_device(x_, y_) for (x_, y_) in corners
                    ]
                    bbox = gdk.Rectangle(
                        *helpers.rotated_rectangle_bbox(corners))

                if gdk_clip_region.rect_in(bbox) == gdk.OVERLAP_RECTANGLE_OUT:
                    continue

            dst = surface.get_tile_memory(tx, ty)
            self.doc.blit_tile_into(dst, tx, ty, mipmap_level, layers,
                                    background)

        if translation_only:
            # not sure why, but using gdk directly is notably faster than the same via cairo
            x, y = cr.user_to_device(surface.x, surface.y)
            self.window.draw_pixbuf(None,
                                    surface.pixbuf,
                                    0,
                                    0,
                                    int(x),
                                    int(y),
                                    dither=gdk.RGB_DITHER_MAX)
        else:
            #print 'Position (screen coordinates):', cr.user_to_device(surface.x, surface.y)
            cr.set_source_pixbuf(surface.pixbuf, round(surface.x),
                                 round(surface.y))
            pattern = cr.get_source()

            # We could set interpolation mode here (eg nearest neighbour)
            #pattern.set_filter(cairo.FILTER_NEAREST)  # 1.6s
            #pattern.set_filter(cairo.FILTER_FAST)     # 2.0s
            #pattern.set_filter(cairo.FILTER_GOOD)     # 3.1s
            #pattern.set_filter(cairo.FILTER_BEST)     # 3.1s
            #pattern.set_filter(cairo.FILTER_BILINEAR) # 3.1s

            if self.scale > 3.0:
                # pixelize at high zoom-in levels
                pattern.set_filter(cairo.FILTER_NEAREST)

            cr.paint()

        if self.doc.frame_enabled:
            # Draw a semi-transparent black overlay for
            # all the area outside the "document area"
            cr.save()
            cr.set_source_rgba(0, 0, 0, 0.6)
            cr.set_operator(cairo.OPERATOR_OVER)
            mipmap_factor = 2**mipmap_level
            frame = self.doc.get_frame()
            cr.rectangle(frame[0] / mipmap_factor, frame[1] / mipmap_factor,
                         frame[2] / mipmap_factor, frame[3] / mipmap_factor)
            cr.rectangle(*model_bbox)
            cr.set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
            cr.fill()
            cr.restore()

        if self.visualize_rendering:
            # visualize painted bboxes (blue)
            cr.set_source_rgba(0, 0, random.random(), 0.4)
            cr.paint()